← All hunts high TLP:CLEAR Part 1 of 2

VoidLink: Exploitation and Kernel-Level Implant Deployment

An adversary has exploited a Java-based Apache Dubbo service to deploy a ZigLang-based VoidLink implant and maintained stealth using an unsigned kernel-level rootkit.

Based on research by Cisco Talos 2026-09-20 11 steps · 3 queries T1190 T1204.002 T1574.002

Brief

Why this hunt

Cisco Talos published an analysis of VoidLink, a sophisticated framework targeting Linux environments. The report, Cisco Talos — VoidLink, details how adversaries exploit Java-based services like Apache Dubbo to deploy custom implants. These attackers use ZigLang-based binaries and unsigned kernel modules to maintain persistence and evade standard monitoring. A simple detection rule for these behaviors often triggers too many alerts in complex server environments. This hunt provides a structured way to find these indicators by focusing on the relationship between vulnerable software and anomalous behavior.

How the hunt flows

The hunt begins with a scoping phase. The first query searches the software inventory to identify every host running Apache Dubbo. This middleware is a known entry point for the UAT-9921 group. By identifying these hosts first, the hunt avoids running expensive forensic queries across the entire fleet. If the hunt finds no instances of Dubbo, it stops to save resources.

Once the hunt identifies target servers, it starts a parallel forensic fan-out. The first branch looks for rare child processes spawned by Java. The query focuses on binaries executed from temporary or shared memory paths like /tmp or /dev/shm. Because legitimate Java applications rarely spawn unknown binaries from these locations, these events suggest successful remote code execution. The hunt uses a prevalence filter to ensure that only binaries appearing on a few hosts reach the analyst.

The second branch of the fan-out examines kernel module activity. It searches for unsigned modules loaded from temporary or hidden directories. VoidLink uses these modules to hide its presence and its command-and-control traffic. Legitimate modules typically reside in standard library paths and carry valid signatures. Finding an unsigned module in a world-writable path is a high-confidence indicator of rootkit activity.

In the final phase, an agent synthesizes these results. It correlates the presence of the vulnerable software with any identified process anomalies or kernel modules. This host-based context allows the hunt to produce a specific verdict. If a host running Dubbo also shows a rare Java child process and an unsigned kernel module, the hunt recommends immediate isolation.

What this hunt cannot see

This hunt has three primary blind spots. First, it relies on accurate software inventory. If a server does not report its installed packages, the scoping lead will fail, and the hunt will not examine that host. Second, the hunt focuses on traditional Linux Kernel Modules (LKM). If the adversary uses an eBPF-based rootkit, it may not appear in the module activity logs used here. Finally, the behavioral queries only protect managed systems. Any unmanaged or shadow IT systems running Dubbo remain invisible to this hunt.

In this series

Steps

  1. Lead: Identify Apache Dubbo software

    Query · scoping

    Identify the subset of the fleet running Apache Dubbo, which UAT-9921 targets for remote code execution.

    reads hb_software_inventorysql
    SELECT device_hostname, package_name, package_version, vendor_name FROM hb_software_inventory WHERE LOWER(package_name) LIKE '%dubbo%'

    What a hit looks like. Hosts running Dubbo. If none are found, the likelihood of this specific exploit chain is low, though manual deployments may still exist.

  2. Evaluate software lead

    Agent triage

    Determine if any host runs the vulnerable software before starting expensive telemetry queries.

  3. Gate: Proceed on software match

    Decision

    Avoid running deep forensic queries across the entire estate if no target software is identified.

  4. Rare child processes spawned by Java

    Query · detection candidate

    Detect the transition from Java serialization exploitation to execution of an implant, focusing on rare binaries in temporary directories.

    reads hb_process_activitysql
    SELECT LOWER(process_path) AS binary_path, parent_process_name, COUNT(DISTINCT device_hostname) AS host_count FROM hb_process_activity WHERE LOWER(parent_process_name) LIKE '%java%' AND (LOWER(process_path) LIKE '%/tmp/%' OR LOWER(process_path) LIKE '%/dev/shm/%' OR LOWER(process_path) LIKE '%/var/tmp/%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY 1, 2 HAVING host_count <= {{rare_threshold}}

    What a hit looks like. Rare binaries spawned by Java in world-writable paths. A small host count indicates a targeted deployment rather than legitimate maintenance.

  5. Unsigned kernel modules in suspicious paths

    Query · baseline

    Identify potential LKM rootkits deployed by VoidLink to hide its presence and the C2 server.

    reads hb_module_activitysql
    SELECT device_hostname, module_path, module_name, module_signed, time FROM hb_module_activity WHERE module_signed = 0 AND (LOWER(module_path) LIKE '%/tmp/%' OR LOWER(module_path) LIKE '%/.%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Unsigned modules loaded from temporary or hidden paths. Legitimate kernel modules are typically signed and live in /lib/modules/.

  6. Synthesize VoidLink evidence

    Agent triage

    Combine the software context with behavioural markers to determine if a host is compromised.

  7. Route on verdict

    Decision

    Trigger isolation for high-confidence threats and review for suspicious anomalies.

  8. Isolate host

    Response action

    Contain the threat and prevent further lateral movement or data exfiltration.

  9. Analyst review

    Analyst task

    Perform manual verification of the triage findings and look for additional VoidLink markers.

  10. Close out

    Analyst task

    Document the hunt results and record any tuning notes.

Coverage

Scenario coverage

StageCoveredHow, or why not
Apache Dubbo Java Serialization Exploitation
T1190
Yes lead-dubbo-inventory, suspicious-java-children
VoidLink Implant Execution
T1204.002 · T1574.002
Yes suspicious-java-children
Persistence and Privilege Escalation
T1574.002
Yes unsigned-kernel-modules
Internal Network Reconnaissance
T1090.003
Out of scope Belongs to another part of the 'VoidLink' series.
Cloud and Container Asset Discovery Out of scope Belongs to another part of the 'VoidLink' series.
Peer-to-Peer Mesh C2
T1071 · T1090.003 · T1041
Out of scope Belongs to another part of the 'VoidLink' series.

Blind spots

  • Needs hb_software_inventory for all Linux servers. A host without inventory reporting might be a target but will cause the lead query to return silence, skipping forensic analysis. It would answer whether Apache Dubbo is present on servers that do not report inventory.
  • Needs eBPF probe registration telemetry. VoidLink supports eBPF rootkits which may not appear as a module file on disk or a traditional .ko load event in hb_module_activity. It would answer whether an eBPF rootkit is active without a traditional LKM load.
  • Needs Endpoint agent on high-value servers. The behavioural queries only cover systems where telemetry is collected; unmanaged servers exploited via Dubbo remain invisible. It would answer whether VoidLink activity occurs on unmanaged or shadow IT systems.

Parameters & data

Parameters

ParameterTypeDefaultWhat it is
lookback_daysnumber14Days of history to examine for process and module activity.
rare_thresholdnumber5The maximum number of hosts a process path can appear on to be considered rare.
scope_hostslist[host]List of hostnames from the software inventory lead to focus behavioral queries.

Telemetry

SourceCategoryTelemetry
Endpoint telemetry (hb_ surfaces)endpointendpoint

Source

Download hunt.md Definition (JSON) An open hunt.md file; it runs anywhere that reads the format.
---
analysis: A simple rule for Dubbo exploitation or rootkit loading would generate excessive
  noise in large Linux environments. This hunt uses a gated logic to only perform
  forensic analysis on hosts with the target software, applies prevalence baseline
  counting to filter common maintenance scripts, and uses an agent to weigh multiple
  independent indicators before recommending isolation.
blind_spots:
- id: no-inventory-telemetry
  question: whether Apache Dubbo is present on servers that do not report inventory
  requires: hb_software_inventory for all Linux servers
  risk: A host without inventory reporting might be a target but will cause the lead
    query to return silence, skipping forensic analysis.
  stage: initial-access-dubbo-exploit
- id: ebpf-rootkit-stealth
  question: whether an eBPF rootkit is active without a traditional LKM load
  requires: eBPF probe registration telemetry
  risk: VoidLink supports eBPF rootkits which may not appear as a module file on disk
    or a traditional .ko load event in hb_module_activity.
  stage: rootkit-and-privilege-escalation
- id: no-agent-coverage
  question: whether VoidLink activity occurs on unmanaged or shadow IT systems
  requires: Endpoint agent on high-value servers
  risk: The behavioural queries only cover systems where telemetry is collected; unmanaged
    servers exploited via Dubbo remain invisible.
coverage:
- stage: initial-access-dubbo-exploit
  status: covered
  steps:
  - lead-dubbo-inventory
  - suspicious-java-children
- stage: implant-execution-and-sideloading
  status: covered
  steps:
  - suspicious-java-children
- stage: rootkit-and-privilege-escalation
  status: covered
  steps:
  - unsigned-kernel-modules
- reason: Belongs to another part of the 'VoidLink' series.
  stage: internal-scanning-recon
  status: out_of_scope
- reason: Belongs to another part of the 'VoidLink' series.
  stage: cloud-api-discovery
  status: out_of_scope
- reason: Belongs to another part of the 'VoidLink' series.
  stage: mesh-c2-communications
  status: out_of_scope
guardrails:
  claims: no_unsupported
  evidence: citation_required
  missing_data: not_benign
  telemetry: untrusted
hunt:
  applicability: campaign-specific
  handoff: promote-to-detection
  justification: VoidLink is a sophisticated, defense-contractor grade framework targeting
    Linux environments. Identifying its deployment through initial exploit patterns
    and kernel persistence is essential for protecting server infrastructure from
    persistent compromise.
  methodology: model-assisted
  trigger: intel-report
hypothesis: An adversary has exploited a Java-based Apache Dubbo service to deploy
  a ZigLang-based VoidLink implant and maintained stealth using an unsigned kernel-level
  rootkit.
labels:
- hunt
- attack.t1190
- attack.t1204.002
- attack.t1574.002
name: 'VoidLink: Exploitation and Kernel-Level Implant Deployment'
parameters:
  lookback_days:
    default: '14'
    description: Days of history to examine for process and module activity.
    from:
      kind: manual
      observed: '2024-01-01'
      ref: VoidLink analysis lookback
    type: number
  rare_threshold:
    default: '5'
    description: The maximum number of hosts a process path can appear on to be considered
      rare.
    type: number
  scope_hosts:
    default: []
    description: List of hostnames from the software inventory lead to focus behavioral
      queries.
    type: list[host]
provenance:
  authors:
  - name: Huntbase hunt generation
    org: huntbase.io
  generated:
    by: huntbase-hunt-generation
    from: https://blog.talosintelligence.com/voidlink/
    gates:
    - dry-run
    - lint
    model: hb_google/gemini-3-flash-preview
rationale: Focus on Linux servers running Java middleware, particularly those with
  internet exposure. The hunt starts with a wide software scan and then uses specific
  behavioural triggers to narrow the volume.
references:
- name: "Cisco Talos \u2014 VoidLink"
  url: https://blog.talosintelligence.com/voidlink/
related:
- hunt: voidlink-internal-recon-and-lateral-movement
  reason: This hunt focuses on initial deployment; a follow-on hunt is needed for
    internal scanning using FSCAN and mesh-C2 traffic.
  relation: follows
scenario:
  stages:
  - name: Apache Dubbo Java Serialization Exploitation
    observables:
    - Apache Dubbo project
    - Java serialization vulnerabilities
    - Pre-obtained credentials
    slug: initial-access-dubbo-exploit
    tactic: initial-access
    techniques:
    - T1190
  - name: VoidLink Implant Execution
    observables:
    - ZigLang-based implant binary
    - DLL sideloading on Windows
    - C-based plugins loaded via ELF linker
    - VoidLink compile-on-demand framework
    slug: implant-execution-and-sideloading
    tactic: execution
    techniques:
    - T1204.002
    - T1574.002
  - name: Persistence and Privilege Escalation
    observables:
    - eBPF rootkit
    - Loadable Kernel Module (LKM) rootkit
    - Container privilege escalation
    - Docker/Kubernetes sandbox escape
    slug: rootkit-and-privilege-escalation
    tactic: persistence
    techniques:
    - T1574.002
  - name: Internal Network Reconnaissance
    observables:
    - FSCAN
    - SOCKS server on compromised hosts
    - Scanning of entire Class C networks
    - Internal and external network scanning
    slug: internal-scanning-recon
    tactic: discovery
    techniques:
    - T1090.003
  - name: Cloud and Container Asset Discovery
    observables:
    - Kubernetes API interactions
    - Docker API interactions
    - Cloud-aware gathering of environment info
    slug: cloud-api-discovery
    tactic: discovery
  - name: Peer-to-Peer Mesh C2
    observables:
    - GoLang backend
    - Mesh Peer-to-Peer (P2P) routing
    - Dead-letter queue routing
    - Encrypted/obfuscated exfiltration traffic
    slug: mesh-c2-communications
    tactic: command-and-control
    techniques:
    - T1071
    - T1090.003
    - T1041
  summary: UAT-9921 utilizes the VoidLink modular framework, targeting Linux and Windows
    systems by exploiting Java serialization vulnerabilities in Apache Dubbo or using
    stolen credentials. The ZigLang-based implant deploys plugins for eBPF-based rootkits
    and container escapes, while conducting internal reconnaissance with FSCAN and
    establishing a peer-to-peer mesh command-and-control network.
series:
  index: 1
  slug: voidlink
  title: VoidLink
  total: 2
severity: high
targets:
  analyst:
    name: Tier-2 analyst
    role: analyst
  endpoint:
    category: endpoint
    name: Endpoint telemetry (hb_ surfaces)
    telemetry:
    - endpoint
  hunter:
    agent: true
    name: Hunt agent
tlp: clear
type: investigation
---


# VoidLink: Exploitation and Kernel-Level Implant Deployment

This hunt targets the initial stages of a VoidLink intrusion. It identifies servers running Apache Dubbo, which is a reported entry point for UAT-9921. If the software is present, the hunt triggers a gated forensic fan-out to find suspicious child processes spawning from Java and unsigned kernel modules that indicate rootkit activity. An agent then synthesizes the inventory context with the behavioural findings to identify compromised hosts.

## lead-dubbo-inventory
<!-- Lead: Identify Apache Dubbo software -->
Identify the subset of the fleet running Apache Dubbo, which UAT-9921 targets for remote code execution.

```sqlite target=endpoint role=scoping
~~~yaml
expected: Hosts running Dubbo. If none are found, the likelihood of this specific
  exploit chain is low, though manual deployments may still exist.
reads:
- device_hostname
- package_name
- package_version
- vendor_name
silence: not_evidence_of_absence
source: hb_software_inventory
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, package_name, package_version, vendor_name FROM hb_software_inventory WHERE LOWER(package_name) LIKE '%dubbo%'
```

## evaluate-scoping
<!-- Evaluate software lead -->
```agent target=hunter
cite: required
context:
- lead-dubbo-inventory
max_iterations: 3
objective: Confirm the presence of Apache Dubbo and identify target servers for forensic
  analysis.
success_criteria: A list of hostnames to populate the scope_hosts parameter.
tools:
- endpoint
```

## gate-to-forensics
<!-- Gate: Proceed on software match -->
if: `evaluate-scoping.rows > 0`
then: → forensic-fan-out
else: → close-out

## forensic-fan-out
<!-- Forensic Fan-Out -->
parallel:
- → suspicious-java-children
- → unsigned-kernel-modules
join: → triage-synthesis

## suspicious-java-children
<!-- Rare child processes spawned by Java -->
Detect the transition from Java serialization exploitation to execution of an implant, focusing on rare binaries in temporary directories.

```sqlite target=endpoint role=detection-candidate params=(lookback_days=lookback_days, scope_hosts=scope_hosts, rare_threshold=rare_threshold)
~~~yaml
baseline:
  compare: new_this_window
  window: '{{lookback_days}}d'
expected: Rare binaries spawned by Java in world-writable paths. A small host count
  indicates a targeted deployment rather than legitimate maintenance.
prevalence:
  by: device_hostname
  key:
  - process_path
  rare_below: 5
reads:
- device_hostname
- process_path
- parent_process_name
- time
silence: evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT LOWER(process_path) AS binary_path, parent_process_name, COUNT(DISTINCT device_hostname) AS host_count FROM hb_process_activity WHERE LOWER(parent_process_name) LIKE '%java%' AND (LOWER(process_path) LIKE '%/tmp/%' OR LOWER(process_path) LIKE '%/dev/shm/%' OR LOWER(process_path) LIKE '%/var/tmp/%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY 1, 2 HAVING host_count <= {{rare_threshold}}
```

## unsigned-kernel-modules
<!-- Unsigned kernel modules in suspicious paths -->
Identify potential LKM rootkits deployed by VoidLink to hide its presence and the C2 server.

```sqlite target=endpoint role=baseline params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
baseline:
  compare: first_seen
  window: '{{lookback_days}}d'
expected: Unsigned modules loaded from temporary or hidden paths. Legitimate kernel
  modules are typically signed and live in /lib/modules/.
prevalence:
  by: device_hostname
  key:
  - module_name
  rare_below: 3
reads:
- device_hostname
- module_path
- module_name
- module_signed
- time
silence: not_evidence_of_absence
source: hb_module_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, module_path, module_name, module_signed, time FROM hb_module_activity WHERE module_signed = 0 AND (LOWER(module_path) LIKE '%/tmp/%' OR LOWER(module_path) LIKE '%/.%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## triage-synthesis
<!-- Synthesize VoidLink evidence -->
```agent target=hunter
cite: required
context:
- evaluate-scoping
- suspicious-java-children
- unsigned-kernel-modules
max_iterations: 6
objective: Determine if any host showing Dubbo software also exhibits rare Java child
  processes or suspicious kernel modules.
success_criteria: A per-host verdict of malicious | suspicious | benign, citing specific
  binary paths and module names.
tools:
- endpoint
```

## route-on-verdict
<!-- Route on verdict -->
if~: "the triage verdict is malicious for at least one host running Dubbo" (confidence: high, judge=hunter)
then: → isolate-host
indeterminate: → analyst-review
unavailable: → analyst-review (blind_spot: no-agent-coverage)
else: → close-out

## isolate-host
<!-- Isolate host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host immediately. Preserve any artifacts in temporary directories and perform a memory dump to capture the rootkit state.
```
→ analyst-review

## analyst-review
<!-- Analyst review -->
```manual target=analyst
Review the cited child processes and unsigned modules. Confirm if the rare binaries use ZigLang or C as reported. Investigate the command line of the Java parent to identify the serialization exploit attempt.
```
→ end

## close-out
<!-- Close out -->
```manual target=analyst
Record the hosts scanned and the absence of matching behaviour. If many false positives occurred from legitimate Java child processes, update the rare_threshold or add exclusions for known maintenance scripts.
```
→ end

Run it

Take this hunt into your environment.

Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.

Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, then reviewed by a person.