# eBPF Rootkits Gaining Traction on Underground Forums (Flare research; BPFDoor, Symbiote, LinkPro, CVE-2017-16995 reposts)

> Sponsored Flare research reports underground forum posts sharing eBPF rootkit code and tutorials, including a Russian-language Duty Free tutorial with XDP code, and widely reposted CVE-2017-16995 exploit code. eBPF programs load without a kernel module, so a routine lsmod check can miss them; real-world families include BPFDoor, Symbiote and LinkPro.

- **Published:** 2026-11-11T19:42:39Z
- **Last reviewed:** 2026-11-11T19:42:39Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-5791
- **Card image:** https://intel.threadlinqs.com/og/threat/TL-2026-5791.png
- **ID:** TL-2026-5791
- **Severity:** MEDIUM
- **Category:** MALWARE
- **Status:** MONITORING
- **Detections:** 9 (1 shown free below) · **IOCs:** 22 (3 shown free below)
- **CVEs:** CVE-2017-16995, CVE-2024-23897

## Description

On 2026-11-11 BleepingComputer published research sponsored by and written by Flare describing growing underground interest in eBPF rootkits. Flare monitors forums, marketplaces and paste sites. It cites a Russian-language tutorial on the Duty Free forum (post 29181) on building an eBPF rootkit that names BPFDoor and Symbiote as influences. The tutorial's implant is activated by a TCP SYN packet with a specific window size, hides processes by hooking getdents64, encrypts C2 traffic with AES-256-GCM, and uses XDP to inspect incoming plaintext HTTP and drop packets from a list of 43 IP addresses the author associates with antivirus vendors. The list is not reproduced in the article. A separate unnamed Russian-language post described an implant with process hiding and packet-triggered activation. Flare also found 10 Pastebin posts containing XDP packet-processing code and microsecond timing thresholds.

The article reviews eBPF-related malware from 2021 to 2025. BPFDoor (found by PwC in 2021, publicly reported in 2022, associated with Red Menshen) is a passive backdoor that uses a classic BPF socket filter to recognise crafted TCP, UDP or ICMP packets and open a reverse shell or redirect traffic; it targeted the Middle East and Asia. Note that BPFDoor uses classic BPF (cBPF) rather than eBPF proper. Symbiote (Intezer and BlackBerry) is an LD_PRELOAD shared-library rootkit that intercepts setsockopt() SO_ATTACH_FILTER calls and prepends its own filter instructions to hide traffic from packet capture. ebpfkit (Black Hat USA and DEF CON 2021) is offensive research. TripleCross combines syscall hooks with XDP and tc programs for library injection, execution hijacking, concealment and C2. Boopkit hooks getdents64 and is triggered remotely by a malformed TCP SYN or ordinary TCP connections. LinkPro (Synacktiv, October 2025) is the one in-the-wild eBPF case study in the set.

LinkPro case (Synacktiv, 2025-10-14): the intrusion began with an internet-exposed Jenkins server vulnerable to CVE-2024-23897. The attacker reached the CI/CD pipeline of several Amazon EKS clusters and deployed a malicious Docker image, kvlnt/vv (Kali base), that bind-mounted the host root to /mnt, ran an SSH server with root login, a vnt VPN/proxy binary and the vGet downloader (Rust). vGet harvested kubelet tokens, CA certificates and secrets, then pulled an encrypted vShell 4.9.3 payload from S3 and ran it in memory. A later wave used a dropper that loaded a second in-memory vShell with DNS tunnelling and finally deployed LinkPro. LinkPro has two eBPF modules: Hide (hides processes and BPF objects, requires CONFIG_BPF_KPROBE_OVERRIDE, otherwise falls back to /etc/ld.so.preload with libld.so) and Knock (an XDP/tc magic-packet module). A TCP SYN with window size 54321 is dropped by XDP and whitelists the source IP in knock_map for one hour. During that window XDP rewrites the destination port to 2233 and a tc egress program rewrites the source port back, so replies look like they come from an allowed port such as 443. Persistence is via a fake systemd-resolveld.service (note the trailing d) running a copy at /usr/lib/.system/.tmp~data.resolveld, timestomped to match /etc/passwd. C2 supports HTTP, WebSocket, raw UDP/TCP and DNS in forward mode, and HTTP with XOR-encrypted JSON in reverse mode. LinkPro tried to hide programs from bpftool prog list, but investigators still saw BPF maps and links.

