8 attack patterns in 9 bits. Kernel-level kill chain detection using syscall bitmasks and eBPF.
Each syscall category maps to a bit flag. As a process executes syscalls, flags accumulate per PID. When the accumulated flags match a known attack pattern, we have a detection.
Bit 0: CHAIN_SOCKET — connect/socket (outbound)
Bit 1: CHAIN_DUP_STDIN — dup2(fd, 0)
Bit 2: CHAIN_DUP_STDOUT — dup2(fd, 1)
Bit 3: CHAIN_DUP_STDERR — dup2(fd, 2)
Bit 4: CHAIN_BIND — bind
Bit 5: CHAIN_LISTEN — listen
Bit 6: CHAIN_PTRACE — ptrace
Bit 7: CHAIN_MPROTECT — mprotect(RWX)
Bit 8: CHAIN_SENSITIVE_READ — openat on sensitive path
| Pattern | Constant | Bits | MITRE ATT&CK |
|---|---|---|---|
| Reverse Shell | PATTERN_REVERSE_SHELL |
socket + dup_stdin + dup_stdout | T1059 |
| Bind Shell | PATTERN_BIND_SHELL |
bind + listen + dup_stdin + dup_stdout | T1059 |
| Code Injection | PATTERN_CODE_INJECT |
ptrace + mprotect(RWX) | T1055 |
| Exploit → Shell | PATTERN_EXPLOIT_SHELL |
mprotect(RWX) + dup_stdin + dup_stdout | T1203 |
| Inject → Shell | PATTERN_INJECT_SHELL |
ptrace + dup_stdin | T1055 |
| Exploit → C2 | PATTERN_EXPLOIT_C2 |
mprotect(RWX) + socket | T1071 |
| Full Exploit | PATTERN_FULL_EXPLOIT |
mprotect(RWX) + ptrace + socket | T1203 + T1055 |
| Data Exfiltration | PATTERN_DATA_EXFIL |
sensitive_read + socket | T1041 |
A pattern matches when all of its required bits are present in a PID's accumulated bitmask. Multiple patterns can match the same bitmask (e.g. exploit_c2 and reverse_shell overlap on socket); best_match picks the pattern with the most bits, and max_proximity reports how close the closest pattern is.
The tracker also emits pre-chain warnings when a process accumulates enough of a pattern's bits to cross the proximity threshold (default 0.6) without completing a full pattern. This catches attacks in progress before they finish executing.
killchain is a standalone CLI service (not a library). It consumes eBPF events from a Redis stream, accumulates per-PID syscall bitmasks, matches attack patterns, and publishes incidents to another Redis stream.
cargo build --release
./target/release/killchain \
--redis-url redis://127.0.0.1:6379 \
--events-stream innerwarden:events \
--incidents-stream innerwarden:incidents \
--pre-chain-threshold 0.6 \
--session-timeout-secs 60 \
--log-level infoAll flags have defaults, so it can also be run with no arguments:
./target/release/killchain| Flag | Default | Description |
|---|---|---|
--redis-url |
redis://127.0.0.1:6379 |
Redis connection URL |
--events-stream |
innerwarden:events |
Redis stream to read eBPF events from |
--incidents-stream |
innerwarden:incidents |
Redis stream to publish incidents to |
--pre-chain-threshold |
0.6 |
Minimum proximity score (0.0–1.0) to emit a pre-chain warning |
--session-timeout-secs |
60 |
Session timeout in seconds (cleanup of stale PIDs) |
--log-level |
info |
Log level |
eBPF (kernel) → PID_CHAIN bitmap per process
↓ events via Redis Streams
killchain (userspace) → pattern matching + enrichment → incidents
Part of the InnerWarden security ecosystem.
License: BUSL-1.1