Skip to navigation

Threat reportMalwareTL-2026-2624

eBPF Rootkit Detection: VoidLink, LinkPro, and Atomic Arch Evade Kernel-Level Monitoring

mediumACTIVE

Datadog Security Labs documents three distinct in-the-wild eBPF rootkit techniques — VoidLink's Netlink message-length tampering via bpf_probe_write_user(), LinkPro's bpf_override_return() enumeration spoofing, and Atomic Arch's bpf_send_signal() debugger-killing — and proposes load-time BPF_PROG_LOAD helper-fingerprinting as a defense that runs before any of the three can corrupt the kernel's introspection surface. First disclosed .

Key facts for VoidLink LinkPro Atomic Arch eBPF

IdentifiersTL-2026-2624, CVE-2024-23897
Also known asVoidLink, LinkPro, Atomic Arch
SeverityMEDIUM
First disclosed
Exploitation statusExploited in the wild; Listed in CISA KEV: CVE-2024-23897 (added )
EPSSCVE-2024-23897: 99.9% (99.9th percentile)
Affected productsLinux Kernel eBPF/BPF subsystem; Jenkins Jenkins Server; Arch Linux Arch User Repository (AUR) packages; npm / Bun package ecosystem atomic-lockfile, lockfile-js, js-digest
Weaknesses (CWE)CWE-22
MalwareAtomic Arch, LinkPro, VoidLink
ToolsvShell
MITRE ATT&CK techniquesT1014 Rootkit, T1027 Obfuscated Files or Information, T1036.005 Match Legitimate Resource Name or Location, T1059.004 Command and Scripting Interpreter: Unix Shell, T1070.006 Indicator Removal: Timestomp, T1071.001 Application Layer Protocol: Web Protocols, T1082 System Information Discovery, T1090.002 Proxy: External Proxy, T1190 Exploit Public-Facing Application, T1195.002 Supply Chain Compromise: Compromise Software Supply Chain, T1205.002 Socket Filters, T1497 Virtualization/Sandbox Evasion and 6 more in the attack flow
MotivationFINANCIAL
Target sectorstechnology, cloud services, software development
Target regionsGlobal
Detection rules9 (1 shown free)
Sources8 cited sources

Detection coverage for VoidLink LinkPro Atomic Arch eBPF

As of 2026-09-22, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-2624 across Splunk SPL, Microsoft KQL and Sigma, covering 24 indicator(s) of compromise. The whole corpus is readable without an account. Every threat comes with one complete detection in Splunk SPL, Microsoft KQL and Sigma, free for everyone; a free account adds daily TL Creds to unlock the rest. Paid plans add a larger daily allowance, correlation and the MCP server. Threadlinqs MCP server · View plans.

Free detection: eBPF Rootkit Installation — Dangerous BPF_PROG_LOAD Helper Combination

Detects BPF_PROG_LOAD syscalls requesting bpf_probe_write_user, bpf_override_return, or bpf_send_signal/bpf_send_signal_thread — the load-time helper fingerprint Datadog Security Labs identified as common to VoidLink, LinkPro, and Atomic Arch — correlated with LinkPro's fake systemd-resolveld persistence unit and LD_PRELOAD fallback library drop, and multiple dangerous loads from one process within an hour per Datadog's proposed high-confidence rule.

Splunk SPL

index=ebpf_audit sourcetype="bpf:prog_load"
| eval dangerous_helper=if(match(helpers,"(?i)bpf_probe_write_user|bpf_override_return|bpf_send_signal_thread|bpf_send_signal"), 1, 0)
| where dangerous_helper=1
| bin _time span=1h as load_hour
| stats count as load_count values(helpers) as helper_list values(prog_type) as prog_types min(_time) as first_load max(_time) as last_load by host, pid, process_name, load_hour
| eval multi_load_1h=if(load_count>1, 1, 0)
| join type=left host
    [ search index=linux_audit sourcetype IN ("auditd","sysmon:linux") (path="/etc/systemd/system/systemd-resolveld.service" OR path="/usr/lib/.system/.tmp~data.resolveld" OR path="/etc/libld.so")
      | stats count as persistence_artifact_count values(path) as persistence_paths by host ]
| where multi_load_1h=1 OR persistence_artifact_count>0
| table host, pid, process_name, helper_list, prog_types, first_load, last_load, load_count, persistence_artifact_count, persistence_paths

Microsoft KQL

