Skip to content

Barnacules/ThreatHunter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ThreatHunter

A passive, read-only Windows host threat-hunting tool for blue teams, incident responders, and security-conscious power users.

ThreatHunter sweeps your machine for the kinds of artifacts attackers leave behind — persistence entries, hidden processes, suspicious drivers, high-entropy / packed binaries, AMSI / YARA matches, beaconing network connections, Defender-tampering events, and more — and reports them as structured findings to the console, a rotating log file, JSONL, syslog, or a webhook.

It does not modify your system. It does not quarantine or kill processes. It does not open ports or beacon out. It is purely an enumeration / detection tool — the human reading the output decides what to do with what it finds.


Features

  • Persistence sweep — Run keys, Startup folders, IFEO, Winlogon, BHOs, Scheduled Tasks, Services, WMI subscriptions, screensaver hijacks, keyboard hooks
  • Hidden process detection — cross-checks the kernel process list (NtQuerySystemInformation) against psutil, EnumProcesses, and Toolhelp32 to surface rootkit-hidden PIDs
  • Driver inspection with Authenticode signature verification
  • File entropy / packer detection plus optional AMSI scanning, YARA rule matching, and VirusTotal reputation lookups
  • Real-time process monitor — watches new process creations and flags LOLBins, suspicious parent/child chains, and risky command lines
  • Network beaconing detection — flags low-jitter periodic connections (classic C2 pattern) using coefficient-of-variation on inter-arrival times
  • ETW monitoring — subscribes to Sysmon and Defender event channels (uses pywintrace if installed, falls back to wevtutil polling)
  • Defender posture check — alerts if real-time protection, tamper protection, or cloud delivery are disabled
  • Multiple output sinks — colorised console, rotating log file, JSONL, syslog (RFC 5424), and webhook (JSON POST)

Compatibility

  • OS: Windows 10 / 11 / Server 2019+ (64-bit). The tool uses many Windows-only APIs (ctypes against ntdll, psapi, winreg, WMI, ETW) and will not run on Linux or macOS.
  • Python: 3.10 or newer. (3.11+ recommended; tomllib is then in stdlib.)
  • Privileges: Best run from an elevated (Administrator) terminal for full visibility into kernel structures, system-owned processes, drivers, and ETW channels. It will run unprivileged but with reduced coverage and will warn you on startup.

Installation

# 1. Clone
git clone https://github.com/Barnacules/ThreatHunter.git
cd ThreatHunter

# 2. (Recommended) create a virtualenv
python -m venv .venv
.\.venv\Scripts\Activate.ps1

# 3. Install dependencies
pip install -r requirements.txt

Dependencies

requirements.txt pulls in:

Package Purpose
psutil Process / network enumeration
colorama Coloured console output
requests Webhook output sink + VT fallback
WMI WMI subscription / service enumeration
pywin32 Win32 API access (event log, registry, security)
yara-python YARA rule matching against scanned files
vt-py VirusTotal API client (file reputation lookups)
tomli TOML parser (only needed on Python < 3.11)
pywintrace Optional native ETW backend (falls back to wevtutil)

