eBPF shell detection
Security Tools
William  

Detect Shell with eBPF

I use eBPF shell detection to catch stealthy programs that land inside the kernel and then hide from normal tools. You will see why watching load-time events matters more than chasing artifacts later.

The kernel grants deep visibility into system activity, but that same access gives attackers a way to hide a reverse shell or backdoor inside programs. Traditional security tools running in user space can miss kernel-resident hooks or be fed forged information after compromise.

In my experience, the most reliable approach is to log high-fidelity data at program load and attachment time, then use cross-layer tools for verification. This guide focuses on practical steps you can run with bpftool, Tracee, Falco and memory inspection when needed.

Table of Contents

Key Takeaways

  • Prioritize catching load events and tracking suspicious hooks within linux kernel.
  • Combine runtime tools and forensics to validate kernel-resident programs.
  • Log verifiable artifacts you can check from outside the operating system.
  • Use bpftool, Tracee, Falco and memory tools as complementary layers.
  • Expect precise commands, fields to collect, and post-incident checklists.
  • Plan for cloud and Kubernetes where namespace tricks can mask activity.

What eBPF Is and Why Shell Detection Matters on Linux

I explain how running small bytecode inside the linux kernel changes visibility and risk. You should watch load and attach events, not only artifacts left later.

From classic BPF to ebpf: kernel, system calls, and verifier basics

Classic bpf filtered packets. Modern ebpf adds many hook points and maps for state. Developers load code via the bpf() syscall. The verifier checks bounds and loops. The kernel then JIT compiles safe bytecode so programs run fast in kernel space.

Shell activity signals: exec, socket use, and file access patterns

Watch execve events, unexpected socket families, and access to /etc/shadow or SSH keys. Include PID, UID, container or cgroup tags, and parent lineage to reduce false positives.

AreaClassicExtendedConcrete example
HooksNetwork onlykprobes, tracepoints, sockets, XDPexecsnoop for exec visibility
StateNoneMaps and helpersTrack PID → cgroup mapping
Load pathNAbpf() syscall, verifier, JITLog bpf() loads in real time
  • Limit noise by whitelisting known maintenance tools.
  • Keep minimal per-event data: timestamp, program, args.
  • Test filters against your kernel version and machine to tune alerts.

Threat Landscape: eBPF Backdoors and Kernel-Level Shells

Modern threats place small programs inside the kernel to bypass user-space controls and hide activity.

Two notable cases illustrate the risk. BPFDoor used BPF filters that listened for magic packets. When triggered, it opened a hidden shell while keeping ports invisible to scans.

Pamspy took a different route. It attached a uretprobe to pam_get_authtok. That hook captured credentials during logins without needing a visible process on the host.

Traditional antivirus looks at files and user processes. Programs running inside the linux kernel can bypass those checks. They can also alter outputs from bpftool and debugfs so live listings are unreliable.

Concrete indicators and actions

  • Watch for setsockopt calls that install BPF filters and unexpected raw socket use.
  • Look for unexplained kprobe/uprobes on authentication paths and deleted executables.
  • Exclude known tools like tcpdump and dhclient to reduce alert noise.
  • Prefer catching loads and attach events; if missed, use hypervisor or memory dumps for forensics.

Core Challenges in Detecting eBPF-Based Shell Activity

Kernel-resident programs can appear without files and evade common monitoring paths.

You cannot rely on file scans. Malicious code lives in memory and attaches to kernel events without a persistent file on disk. That breaks many endpoint assumptions fast.

Once code runs in kernel context, a rootkit can tamper with local tools and telemetry. Your own process listings, bpftool outputs, and logs may be poisoned after compromise.

  • High event volume causes noise. Pick tight attach points and log only essential fields.
  • Some techniques hide links or override return paths. Simple enumeration then fails.
  • The verifier blocks many unsafe tricks, but attackers reuse allowed helpers and hooks. Technology controls alone are not enough.
  • If you miss the load event, you face a window problem and must move to memory or hypervisor-based forensics.

Reduce exposure by shrinking who can load programs and by restricting CONFIG and capability flags. Still, prevention does not replace fast load-time logging and off-host collection for trusted views.

Build a small, stable log schema. Combine quick alerts with scheduled deep snapshots. This balances overhead while keeping enough data to investigate risk and apply practical techniques.

Real-Time Detection: Catching eBPF Program Loads and Attachments

Focus on the bpf() path and attach events to record who loaded a program and where it hooked into the kernel.