let DangerousBpfLoads =
    BpfProgramEvents_CL
    | where TimeGenerated > ago(1h)
    | where Helpers_s has_any ("bpf_probe_write_user", "bpf_override_return", "bpf_send_signal_thread", "bpf_send_signal")
    | summarize LoadCount=count(), Helpers=make_set(Helpers_s), FirstLoad=min(TimeGenerated), LastLoad=max(TimeGenerated) by DeviceName, ProcessId=Pid_d, ProcessName_s;
let PersistenceArtifacts =
    DeviceFileEvents
    | where Timestamp > ago(1h)
    | where FolderPath in~ ("/etc/systemd/system/systemd-resolveld.service", "/usr/lib/.system/.tmp~data.resolveld", "/etc/libld.so")
    | summarize ArtifactCount=count(), Paths=make_set(FolderPath) by DeviceName;
DangerousBpfLoads
| join kind=leftouter (PersistenceArtifacts) on DeviceName
| where LoadCount > 1 or isnotempty(Paths)
| project DeviceName, ProcessId, ProcessName_s, Helpers, LoadCount, FirstLoad, LastLoad, ArtifactCount, Paths

Sigma

title: eBPF Rootkit Installation via Dangerous BPF_PROG_LOAD Helper Combination
id: 1d3e5f7a-8b9c-4d1e-2f3a-4b5c6d7e8f04
status: experimental
description: Detects a BPF_PROG_LOAD event requesting bpf_probe_write_user, bpf_override_return, or bpf_send_signal(_thread) — the load-time helper fingerprint common to the VoidLink, LinkPro, and Atomic Arch eBPF rootkits per Datadog Security Labs' "Detection primitives for eBPF rootkits".
references:
    - https://securitylabs.datadoghq.com/articles/detection-primitives-for-ebpf-rootkits/
    - https://www.synacktiv.com/en/publications/linkpro-ebpf-rootkit-analysis
author: AII-Detector — ThreadLinqs Intelligence
date: 2026-09-22
tags:
    - attack.persistence
    - attack.defense-evasion
    - attack.t1014
    - attack.t1622
    - attack.t1543.002
    - attack.t1574.006
    - attack.tool.linkpro
    - attack.tool.voidlink
logsource:
    category: process_creation
    product: linux
detection:
    selection_bpf_load:
        syscall: 'bpf'
        bpf_cmd: 'BPF_PROG_LOAD'
    selection_dangerous_helper:
        helpers|contains:
            - 'bpf_probe_write_user'
            - 'bpf_override_return'
            - 'bpf_send_signal'
            - 'bpf_send_signal_thread'
    condition: selection_bpf_load and selection_dangerous_helper
falsepositives:
    - Legitimate eBPF-based observability/security tooling (Falco, Tetragon, Datadog CWS, Cilium, BCC tools) that intentionally loads programs using these helpers — allowlist by verified binary path/signature
level: critical

Known false positives:

  • Legitimate eBPF-based observability/security tooling (Falco, Tetragon, Datadog CWS, Cilium, BCC tools) intentionally loading programs that use bpf_probe_write_user/bpf_override_return/bpf_send_signal — allowlist by verified binary path, hash, and systemd unit

Tuning notes: Build an allowlist of verified eBPF loader binaries (path + hash + code-signing) for Falco/Tetragon/Datadog CWS/Cilium/BCC and suppress matches from those processes; retain the correlation requiring either >1 dangerous-helper load from the same process within an hour or co-occurrence with a LinkPro persistence artifact (systemd-resolveld.service, .tmp~data.resolveld, libld.so) to keep single-load false positives low, per Datadog's proposed high-confidence rule.

8 more detection rules (Splunk SPL, Microsoft KQL, Sigma) · unlock with TL Creds. Sign up free to unlock the detection rules or query them with the Threadlinqs MCP server (Purple)
  • Jenkins CVE-2024-23897 CLI File-Read Exploitation Preceding EKS Rootkit Deployment (Sentinel) · unlock with TL Creds
  • eBPF Rootkit Installation — Dangerous BPF_PROG_LOAD Helper Combination (Sentinel) · unlock with TL Creds
  • LinkPro C2 Beaconing and Magic-Packet Port Knock Activation (Sentinel) · unlock with TL Creds
  • Jenkins CLI CVE-2024-23897 Arbitrary File Read Exploitation Attempt · unlock with TL Creds
  • eBPF Rootkit Anti-Debug Trigger — ptrace SIGKILL via bpf_send_signal · unlock with TL Creds
  • VoidLink Netlink Socket-Diagnostic Concealment via bpf_probe_write_user · unlock with TL Creds
  • Jenkins CVE-2024-23897 CLI File-Read Exploitation Preceding EKS Rootkit Deployment · unlock with TL Creds
  • LinkPro C2 Beaconing and Magic-Packet Port Knock Activation · unlock with TL Creds