If a single package fails to install (e.g. you don't have a C toolchain for yara-python), ThreatHunter degrades gracefully — the corresponding detector will simply be skipped and a startup warning will tell you which capability is missing.

Notes on tricky deps

  • yara-python ships pre-built wheels for most Python/Windows combinations; if pip falls back to source, you'll need a C compiler.
  • pywintrace is optional — without it, ETW events are pulled from Windows Event Log via wevtutil polling, which is slower but works on a stock system.

VirusTotal API key (REQUIRED for VT lookups)

This is intentionally blank in the published repo. You must add your own key for file reputation lookups to work.

The repo ships a template called config.example.toml. Your real config lives in config.toml, which is .gitignored so your API key can never be committed by accident.

  1. Sign up for a free account at https://www.virustotal.com/ and grab your API key from your account profile.

  2. Copy the template:

    copy config.example.toml config.toml
  3. Open config.toml and paste your key under [virustotal]:

    [virustotal]
    api_key = "PASTE_YOUR_KEY_HERE"
  4. Save. ThreatHunter will print a startup warning if the key is empty so you know VT lookups are disabled. (If config.toml doesn't exist, the tool automatically falls back to config.example.toml so it still runs — just without VT.)

The free VT public API is rate-limited to 4 requests/min and 500/day. The tool's built-in throttle (max_per_min in config) defaults to 4 to stay inside that.


Usage

# Default: quiet console — only WARN / HIGH / CRITICAL findings + a 60s
# heartbeat. Everything (including INFO/DEBUG) goes to threathunter.log
# and threathunter.jsonl.
python threathunter.py

# Show ALL activity on the console (everything except DEBUG)
python threathunter.py --verbose

# Verbose + DEBUG-level diagnostics (firehose — useful when troubleshooting)
python threathunter.py --debug

# Custom log file path
python threathunter.py --log-file C:\logs\hunter.log

# Heartbeat every 30 seconds instead of 60
python threathunter.py --stats-interval 30

# Disable the heartbeat entirely
python threathunter.py --no-stats

# Use a different config file
python threathunter.py --config C:\configs\hunter.toml

# List the detectors that will run
python threathunter.py --list-detectors

# All options
python threathunter.py --help

Output modes at a glance

Mode Console shows Log file gets
(default) WARN, HIGH, ALERT, CRITICAL + heartbeat lines Everything
-v All severity levels except DEBUG Everything
-d Everything including DEBUG Everything

The default mode is intentionally calm: if the tool is healthy and your machine is clean, you'll see only the heartbeat ticking by once a minute. Anything noisier than that is something you should look at.

The 60-second heartbeat

Every minute (configurable) the tool prints a one-line status update:

[2026-05-15 01:46:13.290] HEARTBEAT: heartbeat — uptime=60s files=128 procs=412 conns=87 detectors=13 findings=2 (HIGH=2)

That tells you it's still alive and how much work it has done since startup — files scanned, processes inspected, network connections checked, detectors run, and findings broken down by severity.

Stopping it

Press ESC in the console window, or Ctrl-C.


Configuration

config.toml controls scan intervals, paths to scan, allowlists, output sinks, and which detectors are enabled. The defaults are sensible for most desktops/workstations — read through the file's comments to tune it for your environment.

Output sinks live under [output]:

  • console = true/false
  • jsonl_path = "threathunter.jsonl"
  • syslog_host, syslog_port, syslog_proto
  • webhook_url

Beacon detection: noise reduction & scoring

Periodic-connection ("beaconing") detectors are notorious for false positives — browsers, OneDrive, push services, telemetry, and Windows itself all beacon. ThreatHunter's beacon detector uses a layered approach to keep the signal high:

1. Process allowlist ([beaconing] process_allowlist)

A list of process names that are expected to beacon (svchost, browsers, OneDrive, Teams, MsMpEng, etc.). Detected beacons from these processes are demoted to LOW severity — invisible in quiet console mode, but still written to the log file and JSONL so you can audit what was suppressed.

2. CIDR allowlist ([beaconing] cidr_allowlist)

Bundles well-known cloud / vendor IP ranges (Microsoft, Cloudflare, Akamai, Apple, AWS, Google). Beacons whose remote IP falls in these ranges are demoted the same way.

3. Tightened triggers ([network])

  • beaconing_min_samples = 20 — require ≥ 20 connections before evaluating
  • beaconing_min_duration_s = 300 — require ≥ 5 min of continuous beaconing
  • beaconing_interval_threshold = 0.05 — coefficient-of-variation threshold

This kills the burst-then-quiet patterns of legitimate apps.

4. Suspicion scoring ([beaconing.score])

When a connection survives the allowlists and triggers, it is scored on six independent signals (weights configurable):

Signal Default weight Source
unsigned_binary 30 Authenticode signature fails
suspicious_path 25 exe under %AppData%/%Temp%/%ProgramData%
unknown_asn 20 no PTR record AND not in cidr_allowlist
nonstandard_port 15 raddr port not in benign_ports
very_low_jitter 15 CV < 0.02 (extremely rigid timing)
long_sustained 10 sustained > 1 hour with consistent timing

The total score (0–100) maps to severity via [beaconing.severity]:

Score range Severity Visible in quiet mode?
0 – 29 LOW no (logged only)
30 – 59 MEDIUM yes
60 – 79 HIGH yes
80 – 100 CRITICAL yes

ASN lookups are optional — they require pip install ipwhois. Without ipwhois, the unknown_asn signal still triggers based on reverse-DNS alone (which is always available via the stdlib). All lookups are cached and only executed when an alert is otherwise about to fire, so this stays cheap.

Each beacon finding now includes the breakdown of which signals contributed to its score, so you can tell at a glance why it triggered.


Troubleshooting

  • "Running without admin" — re-launch from an elevated PowerShell / cmd.exe to enable kernel-level checks and ETW.
  • "YARA not available"pip install yara-python. On Windows, the prebuilt wheel usually works; if you hit a build error, install the MSVC C++ Build Tools or use a Python version with a published wheel.
  • "VirusTotal API key not set" — see the VT section above.
  • Lots of HIGH findings on first run — that's expected. ThreatHunter is surfacing everything notable; many entries will be legitimate software you installed (vendor autorun entries, signed drivers, etc.). Triage once, then add benign items to the allowlists in config.toml.

Contributing

Issues and PRs welcome. Please:

  1. Keep the tool read-only — no write/modify/kill primitives.
  2. Add detectors as their own class deriving from Detector and register them in run_initial_scan() (or as a background Monitor thread).
  3. New severity levels go through Detector.emit() so dedup, JSONL, syslog, webhook, and the stats counter stay consistent.

License

MIT — see LICENSE (add your preferred license file if you fork).


Disclaimer

ThreatHunter is a detection tool. It surfaces suspicious artifacts; it does not decide whether they are malicious or remediate them. Use the output to inform investigation by a qualified responder. The authors are not responsible for actions taken (or not taken) based on its output.

About

Passive, read-only Windows host threat-hunting tool: persistence sweep, hidden-process detection, AMSI/YARA scanning, network beaconing detection, ETW monitoring.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages