mrcord77/beacon-hunter

GitHub: mrcord77/beacon-hunter

Stars: 8 | Forks: 0

# Beacon Hunter **Detecting Non-Periodic Structured C2 via Additive Recurrence** Beacon Hunter detects command-and-control beaconing that uses phi-compatible additive recurrence scheduling — a growing, non-periodic timing pattern where each inter-connection interval approximately equals the sum of the previous two. This family evades regularity-based detectors (RITA, AC-Hunter) by design, while remaining structurally identifiable via a two-gate recurrence test. ## Quick Start ![Pipeline](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/b16ea511d8111345.png) *Beacon Hunter two-gate pipeline: Gate 1 filters by phi-ratio clustering, Gate 2 tests additive recurrence structure.* pip install -r requirements.txt # Run on a Zeek conn.log python beacon_hunter.py /path/to/conn.log # Reproduce all paper results python run_full_evaluation.py --quick # ~2 min, skips full evidence suite python run_full_evaluation.py # ~5 min, full pipeline # Run unit tests pytest tests/ # End-to-end validation (verifies paper claims) python validate.py ## How It Works Beacon Hunter is a two-gate pipeline operating on Zeek connection logs. **Gate 1 — Ratio Test** Groups connections from the same source/destination pair and computes consecutive inter-connection interval (ICI) ratios. Passes if the mean ratio is near phi (φ = 1.618) within ±0.20 and ratio variability (CV) is below 0.50. Minimum: 5 intervals. **Gate 2 — Additive Recurrence Test** Tests whether ICI[n+2] ≈ ICI[n+1] + ICI[n] holds across all consecutive triples, using mean relative error against a 500-iteration permutation null. Passes if mean error < 0.20 and p < 0.05. This gate rejects power-law growth (residual 0.40) and exponential backoff (0.56) which pass Gate 1 by coincidence. **Classification labels** | Label | Meaning | |-------|---------| | `ADDITIVE_RECURRENCE_BEACON` | Both gates pass — phi-compatible growing-interval schedule | | `JITTERED_BEACON` | Periodic with jitter — passes ratio gate, fails recurrence | | `REGULAR_BEACON` | Constant-interval beacon | | `BACKGROUND` | No beaconing structure detected | | `INSUFFICIENT_DATA` | Fewer than 5 intervals | **Acceptance envelope:** geometric ratios in [1.45, 1.80], confirmed empirically via boundary sweep. ## Architecture beacon_hunter_github/ ├── beacon_hunter.py # CLI detector — entry point ├── detectors.py # Pure stateless gate functions (556 lines) ├── validate.py # 32-check end-to-end validation ├── run_full_evaluation.py # One-command reproduction pipeline ├── requirements.txt # Pinned dependencies ├── evidence/ │ ├── evidence_suite.py # All 6 evaluation batteries (Experiments A-J) │ ├── rita_comparison.py # RITA-style periodicity baseline + real RITA comparison │ ├── roc_and_ci.py # ROC curve (AUC=0.900) + Wilson CI │ ├── generate_figures.py # Figures 1-7 (PNG + PDF) │ └── *.json # Pre-computed results ├── data/ │ ├── pcaps/ # Ground-truth PCAPs (see Dataset Notes below) │ └── zeek/ # Zeek conn.log files ├── figures/ # fig1-fig8 PNG + PDF (sequential) ├── paper/ # Full paper with appendices A-G ├── reports/ # Beacon Hunter output reports + real RITA v5.1.2 output ├── tests/ │ └── test_detectors.py # 34 unit tests (34/34 pass) ├── tools/ │ ├── fib_beacon_client.py # Fibonacci beacon traffic generator │ ├── fib_beacon_server.py │ └── uwf_to_connlog.py # UWF-ZeekData22 parquet → Zeek conn.log converter └── archive/ # Deprecated scripts (legacy_detectors.py, old scanners) ## Evidence Pipeline | Script | Experiments | Output | |--------|-------------|--------| | `evidence/evidence_suite.py` | A (synthetic), B (lab PCAP), C (AC jitter), E (adversarial battery), F (jitter sweep), G (length sensitivity), H (null distribution), I (phi boundary), J (logistic map) | `evidence_results.json` | | `evidence/roc_and_ci.py` | G.5 (ROC, AUC=0.900), G (Wilson CI [0.992, 1.000]) | `roc_results.json` | | `evidence/rita_comparison.py` | D (RITA-style baseline comparison) | `rita_comparison_results.json` | | `evidence/generate_figures.py` | Figures 1-7 | `figures/fig*.png/pdf` | ## Dataset Notes | File | Type | Description | |------|------|-------------| | `data/pcaps/fib_beacon_validation.pcapng` | Ground truth | Lab-generated Fibonacci beacon PCAP; used in Experiment B | | `data/pcaps/jit_var_d30_j0_1h.pcap` | Ground truth | 30s constant beacon, 0% jitter, 1 hour | | `data/pcaps/jit_var_d30_j10_1h.pcap` | Ground truth | 30s beacon, 10% jitter, 1 hour | | `data/pcaps/jit_var_d30_j99_1h.pcap` | Ground truth | 30s beacon, 99% jitter (pure noise), 1 hour | | `data/zeek/delay_var_d30_j25_combined.log` | Real + injected | 2-hour enterprise Zeek conn.log with injected 30s+25%jitter beacon | | `data/zeek/delay_var_d30_j25_24h_combined.log` | Real + injected | 24-hour version of above | | `reports/rita_output_v5.1.2_24h.txt` | Real RITA output | Actual RITA v5.1.2 binary output on the 24h dataset (100 flows scored) | For UWF-ZeekData22 evaluation: download from https://datasets.uwf.edu/data/ and convert using `tools/uwf_to_connlog.py`. ## Key Results | Experiment | Result | |------------|--------| | Synthetic detection (Exp A) | 3/3 beacon classes correct, 0 FP | | Lab PCAP (Exp B) | ADDITIVE_RECURRENCE_BEACON, rec_err=0.000, p<0.002 | | Jitter sweep (Exp F) | 100% detection through 20% jitter; cliff at 30% | | Power law vs exp backoff (Exp E) | Residuals 0.40 and 0.56 > threshold 0.20; correctly rejected | | ROC AUC (Exp G.5) | 0.900; TPR=1.000 at FPR=0.071 | | Real RITA v5.1.2 on jittered beacon | 0.617 Low severity (both tools detect; different classification) | | UWF-ZeekData22 (1M flows, benign) | 0/12,083 analyzed flows flagged ARB — 0.00% FPR | | Logistic map battery (Exp J) | Pure logistic: 0% detection; phi-biased ≤20% noise: 100% | | Phi boundary sweep (Exp I) | Acceptance window [1.45, 1.80] confirmed | ## Operational Validation These results are from running Beacon Hunter against real enterprise traffic: **Real RITA v5.1.2 comparison** (`reports/rita_output_v5.1.2_24h.txt`): Both tools detect the 30-second jittered periodic beacon. RITA scores it 0.617 Low severity among 50 other Critical/High alerts. Beacon Hunter classifies it `JITTERED_BEACON`. A pure additive recurrence schedule scores below 0.35 in RITA — analytically proved in Appendix A, empirically confirmed. **UWF-ZeekData22 (1 million real enterprise connections)**: 0/12,083 analyzed flows flagged as `ADDITIVE_RECURRENCE_BEACON` on the benign week. 0/1,995 on the Recon/Discovery attack week (correct — port scans are not beaconing). All 4 injected Fibonacci beacons detected at 0–25% jitter. **24-hour enterprise Zeek background**: 1/243 analyzed flows flagged — IPv6 NDP at 34% analyst triage heuristic, marginal and protocol-attributable. ## Reproduction See [`EXPECTED_RESULTS.md`](EXPECTED_RESULTS.md) for the exact numerical outputs expected. # Quick verification of all paper claims: python validate.py # Full pipeline (generates all outputs from scratch): python run_full_evaluation.py # Expected: 32/32 validation checks pass, ROC AUC=0.900, jitter 20%=100% detection ## Limitations - No confirmed real-world malware using phi-compatible scheduling (threat model is theoretical) - False positive rate characterized on two real datasets; enterprise-scale multi-week evaluation remains future work - Detection surface is narrow by design — the detector targets one structural timing family ## Citation If you use this work, please cite the accompanying paper: [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20431555.svg)](https://doi.org/10.5281/zenodo.20431555) ## License AGPL-3.0. See `LICENSE`. Commercial licensing available through RepoSignal.io LLC.