Exploits: CVE-2017-16995 (Linux BPF verifier check_alu_op incorrect sign extension, CVSS 7.8, CWE-119, kernel 4.4 through 4.14.8 range per NVD) is the most reposted exploit in Flare's dataset, on at least six platforms. An unverified kTLS/eBPF sockmaps local privilege escalation PoC (no CVE cited) tries to corrupt the page cache of /etc/passwd to inject a UID 0 account; its claimed compatibility with all kernels from 4.18 is incorrect and successful escalation on Ubuntu 22.04/24.04 is unverified. In one exploit sample the author credited Claude in a code comment for generating the BPF instructions.

Detection is hard because eBPF programs pass the kernel verifier and run without a kernel module. Current detection relies on monitoring bpf() syscalls, enumerating programs with bpftool, and watching attachments to getdents64 and execve. Recommended defences: audit bpftool prog list, set kernel.unprivileged_bpf_disabled=1, restrict CAP_BPF and CAP_NET_ADMIN, watch for magic packets and unexpected XDP programs, patch promptly, and compare multiple telemetry sources. The article is vendor-sponsored and lists no hashes, domains or IPs of its own; the IOCs below come from Synacktiv's LinkPro analysis. BeaconBeagle checks for the two LinkPro IPs returned HTTP 502 and could not be completed.

## MITRE ATT&CK

- T1190 Exploit Public-Facing Application
- T1059.004 Unix Shell
- T1543.002 Systemd Service
- T1611 Escape to Host
- T1014 Rootkit
- T1574.006 Dynamic Linker Hijacking
- T1205.002 Traffic Signaling: Socket Filters
- T1036.004 Masquerade Task or Service
- T1070.006 Timestomp
- T1620 Reflective Code Loading
- T1552.007 Container API
- T1205 Traffic Signaling
- T1071.001 Web Protocols
- T1071.004 DNS
- T1573.001 Symmetric Cryptography

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**eBPF Rootkit Loader / Socket-Filter Attach via bpf() and SO_ATTACH_FILTER Syscalls (LinkPro, BPFDoor, Symbiote, CVE-2017-16995)** (`TL-2026-5791-SPL-001`)

Detects the kernel-facing step shared by the eBPF rootkit families in TL-2026-5791: a bpf(BPF_PROG_LOAD) call (LinkPro Hide/Knock modules, TripleCross, ebpfkit, and CVE-2017-16995 verifier-bypass exploit PoCs reposted on underground forums) or a setsockopt(SO_ATTACH_FILTER) call (BPFDoor classic-BPF magic-packet filter, Symbiote prepending filters to hide traffic) made by a binary that is not a known observability, networking or container component. eBPF programs load without a kernel module so lsmod misses them; auditd syscall telemetry is the reliable signal.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1068, T1014, T1205.002
- **Data sources:** linux_auditd, splunk_ta_nix:linux:audit
- **Severity:** high
- **Confidence:** high

### Splunk SPL

````spl
index=linux sourcetype="linux:audit" type=SYSCALL arch=c000003e earliest=-24h ((syscall=321 a0=5) OR (syscall=54 a1=1 a2=1a))
```comment: syscall 321 is bpf() and a0=5 is BPF_PROG_LOAD (LinkPro Hide/Knock, TripleCross, ebpfkit, CVE-2017-16995 PoCs); syscall 54 is setsockopt() with SOL_SOCKET and SO_ATTACH_FILTER (BPFDoor, Symbiote). Requires auditd rules for -S bpf and -S setsockopt.```
| eval uid_n=tonumber(uid)
| where isnull(exe) OR NOT match(exe,"^/(usr/)?(s?bin|lib/systemd)/(bpftool|falco|tetragon|cilium-agent|systemd|systemd-networkd|dockerd|tcpdump|dhclient|dhcpcd|NetworkManager|chronyd|ntpd)$")
| eval behaviour=case(syscall="54","socket_filter_attach_BPFDoor_Symbiote_pattern", uid_n!=0,"unprivileged_bpf_prog_load_CVE-2017-16995_pattern", match(exe,"^/(tmp|dev/shm|var/tmp|home|root)/"),"bpf_prog_load_from_writable_path", true(),"bpf_prog_load_by_unexpected_binary")
| stats count AS events min(_time) AS first_seen max(_time) AS last_seen values(comm) AS comm values(key) AS audit_key BY host exe uid auid behaviour
| convert ctime(first_seen) ctime(last_seen)
| sort - events
````