You must log minimal, verifiable facts at the instant a program loads. Capture timestamp, PID, UID, and the invoking command. Tie that to the process tree so you can map user intent to kernel activity.

What to watch

  • Record the syscall entry (bpf()) and any link create events with link ID.
  • Log attach type: kprobe, uprobe, tracepoint, perf_event, XDP, or TC.
  • Include program type, map count, and helpers used to spot risky behavior.
  • Capture target function names and binary paths for uprobes and kprobes.

Why load-time logs matter

After a program is resident, tools and listings may be forged. Rootkits can hide links and alter outputs. That makes later discovery unreliable.

Alert on CAP_BPF changes and unprivileged toggles. Test your pipeline by loading known benign samples and confirming Tracee bpf_attach and Falco bpf() alerts show correct fields.

FieldWhyExampleSource
timestamp, PID, UIDProves who acted and when2025-10-01T12:34Z, 4321, 1000Tracee / audit
attach type, link IDShows where program hookskprobe, link=55bpftool / kernel events
program type, helpersFlags dangerous helpers and featurestracepoint, helper=override_returnTracee / Falco

eBPF shell detection: Tools, Programs, and Practical Workflows

Focus on reproducible steps you can run now: Tracee alerts, Falco policies, bpftool audits, and offline memory checks.

A high-tech workspace filled with cutting-edge tools for eBPF kernel development. In the foreground, a sleek terminal window displays intricate lines of code, hinting at the powerful capabilities of eBPF. Surrounding it, an array of hardware components, including a state-of-the-art workstation, network switches, and diagnostic tools, all carefully arranged to create an efficient and visually striking environment. In the background, a dynamic network diagram pulsates with data flows, showcasing the complex interconnectivity that eBPF helps monitor and manage. Warm, focused lighting casts a professional, almost surgical atmosphere, while the carefully curated color palette and clean, minimalist design evoke a sense of precision and technological prowess.

Tracee rules and quick commands

Enable Tracee rules for bpf_attach and bpf() loads. Tracee logs IDs, types, helper lists, and program names.

Example rule snippet:

- rule: BPF_Attach_Load
  condition: evt.type == bpf_attach or evt.type == bpf
  output: "bpf_attach by %{proc.cmdline} prog_id=%{bpf.id} helpers=%{bpf.helpers}"

Falco policies and scope

Add Falco rules for bpf() and perf_event_open. Limit scope to containers or host as needed. Tune suppressions for tcpdump, wireshark, and dhclient to reduce noise.

bpftool and on-host triage

Use these commands for a quick audit:

  • bpftool prog show
  • bpftool map show
  • bpftool link show

Walk /sys/fs/bpf for pinned objects. Keep a daily export under git for simple diff-based management. A small script can flag deleted executables holding BPF sockets as a hint, not proof.

Memory forensics with Volatility

On compromised machines, use Volatility’s eBPF plugin and a matching kernel profile. It extracts programs via prog_idr and highlights suspicious helpers.

ToolStrengthExample command
TraceeRich attach eventstracee-ebpf –rules bpf_attach
FalcoPolicy alertsfalco -c falco.yaml
bpftoolOn-host triagebpftool prog show

Hardening the Kernel to Reduce Shell Risk Within the Linux Kernel

A small change in kernel build options can remove many attack paths. I focus on settings you can apply now. Each item explains why it matters and how to verify it.

Privilege controls

Enable CONFIG_BPF_UNPRIV_DEFAULT_OFF at build time. This blocks unprivileged users from loading eBPF programs. It removes a common low-privilege vector.

Gate the SYS_bpf syscall to root and CAP_BPF. Add audit rules so every use is logged. Audit records tie actions to accounts for later review.

Reducing attack surface

Disable CONFIG_BPF_KPROBE_OVERRIDE. That helper can force return paths. Turning it off closes an abuse route.

Remove unused kprobe and tracepoint options when compiling the kernel. Fewer attach targets means fewer places for malicious programs to hide.

SettingFlagWhy
Unprivileged BPFCONFIG_BPF_UNPRIV_DEFAULT_OFFBlocks non-root loaders
Force-return helpersCONFIG_BPF_KPROBE_OVERRIDE=offStops helpers that alter flow
Pin namespace/sys/fs/bpf mount optionsRestricts who can pin maps and links
Integrity monitorLKRGAlerts on table or cred changes

Keep your kernel version current. Patch verifier and helper bugs quickly. Pair hardening with monitoring and strict module policies. Document approved exceptions for observability so security and operations stay aligned.