Indicators of compromise for VoidLink LinkPro Atomic Arch eBPF

As of 2026-09-22, Threadlinqs Intelligence tracks 24 indicators of compromise for TL-2026-2624.

Sample indicators (3 of 24)

  • IP address: 56.155.98[.]37
  • Domain: vnt[.]wherewego[.]top
  • URL: hxxps://fixupcount[.]s3[.]dualstack[.]ap-northeast-1[.]amazonaws[.]com/wehn/rich.png

Defanged, TLP:CLEAR. Full set of 24 indicators: unlock with TL Creds.

24 indicators of compromise · unlock with TL Creds. Compare plans

How VoidLink LinkPro Atomic Arch eBPF works

Datadog Security Labs' "Detection primitives for eBPF rootkits" (2026-07-27) synthesizes three separately disclosed Linux rootkit/malware families to argue that eBPF helper-function combinations requested at BPF_PROG_LOAD time are a durable, pre-verifier detection signal because load time is "the last moment the kernel's view of an eBPF program can be trusted."

VoidLink, documented by Check Point Research on 2026-01-13, is a modular, Zig-written cloud-native C2 framework with 37 in-memory plugins spanning reconnaissance, cloud/Kubernetes privilege escalation (docker_escape, k8s_privesc), credential harvesting (ssh_harvester, browser_stealer, passwd_dump, keyring_dump), persistence, lateral movement, and anti-forensics, plus HTTP/HTTPS, ICMP, DNS-tunneling, and partial P2P/mesh C2 channels. Its network-hiding eBPF program places a kprobe/kretprobe pair on __sys_recvmsg to intercept SOCK_DIAG_BY_FAMILY Netlink responses, then calls bpf_probe_write_user() to inflate the nlmsg_len field of the inet_diag_msg record preceding the one to hide by exactly NLMSG_ALIGN(B.nlmsg_len) — enough to make NLMSG_NEXT's traversal cursor skip the hidden record entirely while still passing NLMSG_OK bounds validation, so ss and netstat silently omit selected TCP connections. Check Point assessed the framework was built by a single, Chinese-affiliated developer using AI-assisted tooling (the TRAE IDE) in under a week, and found no evidence of real-world infections at publication — VoidLink is best treated as an advanced but not-yet-deployed capability.