### Microsoft KQL

```kql
let allowed_exe = dynamic(["/usr/bin/bpftool","/usr/sbin/bpftool","/usr/sbin/tcpdump","/usr/bin/tcpdump","/usr/lib/systemd/systemd","/usr/sbin/dhclient","/sbin/dhclient","/usr/bin/dockerd","/usr/sbin/NetworkManager","/usr/sbin/chronyd","/usr/bin/falco","/usr/bin/tetragon","/usr/bin/cilium-agent"]);
Syslog
| where TimeGenerated > ago(24h)
| where SyslogMessage has "type=SYSCALL" and SyslogMessage has "arch=c000003e"
| extend Syscall = extract(@"syscall=(\d+)", 1, SyslogMessage),
         A0 = extract(@"\ba0=([0-9a-f]+)", 1, SyslogMessage),
         A1 = extract(@"\ba1=([0-9a-f]+)", 1, SyslogMessage),
         A2 = extract(@"\ba2=([0-9a-f]+)", 1, SyslogMessage),
         Uid = toint(extract(@"\buid=(\d+)", 1, SyslogMessage)),
         Auid = extract(@"\bauid=(\d+)", 1, SyslogMessage),
         Exe = extract(@'exe="?([^"\s]+)', 1, SyslogMessage),
         Comm = extract(@'comm="([^"]+)"', 1, SyslogMessage)
// syscall 321 = bpf(), a0 5 = BPF_PROG_LOAD; syscall 54 = setsockopt(), SOL_SOCKET (1) / SO_ATTACH_FILTER (0x1a)
| where (Syscall == "321" and A0 == "5") or (Syscall == "54" and A1 == "1" and A2 == "1a")
| where not(Exe in~ (allowed_exe))
| extend Behaviour = case(
    Syscall == "54", "socket_filter_attach_BPFDoor_Symbiote_pattern",
    Uid != 0, "unprivileged_bpf_prog_load_CVE-2017-16995_pattern",
    Exe matches regex @"^/(tmp|dev/shm|var/tmp|home|root)/", "bpf_prog_load_from_writable_path",
    "bpf_prog_load_by_unexpected_binary")
| summarize Events = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), Comms = make_set(Comm, 10) by Computer, Exe, Uid, Auid, Behaviour
| order by Events desc
```

### Sigma

```yaml
title: Suspicious bpf() Program Load or Socket Filter Attach by Unexpected Process (eBPF Rootkit)
id: 3f6a9c1e-5b27-4d84-9e0a-71c2d8b4a6f1
status: experimental
description: Detects bpf(BPF_PROG_LOAD) and setsockopt(SO_ATTACH_FILTER) syscalls from binaries outside a known-good set. Covers eBPF rootkit loaders (LinkPro Hide/Knock, TripleCross, ebpfkit), CVE-2017-16995 verifier exploit PoCs and BPFDoor/Symbiote socket filters. Requires auditd rules for the bpf and setsockopt syscalls on x86_64.
references:
  - https://synacktiv.com/en/publications/linkpro-ebpf-rootkit-analysis
  - https://www.bleepingcomputer.com/news/security/ebpf-rootkits-why-underground-actors-are-taking-notice/
  - https://attack.mitre.org/
author: Threadlinqs Team
date: 2026/11/11
tags:
  - attack.privilege-escalation
  - attack.t1068
  - attack.defense-evasion
  - attack.t1014
  - attack.t1205.002
  - cve.2017.16995
logsource:
  product: linux
  service: auditd
detection:
  selection_bpf_load:
    type: 'SYSCALL'
    arch: 'c000003e'
    syscall: '321'
    a0: '5'
  selection_sockfilter:
    type: 'SYSCALL'
    arch: 'c000003e'
    syscall: '54'
    a1: '1'
    a2: '1a'
  filter_known:
    exe|endswith:
      - '/bpftool'
      - '/tcpdump'
      - '/dhclient'
      - '/dhcpcd'
      - '/systemd'
      - '/systemd-networkd'
      - '/dockerd'
      - '/NetworkManager'
      - '/chronyd'
      - '/falco'
      - '/tetragon'
      - '/cilium-agent'
  condition: 1 of selection_* and not filter_known
falsepositives:
  - Sanctioned eBPF observability or security agents not in the filter list
  - Packet capture and DHCP clients attaching socket filters
  - Kernel developers testing eBPF programs
level: high
```