Post-Incident Hunting: Finding Stealthy Shell Behavior After the Fact

Post-incident hunting is a methodical sweep of the kernel and user artifacts. Start with a trusted snapshot. Save outputs off-host so you can compare later.

Immediate steps

Run these exact commands and store results with timestamps. Keep copies outside the host for integrity.

  1. bpftool prog show > /var/log/bpftool-prog-$(date -I).log
  2. bpftool map show > /var/log/bpftool-map-$(date -I).log
  3. bpftool link show > /var/log/bpftool-link-$(date -I).log
  4. cat /sys/kernel/debug/kprobes/list > /var/log/kprobes-$(date -I).log

Inspect interfaces, pins, and perf owners

  • ip link show — note XDP flags per interface.
  • tc filter show dev $iface — list BPF TC filters on each device.
  • Find pins: ls -l /sys/fs/bpf and record unknown paths.
  • bpftool perf show — map PIDs to probes and correlate to ps and pstree output.

Workflows and diffs

Diff today’s files against yesterday’s to surface new program IDs, maps, or pins. For deleted-on-disk binaries, search /proc for open descriptors and sockets. Collect file hashes, command lines, and ancestry for any suspicious PID.

CommandPurposeAction
bpftool prog showList kernel programsSave and diff
tc filter show dev $ifaceReveal TC BPF entriesNote unexpected devices
cat /sys/kernel/debug/kprobes/listShow kprobe hooksFlag auth/exec/network hooks

If host trust is low, export memory and run an offline analysis with Volatility and its ebpf plugin. Finish with a network sweep for raw sockets and odd listeners to confirm or rule out a hidden shell.

Case Studies: What Worked Against BPFDoor and Pamspy

This section shows exact hooks and IOCs that stopped two real attacks. I focus on the calls, probe names, and network signs you should log.

BPFDoor used setsockopt to install complex filters and hidden ports. Trend Micro linked that to raw sockets opened by processes whose binaries were deleted.

  • Monitor setsockopt inserts for SO_ATTACH_FILTER and unexpected raw socket() calls.
  • Flag processes with deleted executables that call network syscalls.
  • Treat unusually long or obfuscated filter strings as suspicious compared to tcpdump or libpcap patterns.

Pamspy attached a uretprobe on pam_get_authtok inside libpam.so to harvest credentials. Tracee captured the probe name and offsets at attach time.

  • Alert on uretprobe hooks targeting pam_get_authtok. Record offset, target path, and attaching PID.
  • Correlate probe attach time with a spike in login events or unexpected child processes.
  • Keep an allow list of approved auth function names; any new hook is high priority.
CaseKey HookNetwork Indicator
BPFDoorsetsockopt(SO_ATTACH_FILTER), raw socketsHidden ports, odd ICMP/UDP tunnels on iface
Pamspyuretprobe on pam_get_authtok (libpam.so)Credential theft correlated with login spikes
Response actionsbpftool prog/link show, log offsetsBlock raw sockets for non-privileged accounts

Keep example traces with sanitized args. Include process ancestry and the full command line for any alert. Share these cases with ops so small guardrails can block common attacker behavior.

Cloud and Virtualization: OpenStack and vSphere/NSX Detection Paths

Platform teams must bridge guest kernel visibility with network-level controls. In multi-tenant environments, you can often pull kernel state from many machines without interactive logins.

OpenStack host-driven inspection of guest VMs with bpftool

Use host-side commands to run a small scan inside guests. This helps when user access is blocked.

  1. Run a quick script via the cloud CLI:
    openstack server ssh --login root $VM -- 'bpftool prog show; bpftool map show' > /var/log/bpftool-$VM-$(date -I).log
  2. Check XDP and TC filters per interface:
    openstack server ssh $VM -- 'ip link; bpftool net; tc filter show dev eth0' > /var/log/bpf-iface-$VM.log
  3. Save outputs per machine and version your scripts so you can diff states over time.

vSphere + NSX network signals: DFW, IDS/IPS, flows, and ATP intel

NSX spots odd flows and tunneling patterns such as hidden UDP or ICMP channels. It can block outbound ports at the DFW.

  • Use IDS/IPS to flag unusual east-west communication and correlate with ATP feeds.
  • Accept limits: NSX sees network events, not guest kernel tampering. Keep a runtime sensor inside guests for kernel-level context.
  • Document control split: network teams run DFW/IDS, security teams manage in-guest scans and response handoffs.