LinkPro, discovered by Synacktiv's CSIRT (published 2025-10-14) during incident response on a compromised AWS environment, IS observed in a live intrusion. Initial access was an exposed Jenkins server vulnerable to CVE-2024-23897 (CVSS 9.8, CLI @-file-path expansion allowing unauthenticated arbitrary file read), which the actor used to pivot into multiple Amazon EKS clusters and deploy the malicious Docker Hub image kvlnt/vv. That image's start.sh launched a Vnt VPN client (/app/link, connecting to vnt.wherewego.top:29872) and a Rust downloader (/app/app, "vGet") that pulled a vShell 4.9.3 implant staged on S3 (https://fixupcount.s3.dualstack.ap-northeast-1.amazonaws.com/wehn/rich.png) before dropping the Golang LinkPro rootkit itself. LinkPro's Hide eBPF module places tracepoint/kretprobe hooks on getdents64 and sys_bpf: on sys_bpf it checks BPF_PROG_GET_NEXT_ID / BPF_MAP_GET_NEXT_ID / BPF_LINK_GET_NEXT_ID enumeration calls (bpf(2) commands 11, 12, 31) against an allowlist and calls bpf_override_return(ctx, -ENOENT) on a match — which has the side effect of truncating enumeration of every subsequent, non-malicious program with a higher ID as well, and requires a kernel built with CONFIG_BPF_KPROBE_OVERRIDE (present on recent Amazon Linux and Ubuntu 24.04); LinkPro falls back to an /etc/ld.so.preload shared-library hook (/etc/libld.so) when that config is absent. Its Knock module uses an XDP ingress program to watch for a "magic packet" (TCP SYN, window size 54321), records the source IP in a 1-hour-TTL map, and rewrites inbound/outbound TCP ports (via a paired TC egress program) to redirect real C2 traffic to port 2233/2333 while any port scan of the host shows nothing listening. The backdoor persists as a fake systemd unit (/etc/systemd/system/systemd-resolveld.service enabling a binary at /usr/lib/.system/.tmp~data.resolveld, masquerading as systemd-resolved and timestomped to match /etc/passwd), supports interactive shell, file management, chunked Base64 exfiltration, and SOCKS5 reverse-proxy pivoting, and was observed beaconing to 56.155.98.37 (active/forward mode, WebSocket) and 18.199.101.111. Synacktiv found no formal attribution beyond apparent financial motivation.

Atomic Arch is a supply-chain campaign, first reported by Sonatype and expanded on by Corgea and StepSecurity, that on 2026-06-11/12 adopted roughly 1,619 orphaned Arch User Repository (AUR) packages and poisoned their PKGBUILD install scripts to pull malicious npm/Bun dependencies — atomic-lockfile@1.4.2, lockfile-js@1.4.2 (Sonatype-2026-003775 / -003808), and a second-wave js-digest@4.2.2 — whose bundled Rust ELF payload (deps, sha256 6144d433f8a0316869877b5f834c801251bbb936e5f1577c5680878c7443c98b) harvests GitHub tokens, SSH keys, HashiCorp Vault credentials, browser cookies, and chat-app (Slack/Discord/Teams/Telegram) session data, exfiltrating over HTTP POST /api/upload and controlled via POST /api/agent. When run as root the payload deploys an eBPF rootkit (referencing source scales.bpf.c) that hooks getdents64() to hide PIDs, filenames, and socket inodes from /proc via hidden_pids/hidden_names/hidden_inodes maps, interferes with NETLINK_SOCK_DIAG-based socket enumeration, and — the technique that gives the campaign its place in Datadog's article — runs an enter_ptrace program on tp/syscalls/sys_enter_ptrace that inspects every ptrace() call for PTRACE_ATTACH (0x10) or PTRACE_SEIZE (0x4206) against a hidden-PID map and calls bpf_send_signal()/bpf_send_signal_thread() to SIGKILL the calling debugger — not the target — before the kernel completes the attach, leaving no visible sign that an eBPF program caused the crash.

Datadog's proposed countermeasure instruments the BPF_PROG_LOAD syscall itself: an LSM security_bpf_prog hook records program type/attach type/name/tag/ID, a kprobe on check_helper_call extracts the raw helper IDs a program requests before the verifier can rewrite them, and the syscall-exit path stitches identity and helper metadata into one event evaluated against rules such as "BPF_PROG_LOAD && BPF_PROBE_WRITE_USER in bpf.prog.helpers", the same pattern for BPF_OVERRIDE_RETURN, and for BPF_SEND_SIGNAL / BPF_SEND_SIGNAL_THREAD — with correlation of multiple such loads from one process within an hour flagged as high-confidence rootkit installation.

MITRE ATT&CK techniques by tactic:

Stealth

T1014 Rootkit; T1027 Obfuscated Files or Information; T1036.005 Match Legitimate Resource Name or Location; T1070.006 Indicator Removal: Timestomp; T1205.002 Socket Filters; T1497 Virtualization/Sandbox Evasion; T1622 Debugger Evasion

Execution

T1059.004 Command and Scripting Interpreter: Unix Shell

Command and Control

T1071.001 Application Layer Protocol: Web Protocols; T1090.002 Proxy: External Proxy

Discovery

T1082 System Information Discovery

Initial Access

T1190 Exploit Public-Facing Application; T1195.002 Supply Chain Compromise: Compromise Software Supply Chain

Persistence

T1543.002 Create or Modify System Process: Systemd Service

Credential Access

T1552.001 Unsecured Credentials: Credentials In Files; T1555.003 Credentials from Password Stores: Credentials from Web Browsers

stealth

T1574.006 Hijack Execution Flow: Dynamic Linker Hijacking

Privilege Escalation

T1611 Escape to Host

Remediation for VoidLink LinkPro Atomic Arch eBPF

Patches

  • Jenkins security advisory fix for CVE-2024-23897 (2.442+ / LTS 2.426.3+)

Immediate actions

  • Patch Jenkins beyond 2.441 / LTS 2.426.2 (CVE-2024-23897) or disable the Jenkins CLI's @-file-path command expansion until patched
  • Hunt for LinkPro IOCs on Linux/EKS hosts: /etc/systemd/system/systemd-resolveld.service, /usr/lib/.system/.tmp~data.resolveld, /etc/libld.so, outbound traffic to 56.155.98.37 and 18.199.101.111, and the kvlnt/vv Docker Hub image
  • Audit CI/build systems and developer workstations for atomic-lockfile, lockfile-js, or js-digest in npm/Bun lockfiles and package caches; if found, treat all credentials on that host as compromised (GitHub tokens, SSH keys, HashiCorp Vault tokens, browser sessions, chat-app sessions) and rotate them
  • Review any recently AUR-adopted/orphaned packages before rebuilding them with yay/paru; diff PKGBUILD changes against the prior maintainer's version

Workarounds

  • Disable remoting-based CLI access to Jenkins controllers that cannot be immediately patched
  • Pin AUR/npm/Bun dependency versions and require manual review of any newly adopted or newly published transitive dependency

Longer-term hardening

  • Deploy load-time BPF_PROG_LOAD monitoring (LSM security_bpf_prog hook plus a kprobe on check_helper_call, per Datadog's proposal) to flag any program requesting bpf_probe_write_user, bpf_override_return, or bpf_send_signal/bpf_send_signal_thread, and alert on multiple such loads from one process within an hour
  • Restrict which workloads may hold CAP_BPF/CAP_SYS_ADMIN and require CONFIG_BPF_KPROBE_OVERRIDE-aware allowlisting for eBPF program loaders on production Kubernetes/EKS nodes
  • Adopt a CWPP/eBPF-aware runtime sensor capable of correlating BPF_PROG_LOAD events with process lineage and container identity, since userspace tools (ss, netstat, ps, bpftool) can no longer be trusted once any of these three techniques is installed

Affected and fixed versions

  • Linux Kernel — eBPF/BPF subsystem
    Vulnerable versions: Kernels built with CONFIG_BPF_KPROBE_OVERRIDE (e.g. recent Amazon Linux, Ubuntu 24.04) for bpf_override_return abuse; any kernel ≥ 5.5 for eBPF-capable rootkits generally
  • Jenkins — Jenkins Server
    Vulnerable versions: 2.441 and earlier; LTS 2.426.2 and earlier
    Fixed in: 2.442+; LTS 2.426.3+
  • Arch Linux — Arch User Repository (AUR) packages
    Vulnerable versions: ~1,619 orphaned AUR packages adopted and poisoned June 11-12, 2026
  • npm / Bun package ecosystem — atomic-lockfile, lockfile-js, js-digest
    Vulnerable versions: atomic-lockfile 1.4.2; lockfile-js 1.4.2; js-digest 4.2.2

Timeline of VoidLink LinkPro Atomic Arch eBPF

  • CVE-2024-23897 (Jenkins CLI @-file-path expansion, CVSS 9.8) is publicly disclosed; later used as locked-ioc-23's initial-access vector against an exposed Jenkins server.
  • Synacktiv's CSIRT publishes "locked-ioc-23: eBPF rootkit analysis," disclosing the Hide and Knock eBPF modules discovered during incident response on a compromised AWS/EKS environment.
  • The Hacker News and other outlets report on locked-ioc-23's magic-packet port-knocking and bpf_override_return enumeration-spoofing techniques.
  • Check Point Research publishes "locked-ioc-22: The Cloud-Native Malware Framework," detailing the Zig-based C2 and its bpf_probe_write_user Netlink nlmsg_len-inflation technique; no real-world infections observed.
  • locked-ioc-20 campaign begins: attackers adopt orphaned Arch User Repository (AUR) packages and poison PKGBUILD install scripts to pull the malicious npm package locked-ioc-13.
  • A second locked-ioc-20 wave introduces Bun-based installation via locked-ioc-16 (published 10:21:34Z, unpublished 11:53:23Z) and locked-ioc-15 (published 13:01:03Z, unpublished 16:29:49Z), bringing the campaign to roughly 1,619 affected AUR packages.
  • Corgea and StepSecurity publish follow-on technical analyses of the locked-ioc-20 eBPF rootkit component (scales.bpf.c), documenting its getdents64 hooking and PTRACE_ATTACH/PTRACE_SEIZE anti-debug logic.
  • Datadog Security Labs publishes "Detection primitives for eBPF rootkits," synthesizing locked-ioc-22, locked-ioc-23, and locked-ioc-20 and proposing BPF_PROG_LOAD-time helper-function fingerprinting as a load-time detection primitive.

Sources cited for VoidLink LinkPro Atomic Arch eBPF

Other reports on CVE-2024-23897

Previous and next in malware

Drafted by the Threadlinqs research pipeline from 8 sources; published ; last updated —.

Threadlinqs Intelligence — Real-Time Threat Detection Platform

[ 0 threats ] [ 0 det ] [ CRIT: 0 ] [ HIGH: 0 ]
// threat_feed
$ sort --newest
Showing all threats

Live intelligence console

Threat level

Latest Threats