The `bpftool prog show` Command That Unmasks Hidden Kernel Backdoors
Are you confident that only legitimate eBPF programs are running in your production kernel? Practical commands, expected outputs and a checklist inside.
Attackers live in the kernel now, bypassing user-space agents entirely. If you cannot account for every loaded payload on your nodes, your hosts are already compromised.
TL;DR: Malicious rootkits hide from standard process monitors by executing directly in kernel context. This post details how to use
bpftoolto audit attached hooks and expose invisible backdoors. You will get the exact audit commands to verify host integrity immediately.
How Do You Find Hidden eBPF Programs in Linux?
You find hidden payloads by querying the kernel directly using the bpftool prog show command. This bypasses user-space abstractions to list every loaded program ID, its type, and memory footprint. Running this exposes payloads that rootkits attempt to mask from standard tracing tools.
1
bpftool prog show --json --pretty
1
2
3
4
5
6
7
8
9
10
11
12
[
{
"id": 42,
"type": "kprobe",
"tag": "d3b300305a415a76",
"gpl_compatible": true,
"loaded_at": 1716301234,
"name": "hidden_hook",
"run_time_ns": 45000,
"run_cnt": 12
}
]
An eBPF program is a compiled, sandboxed application that executes directly within the Linux kernel to extend OS capabilities safely. Executing the audit above requires bpftool >= 6.8 and elevated host privileges.
| Flag/Argument | Description | Best For |
|---|---|---|
prog show |
Queries kernel for all loaded programs | Baseline visibility |
--json |
Outputs raw JSON data | Scripted audits |
--pretty |
Formats JSON with human-readable indentation | Manual inspection |
Scenario Variations:
- Pinpoint a specific payload by ID:
1
bpftool prog show id 42 - View attached network hooks specifically:
1
bpftool net show
- Dump translated instructions for reverse engineering:
1
bpftool prog dump xlated id 42
When NOT to use it: Do not run bpftool prog dump jited on production systems under heavy load. JIT dumping triggers kernel locks that heavily degrade network throughput for latency-sensitive applications like Aicademy APIs.
Always append
--jsonto your automated monitoring scripts to prevent parsing failures when kernel structures change.
How Do You Differentiate Legitimate vs Suspicious eBPF Payloads?
You separate legitimate payloads from suspicious ones by mapping the loaded program IDs to known monitoring agents. Any program lacking a verified user-space owner or attached to sensitive tracepoints without documentation requires immediate quarantine. To structure a proper audit, compare this baseline against expected host profiles.
View Verbose Audit Output
1
2
3
4
5
6
7
8
9
10
11
12
[
{
"id": 142,
"type": "cgroup_skb",
"tag": "03b300305a415a76",
"gpl_compatible": false,
"loaded_at": 1716301234,
"name": "",
"run_time_ns": 45000,
"run_cnt": 12
}
]
Review how architecting runtime security at the kernel edge establishes strict baseline rules for authorized agents. You must also implement aggressive Linux system hardening strategies to lock down bpf() syscall access completely. Advanced rootkits manipulate memory pointers directly, making immediate containment critical.
Since Linux 4.15, the eBPF verifier limits instruction counts to prevent kernel hangs, but attackers bypass this by daisy-chaining smaller malicious programs via tail calls. You must audit the entire hook chain, not just the entry point.
-
Verify the
typealigns with the program’s intended function (e.g.,xdpfor network filters). -
Match
loaded_attimestamps against authorized CI/CD deployment windows. -
Confirm
gpl_compatiblestatus, as proprietary rootkits often spoof or omit this flag entirely.
graph TD
A["User Space Rootkit"] -->|"loads payload"| B["bpf() syscall"]
B --> C["eBPF Verifier"]
C --> D["Kernel Hook Point"]
D -->|"executes hidden logic"| E["Network/Process Event"]
Cross-reference
loaded_attimestamps against your CI/CD deployment logs to quickly spot out-of-band kernel modifications.
Bottom Line
Run your eBPF audits directly via kernel interfaces, never trusting user-space process lists alone. A compromised host lies to ps, but it cannot hide raw BPF structures from a static binary querying the kernel. Implement this one-liner into your daily security checks to catch memory-resident threats early.
Next up in the series: analyzing eBPF map memory structures to detect data exfiltration.
FAQ
What is the default access level required to run bpftool?
You need CAP_SYS_ADMIN or CAP_BPF capabilities to execute bpftool prog show. Unprivileged users receive a permission denied error by default on modern kernels.
How do you remove a malicious eBPF program once found?
You cannot directly “kill” an eBPF program. You must terminate the user-space process holding the file descriptor, or detach it from the hook using bpftool net detach for network programs.
Can eBPF rootkits hide from bpftool?
Advanced rootkits attempt to hook the bpf() syscall itself to filter bpftool output. Detecting these requires static memory forensics and hypervisor-level introspection rather than live kernel querying.
Why does bpftool show programs with no names?
Older kernels did not enforce program naming, and malicious actors intentionally leave names blank to evade simple string-matching alerts. Treat unnamed programs as highly suspicious.
Part of the series: ebpf-security-masterclass
- eBPF for the Impatient: Architecting Runtime Security at the Kernel Edge
- The `bpftool prog show` Command That Unmasks Hidden Kernel Backdoors (you are here)
Further Reading
🚀 Ready to get hands-on? Spin up an interactive AI or Kubernetes Sandbox at Aicademy Labs for free.