PlatformVisible SignalsWhat it cannot seeRecommended action
OpenStackGuest bpftool outputs, XDP/TC filters, per-VM logsOff-host kernel tamper without guest accessHost-run scripts; save timestamped files per machine
vSphere + NSXDFW blocks, IDS/IPS alerts, flow analyticsIn-guest kernel state and map contentsUse flow intel and require in-guest runtime sensors
CombinedCorrelated network and kernel events across systemsSingle-layer blind spots if used aloneDual-layer monitoring and clear handoffs between teams

Kubernetes Runtime: Detecting Reverse Shells and Privileged Containers Using eBPF

Detecting container escape requires tying process execs to container IDs and watching for host namespace joins. Watch runtime events on nodes and map them back to pods, namespaces, and service accounts. This gives context for quick response.

Signals of container escape

  • Alert when a pod uses hostPID or hostNetwork with CAP_SYS_ADMIN or CAP_NET_RAW on nodes that should not allow it.
  • Match commands like nsenter -t 1 -m -u -n -i -p to the container ID and service account for fast triage.
  • Flag access to /etc/shadow or other host files after a namespace join as a high-priority event.

Runtime monitoring of sockets and RCE patterns

Use a runtime sensor to watch system calls for exec of bash or sh with a TTY over a non-standard socket. That is a strong sign of a reverse connection.

  1. Log process, pod, node, namespace, and labels with each event.
  2. Flag raw socket opens and outbound connects from unexpected namespaces.
  3. Track program loads on nodes to spot attempts to hide at the kernel level.
SignalWhy it mattersExample action
hostPID + CAP_SYS_ADMINEnables host-level access from a podBlock admission; alert owner team
nsenter commandShows namespace join attemptsMap to pod ID and revoke creds
TTY over non-standard socketIndicates reverse interactive sessionIsolate node and capture logs

Action Plan: Layered Strategies and Tools to Lower Risk Now

Action Plan: Focus on layered strategies you can test today to lower risk across kernel and cloud environments.

Start with visibility. Deploy Tracee or Falco to alert on bpf() loads and attachments. Route compact fields into your SIEM so events are usable.

Harden the kernel. Enable CONFIG_BPF_UNPRIV_DEFAULT_OFF, restrict CAP_BPF and disable the kprobe override. Add LKRG for integrity monitoring.

Schedule management tasks. Export bpftool prog/map/link daily, store in git, and diff for new program IDs. Test memory capture and the Volatility plugin in a lab.

Cover cloud and Kubernetes. Use host-run bpftool in OpenStack. Leverage NSX flows and block privileged pods at admission. Train owners with short runbooks and keep a small, consistent event schema. Review monthly and tune tools and processes to keep this plan simple and effective.

FAQ

What does "Detect Shell with eBPF" mean and why is it useful?

It means using extended Berkeley Packet Filter programs inside the Linux kernel to spot interactive or programmatic shell-like behavior. This helps you catch post-exploit activity that lives in kernel space or uses kernel hooks. You gain visibility into exec, socket, and file patterns that typical userland agents miss.

How does the modern verifier and syscall model differ from classic BPF?

Classic BPF targeted packet filters in a limited VM. The modern verifier enforces safety for richer programs that call helpers and attach to many kernel hooks. The bpf() syscall is the entry point. The verifier and helper model let programs run safely but also raise the bar for detection because logic can live closer to kernel internals.

What runtime signals indicate shell-like activity from kernel programs?

Watch for unusual execve chains, new raw or nonstandard sockets, repetitive file open/write patterns, pinned maps or programs, and links into networking hooks like XDP or TC. Correlate these with process capabilities and attach events to separate benign from suspicious activity.

Are there real examples of kernel-resident backdoors using this tech?

Yes. Kernel-resident implants have used kernel hooks and BPF-like techniques to intercept auth paths and spawn covert channels. These cases often hide by running as seemingly normal kernel programs and by avoiding obvious userland artifacts, which is why kernel-focused inspection proved essential.

Why do traditional antivirus and endpoint agents miss kernel-resident programs?

Most agents run in user space and focus on file indicators, process trees, and signatures. Kernel-resident programs attach to callbacks or use maps and links that do not create persistent files. Without kernel-level telemetry you lack the signals needed to detect these behaviors.

What are the main challenges when detecting programs that attach to kernel hooks?

Challenges include dynamic loading, minimal userland footprint, legitimate uses that closely resemble malicious behavior, and the complexity of mapping helper calls to intent. High-volume noise from benign tracing and networking code also creates false positives unless you tune filters.

