Kernel-grade process integrity monitoring & in-memory threat detection
Detect process hollowing, DKOM rootkits, orphan-tree hijacks, syscall spikes and in-memory shellcode — from kernel telemetry to signed SIEM webhooks, with an optional enforcement engine that can kill, suspend or LSM-block a threat.
Most open-source EDR projects stop at "log the event." GhostTrace is built as a complete sensor pipeline:
kernel probes ─▶ zero-copy frames ─▶ process DAG ─▶ statistical detection ─▶ response
eBPF 64-byte Welford weighted scoring kill /
ETW ring buffers baselines ATT&CK tagging suspend /
kprobes lock-free learning mode dedup + webhooks LSM block
- Dual-platform telemetry — Linux eBPF tracepoints (
execve,mmap,mprotect,sched::fork/exit,ptrace,connect) and Windows realtime ETW kernel-process sessions (no more blind polling windows). - Statistical baselining — online Welford mean/variance per process plus shared per-binary baselines, with a configurable learning period that kills false positives during warm-up.
- Bounded by design — dirty-node scoring is O(changed) not O(all), exited nodes evict on TTL, node count is hard-capped.
- Response-ready — dry-run first enforcement engine: SIGKILL / SIGSTOP /
NtSuspendProcess, allowlists, cooldowns, and an experimental BPF LSM hook that denies anonymous executable mappings for flagged PIDs.
graph TD
subgraph Telemetry Providers
A1["Linux eBPF tracepoints<br/>execve · mmap · mprotect<br/>sched fork/exit · ptrace · connect"]
A2["C shim + inline hooks<br/>kallsyms trampolines"]
A3["Windows ETW<br/>Microsoft-Windows-Kernel-Process<br/>(Toolhelp32 poll fallback)"]
end
subgraph Ingest
B1[eBPF ringbuf readers]
B2[CShim lock-free ring]
B3[ETW realtime consumer]
end
C["64-byte frame decoder<br/>(events)"]
D["Process Graph Engine<br/>PID lineage DAG · Welford rates<br/>per-comm baselines · learning window<br/>dirty-node scoring · TTL eviction"]
E{Multi-vector anomaly<br/>evaluator}
F1["Orphan Tree<br/><i>T1134.004</i>"]
F2["Hollowing<br/><i>T1055.012</i>"]
F3["Spike / Burst<br/><i>T1055 · T1106</i>"]
F4["DKOM<br/><i>T1014</i>"]
F5["Shellcode scan<br/><i>T1620</i>"]
F6["Connect burst<br/><i>T1071</i>"]
G["Deduplicator →<br/>Enforcement Engine"]
H1[Bubbletea Ops Console]
H2["HMAC-SHA256<br/>SIEM webhooks"]
H3["JSON stream +<br/>timestamped exports"]
A1 --> B1
A2 --> B2
A3 --> B3
B1 & B2 & B3 --> C --> D --> E
E --> F1 & F2 & F3 & F4 & F5 & F6
F1 & F2 & F3 & F4 & F5 & F6 --> G
G -->|"score ≥ min"| R["⚡ Respond<br/>kill · suspend ·<br/>LSM exec-block"]
G --> H1 & H2 & H3
classDef provider fill:#0f172a,stroke:#38bdf8,stroke-width:2px,color:#e2e8f0;
classDef core fill:#111827,stroke:#34d399,stroke-width:2px,color:#e2e8f0;
classDef detect fill:#312e81,stroke:#a5b4fc,stroke-width:2px,color:#eef2ff;
classDef output fill:#1e1b4b,stroke:#fbbf24,stroke-width:2px,color:#fffbeb;
classDef respond fill:#450a0a,stroke:#f87171,stroke-width:2px,color:#fee2e2;
class A1,A2,A3,B1,B2,B3 provider;
class C,D,E core;
class F1,F2,F3,F4,F5,F6 detect;
class H1,H2,H3 output;
class R respond;
sequenceDiagram
autonumber
participant K as Kernel / OS
participant T as Probe (eBPF·ETW·shim)
participant D as Decoder
participant G as Process Graph
participant S as AVX2 Scanner
participant A as Dedup → Enforcer
participant W as TUI / Webhook
K->>T: syscall · sched · ETW record
T->>D: fixed-size binary frame
D->>G: typed event (proc/mem/net/syscall)
G->>G: mark node dirty → score only deltas
G-->>A: weighted observation merge (0–100)
A->>A: dedup window · policy check
alt score ≥ min_score
A->>K: kill / suspend / LSM block ⚡
end
A->>S: periodic anon-exec region sweep
S-->>A: signature hits (T1620)
A->>W: alert {attack[], action} → TUI feed + HMAC POST
| Domain | Capability |
|---|---|
| 🔭 Telemetry | Linux eBPF tracepoints (7 probes) · Windows realtime ETW · native kallsyms hook shim |
| 🧠 Detection | Hollowing · DKOM · orphan trees · Welford spike/burst · connect bursts · ptrace watch · AVX2 shellcode signatures |
| 🎯 Signatures | Built-ins plus custom hex patterns with ?? wildcards, hot-reloadable via SIGHUP |
| 🛡️ Response | Dry-run-first enforcer · kill / suspend (SIGSTOP, NtSuspendProcess) · allowlists & cooldowns · experimental BPF LSM exec-block |
| 📡 Delivery | HMAC-SHA256 signed webhooks · JSON stdout · timestamped exports · retro-premium ops console |
| 📊 Engineering | Dirty-node O(Δ) scoring · bounded graph memory · context-cancellable IO everywhere · cross-platform build matrix |
| Vector | Signal | Technique | Base Score | Weight |
|---|---|---|---|---|
| Process hollowing | execve followed ≤2 s by anonymous PROT_EXEC mapping (+ captured kstack) |
T1055.012 |
78 | 0.70 |
| Shellcode in memory | Meterpreter prologue, Cobalt Strike beacon, NOP-sled syscall, /bin/sh — or your own hex sigs |
T1620 |
95 | direct |
| DKOM suspicion | PID alive in telemetry but absent from /proc |
T1014 |
90 | 1.00 |
| Syscall rate spike | instantaneous rate > rolling baseline × multiplier, corroborated against per-binary mean | T1055 |
35–85 | 0.45 |
| Timing-gap burst | >100 ms silence then ≥5 syscalls <20 ms apart | T1106 |
60 | 0.50 |
| Orphaned execution | parent PID missing from live graph (PPID-spoofing artifact) | T1134.004 |
45 | 0.35 |
| Connect burst | ≥8 outbound connects inside 5 s sliding window | T1071 |
72 | 0.65 |
| ptrace attach | PTRACE_ATTACH / SEIZE / TRACEME observed |
T1055 |
65 | 0.55 |
Observations on the same tick are merged into one alert via a weighted average; severity maps through operator-configurable thresholds (default warn 30 / crit 70).
| Mode | OS | Telemetry source | Privilege | Profile |
|---|---|---|---|---|
ebpf (default) |
Linux 5.15+ | tracepoints, read-only | root / CAP_BPF |
✅ production |
windows |
Win 10+ | ETW session → Toolhelp32 fallback | Administrator | ✅ production |
hybrid |
Linux | native hooks → eBPF fallback | root | lab / research |
asm |
Linux | inline JMP trampolines | root, unrestricted |
- Go 1.24+ everywhere
- Linux: kernel 5.15+,
clang/llvmfor runtime eBPF compilation (optional — see precompiled objects) ,nasmforasmmode - Windows: PowerShell 5.1+, elevation for ETW
# Linux (native shim + AVX2 scanner)
make build # → bin/ghosttrace
# Windows
make build-windows # → bin/ghosttrace.exe# ── Linux ───────────────────────────────────────────────
sudo ./bin/ghosttrace --mode=ebpf # ops console
sudo ./bin/ghosttrace --mode=ebpf --no-tui # JSON stream for systemd/SIEM
# ── Windows (elevated shell) ────────────────────────────
.\bin\ghosttrace.exe --mode=windowsRemove the clang requirement on production sensors:
make bpf-objects # docker build → build/bpf/*.bpf.o
scp -r build/bpf sensor:/var/lib/ghosttrace/bpf/The loader resolves objects in this order — falling back to embedded-source compilation only when none are found:
$GHOSTTRACE_BPF_DIR → /var/lib/ghosttrace/bpf → ./build/bpf → runtime clang
Full annotated template lives at configs/ghosttrace.yaml.
Search order: --config flag → ./ghosttrace.yaml → ./configs/ → /etc/ghosttrace/.
scan:
patterns:
- meterpreter # built-in name
- "hex:fc 48 83 e4 ?? e8" # spaced hex with ?? wildcards
- "905050??5050" # dense implicit hexWildcards are mask-aware and anchor-optimized; exact patterns still take the
hand-written AVX2 fast path. On Linux, kill -HUP <pid> re-applies patterns,
thresholds and enforcement policy without dropping telemetry.
enforcement:
enabled: true
dry_run: true # start here — logs the action, touches nothing
action: kill # kill | suspend
min_score: 70
cooldown_seconds: 60
allow_comms: ["systemd", "sshd"]
block_exec_anon: false # BPF LSM: deny PROT_EXEC anon mmap for flagged PIDsEvery enforced alert carries its decision in the action field
(KILL, SUSPEND, DRY_RUN, BLOCK_EXEC) so your SIEM can audit responses.
Webhooks are POSTed per unique alert with an HMAC-SHA256 signature header:
{
"id": "e6a4b12c-982d-4f1a-b310-84c172f3e891",
"severity": "CRITICAL",
"type": "SHELLCODE",
"pid": 4242,
"comm": "target_process",
"detail": "matched cobalt_strike at 0x7f9a14001000",
"score": 95.0,
"attack": ["T1620"],
"action": "",
"timestamp": "2026-08-06T19:10:00Z",
"mitigations": [
"inspect /proc/4242/maps",
"consider isolating PID 4242 before termination"
]
}Verify authenticity receiver-side:
import hmac, hashlib
def verify(secret: str, body: bytes, header_sig: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header_sig)Press : or / to enter command mode:
| Command | Action |
|---|---|
help, ? |
command reference overlay |
kill <pid> |
terminate a process |
filter <text> |
radar substring filter (filter alone clears) |
pause / resume |
freeze / resume the alert stream |
export |
dump alerts → outputs/ghosttrace_<ts>.json |
clear |
wipe the telemetry feed |
quit, exit |
graceful shutdown (alerts are exported automatically) |
Global keys — TAB cycle panels · j/k scroll · p pause · e export ·
q q double-tap quit · ESC dismiss overlays.
GhostTrace/
├── cmd/ghosttrace/ # entrypoint · mode routing · reload watcher · monitors
├── internal/
│ ├── alert/ # model · severity thresholds · dedup · HMAC webhooks
│ ├── config/ # viper schema · validation · defaults
│ ├── ebpf/ # loader · object resolution · 7 probes + LSM (programs/*.c)
│ ├── enforce/ # policy engine · kill/suspend · blocker interface
│ ├── events/ # 64-byte frame codec · typed events
│ ├── graph/ # DAG · Welford baselines · dirty-node detector fusion
│ ├── hooks/ # cshim bridge · ring sizing
│ ├── ringbuf/ # pooled consumer · backoff blocking reads
│ ├── scanner/ # maps parser · masked signatures · worker pools · Windows VAD walk
│ └── windowsmon/ # ETW stream · snapshot fallback
├── cshim/ # C ABI: shared ring · kallsyms hooks
├── asm/ # AVX2 scanner · x86_64/arm64 trampolines · PMU tap
├── ui/tui/ # Bubbletea console · views (radar/feed/sparkline)
├── configs/ghosttrace.yaml # annotated production template
├── scripts/build_bpf.sh # Docker-based probe precompiler
└── docs/ # architecture notes · threat model · install guide
go test ./... # unit suites (codec, detectors, policy, signatures…)
make race # CGO race-detector run (needs gcc/clang)
make vet && make lint # static analysis
GOOS=linux go build ./... # cross-compile matrix: linux · darwin · windowsHighlights covered by tests: wildcard pattern parsing & matching, eviction TTLs, learning-window suppression, threshold wiring, enforcement allowlist / cooldown / dry-run semantics, frame codec round-trips, webhook retries.
- File-open + DNS telemetry probes
- Sigma rule export for detections
- Prometheus metrics endpoint + pprof profiling
- Fleet mode: multi-sensor aggregation server
- Container namespace awareness (cgroup → workload attribution)
Apache 2.0 — see LICENSE.