**Known false positives:**

- Observability and security agents (Falco, Tetragon, Cilium, Datadog, Elastic Agent) that load eBPF programs from non-allowlisted paths
- Packet-capture tools and DHCP/NTP clients using SO_ATTACH_FILTER (tcpdump, dhclient, wireshark) outside the allowlist
- Developers and kernel engineers testing eBPF programs on lab hosts

**Tuning notes:** Requires auditd rules on x86_64: -a always,exit -F arch=b64 -S bpf -k bpf_call and -a always,exit -F arch=b64 -S setsockopt -F a1=1 -F a2=0x1a -k sockfilter (arm64 uses different syscall numbers: adjust). Extend the exe allowlist regex with your sanctioned eBPF agents, and alert at higher priority when behaviour is unprivileged_bpf_prog_load or bpf_prog_load_from_writable_path. Pair with kernel.unprivileged_bpf_disabled=1.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- Jenkins Controller Spawning Shells or Host-Root Docker Mounts (CVE-2024-23897 / kvlnt/vv LinkPro Initial Access) (locked: unlock with TL Creds)
- vGet/vShell In-Memory Execution and Kubelet Credential Harvesting on Linux Hosts (locked: unlock with TL Creds)
- LinkPro Knock Module: Inbound Connections or Listener on Redirect Port 2233 (XDP Magic-Packet Traffic Signaling) (locked: unlock with TL Creds)
- Jenkins CLI Request Pattern Consistent with CVE-2024-23897 Arbitrary File Read (LinkPro Initial Access) (locked: unlock with TL Creds)
- eBPF Rootkit Tooling: XDP/tc Attach, bpftool Program Load, Unprivileged BPF Enablement and Timestomp to /etc/passwd (locked: unlock with TL Creds)
- vShell DNS Tunnelling and vnt Relay Domain Resolution (LinkPro DNS C2) (locked: unlock with TL Creds)
- LinkPro Persistence Artifacts: Fake systemd-resolveld Service, Hidden .system Copy and ld.so.preload Hijack (locked: unlock with TL Creds)
- LinkPro / vShell C2 Network Indicators: C2 IPs, vnt Relay, S3 Payload Host and /reverse/* HTTP Endpoints (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (3 of 22)

Defanged, TLP:CLEAR.

- IP address: `18.199.101[.]111`
- Domain: `vnt[.]wherewego[.]top`
- File hash: `d5b2202b7308b25bda8e106552dafb8b6e739ca62287ee33ec77abe4016e698b`

Full set of 22 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [eBPF Rootkits: Why Underground Actors Are Taking Notice (Flare, sponsored)](https://www.bleepingcomputer.com/news/security/ebpf-rootkits-why-underground-actors-are-taking-notice/)
- [LinkPro: eBPF rootkit analysis (Synacktiv)](https://synacktiv.com/en/publications/linkpro-ebpf-rootkit-analysis)
- [LinkPro Linux Rootkit Uses eBPF to Hide and Activates via Magic TCP Packets (The Hacker News)](https://thehackernews.com/2025/10/linkpro-linux-rootkit-uses-ebpf-to-hide.html)
- [NVD - CVE-2017-16995](https://nvd.nist.gov/vuln/detail/CVE-2017-16995)
- [Linux kernel fix commit for CVE-2017-16995 (95a762e2c8c9)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=95a762e2c8c942780948091f8f2a4f32fce1ac6f)
- [Project Zero issue 1454 (BPF verifier sign extension)](https://bugs.chromium.org/p/project-zero/issues/detail?id=1454)
- [Debian Security Advisory DSA-4073](https://www.debian.org/security/2017/dsa-4073)
- [Stealthy Linux implant BPFDoor compromised organizations globally for years (CSO Online)](https://www.csoonline.com/article/3659802/stealthy-linux-implant-bpfdoor-compromised-organizations-globally-for-years.html)
- [BPFDoor Hidden Controller (Trend Micro)](https://www.trendmicro.com/en_us/research/25/d/bpfdoor-hidden-controller.html)
- [Flare forum post, Duty Free #29181 (requires Flare account)](https://app.flare.io/#/forum_post/duty-free/29181)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-5791