How can I detect program loads and attachments in real time?

Monitor the bpf() syscall, kprobe/uprobes registrations, and netdev/XDP attach events. Log fields such as program type, helper usage, pinned object names, and target functions. Correlate with process credentials and capability state at load time to prioritize alerts.

Which event fields matter most when logging attach events?

Capture program type (XDP, tracing, socket filter), helpers invoked, presence of maps, link target (function or net device), process UID/GID, CAP_BPF or similar capabilities, and whether the object is pinned to bpffs. These help you triage intent quickly.

When do detection attempts commonly fail after a program is loaded?

Detections fail when programs hide behind generic helpers, reuse legitimate pinned map names, detach and reattach quickly, or execute logic that only triggers on rare conditions. Failure also happens when audit pipelines drop kernel events or when logs lack context about the loader process.

What open-source tools help in spotting and investigating these kernel programs?

Use tracee or Falco rules tuned for bpf_attach and suspicious syscalls for runtime detection. Use bpftool for manual inspection of programs, maps, links, and bpffs. For memory forensics, use Volatility plugins that understand kernel BPF objects.

How do Tracee and Falco differ for this purpose?

Tracee focuses on syscall-level tracing and can emit detailed bpf() and attach events. Falco is rules-driven and excels at alerting on behavioral patterns in runtime logs. Use both: Tracee for rich telemetry and Falco for continuous policy enforcement.

What should I inspect with bpftool during a hunt?

List programs, maps, and links. Check program attach points, helper calls, pinned object locations in bpffs, and map contents where possible. Store outputs for diff-based comparison across time to spot stealthy changes.

Which kernel hardening knobs reduce risk from kernel programs?

Enforce CAP_BPF restrictions, set CONFIG_BPF_UNPRIV_DEFAULT_OFF where available, and restrict unprivileged bpf() usage. Disable unused features like kprobe override and limit loadable tracing where possible. Keep kernels patched and minimize attack surface.

How can capability controls like CAP_BPF help?

They limit which users or processes can create and attach programs. Removing CAP_BPF from untrusted services prevents many unauthorized program loads. Combine this with policy and audit to block escalation paths that lead to kernel-level implants.

What post-incident steps reveal stealthy kernel behavior after compromise?

Inspect pinned objects, active kprobes, XDP and TC filters, and check for unusual bpffs entries. Capture bpftool dumps and compare against known baselines. Look for unexpected links into auth code paths or network stacks.

How do diff-based audits of bpftool outputs help?

They show changes over time. Many stealthy implants modify or add programs and maps with subtle names. Regularly snapshotting and diffing bpftool outputs highlights additions, deletions, and modified attach points that single-time inspections miss.

What indicators helped stop BPFDoor and similar threats?

Indicators included abnormal setsockopt usage, raw socket creation, complex BPF filters attaching to network stacks, and uretprobe hooks on authentication binaries. Correlating those with new pinned maps and unexpected helper calls exposed malicious intent.

How do you detect uretprobe hooks on auth paths?

Monitor uprobe and uretprobe registrations against common auth binaries. Alert when probes attach to passwd, su, sshd, or PAM libraries from unexpected processes. Combine with exec and capability logs to determine whether the hooks are legitimate.

How can cloud platforms like OpenStack help inspect guest VMs for kernel programs?

Host-driven inspection using bpftool on hosts can surface guest-created pinned objects and network filters when shared drivers are used. Integrate host telemetry into your cloud monitoring and use agent-assisted inspection where host-level access exists.

What network signals from vSphere/NSX help detect hidden kernel programs?

Look for anomalous distributed firewall rules, IDS/IPS alerts, unexpected flows, and ATP intelligence tied to unusual sockets or encapsulation. Correlate network telemetry with host bpftool outputs to map network anomalies back to kernel hooks.

What are container runtime signs of privilege escalation or reverse shells?

Watch for nsenter usage, host namespace joins, sudden CAP additions, or nonstandard socket creation inside containers. Trace attachments to host hooks and unusual pinned objects accessible from container mounts. These are strong signals of escape attempts.

How should teams prioritize detection and hardening actions now?

Start by auditing unprivileged bpf() access and removing unnecessary capabilities. Deploy runtime rules for bpf_attach and suspicious syscalls. Add regular bpftool snapshots and diffing into your change-control workflow. Combine kernel telemetry with network and process signals for layered detection.

Related: Operationalizing Falco: eBPF Driver Setup and Alert Routing