{
  "hunt": {
    "meta": {
      "tlp": "clear",
      "hunt": {
        "handoff": "promote-to-detection",
        "trigger": "intel-report",
        "methodology": "model-assisted",
        "applicability": "campaign-specific",
        "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."
      },
      "name": "VoidLink: Exploitation and Kernel-Level Implant Deployment",
      "type": "investigation",
      "labels": [
        "hunt",
        "attack.t1190",
        "attack.t1204.002",
        "attack.t1574.002"
      ],
      "series": {
        "slug": "voidlink",
        "index": 1,
        "title": "VoidLink",
        "total": 2
      },
      "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"
        }
      ],
      "targets": {
        "hunter": {
          "name": "Hunt agent",
          "agent": true
        },
        "analyst": {
          "name": "Tier-2 analyst",
          "role": "analyst"
        },
        "endpoint": {
          "name": "Endpoint telemetry (hb_ surfaces)",
          "category": "endpoint",
          "telemetry": [
            "endpoint"
          ]
        }
      },
      "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.",
      "coverage": [
        {
          "stage": "initial-access-dubbo-exploit",
          "steps": [
            "lead-dubbo-inventory",
            "suspicious-java-children"
          ],
          "status": "covered"
        },
        {
          "stage": "implant-execution-and-sideloading",
          "steps": [
            "suspicious-java-children"
          ],
          "status": "covered"
        },
        {
          "stage": "rootkit-and-privilege-escalation",
          "steps": [
            "unsigned-kernel-modules"
          ],
          "status": "covered"
        },
        {
          "stage": "internal-scanning-recon",
          "reason": "Belongs to another part of the 'VoidLink' series.",
          "status": "out_of_scope"
        },
        {
          "stage": "cloud-api-discovery",
          "reason": "Belongs to another part of the 'VoidLink' series.",
          "status": "out_of_scope"
        },
        {
          "stage": "mesh-c2-communications",
          "reason": "Belongs to another part of the 'VoidLink' series.",
          "status": "out_of_scope"
        }
      ],
      "scenario": {
        "stages": [
          {
            "name": "Apache Dubbo Java Serialization Exploitation",
            "slug": "initial-access-dubbo-exploit",
            "tactic": "initial-access",
            "techniques": [
              "T1190"
            ],
            "observables": [
              "Apache Dubbo project",
              "Java serialization vulnerabilities",
              "Pre-obtained credentials"
            ]
          },
          {
            "name": "VoidLink Implant Execution",
            "slug": "implant-execution-and-sideloading",
            "tactic": "execution",
            "techniques": [
              "T1204.002",
              "T1574.002"
            ],
            "observables": [
              "ZigLang-based implant binary",
              "DLL sideloading on Windows",
              "C-based plugins loaded via ELF linker",
              "VoidLink compile-on-demand framework"
            ]
          },
          {
            "name": "Persistence and Privilege Escalation",
            "slug": "rootkit-and-privilege-escalation",
            "tactic": "persistence",
            "techniques": [
              "T1574.002"
            ],
            "observables": [
              "eBPF rootkit",
              "Loadable Kernel Module (LKM) rootkit",
              "Container privilege escalation",
              "Docker/Kubernetes sandbox escape"
            ]
          },
          {
            "name": "Internal Network Reconnaissance",
            "slug": "internal-scanning-recon",
            "tactic": "discovery",
            "techniques": [
              "T1090.003"
            ],
            "observables": [
              "FSCAN",
              "SOCKS server on compromised hosts",
              "Scanning of entire Class C networks",
              "Internal and external network scanning"
            ]
          },
          {
            "name": "Cloud and Container Asset Discovery",
            "slug": "cloud-api-discovery",
            "tactic": "discovery",
            "observables": [
              "Kubernetes API interactions",
              "Docker API interactions",
              "Cloud-aware gathering of environment info"
            ]
          },
          {
            "name": "Peer-to-Peer Mesh C2",
            "slug": "mesh-c2-communications",
            "tactic": "command-and-control",
            "techniques": [
              "T1071",
              "T1090.003",
              "T1041"
            ],
            "observables": [
              "GoLang backend",
              "Mesh Peer-to-Peer (P2P) routing",
              "Dead-letter queue routing",
              "Encrypted/obfuscated exfiltration traffic"
            ]
          }
        ],
        "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."
      },
      "severity": "high",
      "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.",
      "guardrails": {
        "claims": "no_unsupported",
        "evidence": "citation_required",
        "telemetry": "untrusted",
        "missing_data": "not_benign"
      },
      "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.",
      "parameters": {
        "scope_hosts": {
          "type": "list[host]",
          "default": [],
          "description": "List of hostnames from the software inventory lead to focus behavioral queries."
        },
        "lookback_days": {
          "from": {
            "ref": "VoidLink analysis lookback",
            "kind": "manual",
            "observed": "2024-01-01"
          },
          "type": "number",
          "default": "14",
          "description": "Days of history to examine for process and module activity."
        },
        "rare_threshold": {
          "type": "number",
          "default": "5",
          "description": "The maximum number of hosts a process path can appear on to be considered rare."
        }
      },
      "provenance": {
        "authors": [
          {
            "org": "huntbase.io",
            "name": "Huntbase hunt generation"
          }
        ],
        "generated": {
          "by": "huntbase-hunt-generation",
          "from": "https://blog.talosintelligence.com/voidlink/",
          "gates": [
            "dry-run",
            "lint"
          ],
          "model": "hb_google/gemini-3-flash-preview"
        }
      },
      "references": [
        {
          "url": "https://blog.talosintelligence.com/voidlink/",
          "name": "Cisco Talos \u2014 VoidLink"
        }
      ],
      "blind_spots": [
        {
          "id": "no-inventory-telemetry",
          "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",
          "question": "whether Apache Dubbo is present on servers that do not report inventory",
          "requires": "hb_software_inventory for all Linux servers"
        },
        {
          "id": "ebpf-rootkit-stealth",
          "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",
          "question": "whether an eBPF rootkit is active without a traditional LKM load",
          "requires": "eBPF probe registration telemetry"
        },
        {
          "id": "no-agent-coverage",
          "risk": "The behavioural queries only cover systems where telemetry is collected; unmanaged servers exploited via Dubbo remain invisible.",
          "question": "whether VoidLink activity occurs on unmanaged or shadow IT systems",
          "requires": "Endpoint agent on high-value servers"
        }
      ]
    },
    "name": "VoidLink: Exploitation and Kernel-Level Implant Deployment",
    "description": "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."
  },
  "nodes": [
    {
      "id": "hypothesis",
      "type": "hypothesis",
      "label": "Hypothesis",
      "config": {
        "tags": [],
        "series": {
          "slug": "voidlink",
          "index": 1,
          "title": "VoidLink",
          "total": 2
        },
        "coverage": [
          {
            "stage": "initial-access-dubbo-exploit",
            "steps": [
              "lead-dubbo-inventory",
              "suspicious-java-children"
            ],
            "status": "covered"
          },
          {
            "stage": "implant-execution-and-sideloading",
            "steps": [
              "suspicious-java-children"
            ],
            "status": "covered"
          },
          {
            "stage": "rootkit-and-privilege-escalation",
            "steps": [
              "unsigned-kernel-modules"
            ],
            "status": "covered"
          },
          {
            "stage": "internal-scanning-recon",
            "reason": "Belongs to another part of the 'VoidLink' series.",
            "status": "out_of_scope"
          },
          {
            "stage": "cloud-api-discovery",
            "reason": "Belongs to another part of the 'VoidLink' series.",
            "status": "out_of_scope"
          },
          {
            "stage": "mesh-c2-communications",
            "reason": "Belongs to another part of the 'VoidLink' series.",
            "status": "out_of_scope"
          }
        ],
        "rationale": "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.",
        "blind_spots": [
          {
            "id": "no-inventory-telemetry",
            "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",
            "question": "whether Apache Dubbo is present on servers that do not report inventory",
            "requires": "hb_software_inventory for all Linux servers"
          },
          {
            "id": "ebpf-rootkit-stealth",
            "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",
            "question": "whether an eBPF rootkit is active without a traditional LKM load",
            "requires": "eBPF probe registration telemetry"
          },
          {
            "id": "no-agent-coverage",
            "risk": "The behavioural queries only cover systems where telemetry is collected; unmanaged servers exploited via Dubbo remain invisible.",
            "question": "whether VoidLink activity occurs on unmanaged or shadow IT systems",
            "requires": "Endpoint agent on high-value servers"
          }
        ],
        "scoping_notes": "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.",
        "beyond_detection": "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."
      }
    },
    {
      "id": "lead-dubbo-inventory",
      "type": "query",
      "label": "Lead: Identify Apache Dubbo software",
      "config": {
        "dsl": "sqlite",
        "role": "scoping",
        "source": "endpoint",
        "content": "SELECT device_hostname, package_name, package_version, vendor_name FROM hb_software_inventory WHERE LOWER(package_name) LIKE '%dubbo%'",
        "surface": "hb_software_inventory",
        "description": "Identify the subset of the fleet running Apache Dubbo, which UAT-9921 targets for remote code execution.",
        "expected_signal": "Hosts running Dubbo. If none are found, the likelihood of this specific exploit chain is low, though manual deployments may still exist."
      },
      "parents": [
        {
          "id": "hypothesis"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "scoping",
        "label": "Lead: Identify Apache Dubbo software",
        "reads": [
          "device_hostname",
          "package_name",
          "package_version",
          "vendor_name"
        ],
        "source": "hb_software_inventory",
        "target": "endpoint",
        "content": "SELECT device_hostname, package_name, package_version, vendor_name FROM hb_software_inventory WHERE LOWER(package_name) LIKE '%dubbo%'",
        "silence": "not_evidence_of_absence",
        "expected": "Hosts running Dubbo. If none are found, the likelihood of this specific exploit chain is low, though manual deployments may still exist.",
        "verified": "dry-run",
        "verified_at": "2026-09-20"
      }
    },
    {
      "id": "evaluate-scoping",
      "type": "analytic",
      "label": "Evaluate software lead",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint"
        ],
        "context": [
          "lead-dubbo-inventory"
        ],
        "objective": "Confirm the presence of Apache Dubbo and identify target servers for forensic analysis.",
        "description": "Determine if any host runs the vulnerable software before starting expensive telemetry queries.",
        "max_iterations": 3,
        "expected_signal": "A decision to proceed if Dubbo is present.",
        "success_criteria": "A list of hostnames to populate the scope_hosts parameter."
      },
      "parents": [
        {
          "id": "lead-dubbo-inventory"
        }
      ]
    },
    {
      "id": "gate-to-forensics",
      "type": "checkpoint",
      "label": "Gate: Proceed on software match",
      "config": {
        "question": "evaluate-scoping.rows > 0",
        "condition": "evaluate-scoping.rows > 0",
        "description": "Avoid running deep forensic queries across the entire estate if no target software is identified.",
        "checkpoint_type": "advisory"
      },
      "parents": [
        {
          "id": "evaluate-scoping"
        }
      ]
    },
    {
      "id": "suspicious-java-children",
      "type": "query",
      "label": "Rare child processes spawned by Java",
      "config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "source": "endpoint",
        "content": "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}}",
        "surface": "hb_process_activity",
        "description": "Detect the transition from Java serialization exploitation to execution of an implant, focusing on rare binaries in temporary directories.",
        "expected_signal": "Rare binaries spawned by Java in world-writable paths. A small host count indicates a targeted deployment rather than legitimate maintenance."
      },
      "parents": [
        {
          "id": "gate-to-forensics",
          "branch": "on_supports"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "label": "Rare child processes spawned by Java",
        "reads": [
          "device_hostname",
          "process_path",
          "parent_process_name",
          "time"
        ],
        "source": "hb_process_activity",
        "target": "endpoint",
        "content": "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}}",
        "silence": "evidence_of_absence",
        "baseline": {
          "window": "{{lookback_days}}d",
          "compare": "new_this_window"
        },
        "expected": "Rare binaries spawned by Java in world-writable paths. A small host count indicates a targeted deployment rather than legitimate maintenance.",
        "verified": "dry-run",
        "prevalence": {
          "by": "device_hostname",
          "key": [
            "process_path"
          ],
          "rare_below": 5
        },
        "verified_at": "2026-09-20"
      }
    },
    {
      "id": "unsigned-kernel-modules",
      "type": "query",
      "label": "Unsigned kernel modules in suspicious paths",
      "config": {
        "dsl": "sqlite",
        "role": "baseline",
        "source": "endpoint",
        "content": "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')",
        "surface": "hb_module_activity",
        "description": "Identify potential LKM rootkits deployed by VoidLink to hide its presence and the C2 server.",
        "expected_signal": "Unsigned modules loaded from temporary or hidden paths. Legitimate kernel modules are typically signed and live in /lib/modules/."
      },
      "parents": [
        {
          "id": "gate-to-forensics",
          "branch": "on_supports"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "baseline",
        "label": "Unsigned kernel modules in suspicious paths",
        "reads": [
          "device_hostname",
          "module_path",
          "module_name",
          "module_signed",
          "time"
        ],
        "source": "hb_module_activity",
        "target": "endpoint",
        "content": "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')",
        "silence": "not_evidence_of_absence",
        "baseline": {
          "window": "{{lookback_days}}d",
          "compare": "first_seen"
        },
        "expected": "Unsigned modules loaded from temporary or hidden paths. Legitimate kernel modules are typically signed and live in /lib/modules/.",
        "verified": "dry-run",
        "prevalence": {
          "by": "device_hostname",
          "key": [
            "module_name"
          ],
          "rare_below": 3
        },
        "verified_at": "2026-09-20"
      }
    },
    {
      "id": "triage-synthesis",
      "type": "analytic",
      "label": "Synthesize VoidLink evidence",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint"
        ],
        "context": [
          "evaluate-scoping",
          "suspicious-java-children",
          "unsigned-kernel-modules"
        ],
        "objective": "Determine if any host showing Dubbo software also exhibits rare Java child processes or suspicious kernel modules.",
        "description": "Combine the software context with behavioural markers to determine if a host is compromised.",
        "max_iterations": 6,
        "expected_signal": "A per-host verdict citing the inventory and activity rows.",
        "success_criteria": "A per-host verdict of malicious | suspicious | benign, citing specific binary paths and module names."
      },
      "parents": [
        {
          "id": "suspicious-java-children",
          "kind": "merge"
        },
        {
          "id": "unsigned-kernel-modules",
          "kind": "merge"
        }
      ]
    },
    {
      "id": "route-on-verdict",
      "type": "checkpoint",
      "label": "Route on verdict",
      "config": {
        "fuzzy": true,
        "judge": "hunter",
        "question": "the triage verdict is malicious for at least one host running Dubbo",
        "condition": "the triage verdict is malicious for at least one host running Dubbo",
        "blind_spot": "no-agent-coverage",
        "confidence": "high",
        "description": "Trigger isolation for high-confidence threats and review for suspicious anomalies.",
        "checkpoint_type": "mandatory"
      },
      "parents": [
        {
          "id": "triage-synthesis"
        }
      ]
    },
    {
      "id": "isolate-host",
      "type": "action",
      "label": "Isolate host",
      "config": {
        "target": "endpoint",
        "description": "Contain the threat and prevent further lateral movement or data exfiltration.",
        "instructions": "Isolate the host immediately. Preserve any artifacts in temporary directories and perform a memory dump to capture the rootkit state.",
        "action_approval": "required"
      },
      "parents": [
        {
          "id": "route-on-verdict",
          "branch": "on_supports"
        }
      ]
    },
    {
      "id": "analyst-review",
      "type": "task",
      "label": "Analyst review",
      "config": {
        "assignee": "analyst",
        "description": "Perform manual verification of the triage findings and look for additional VoidLink markers.",
        "instructions": "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."
      },
      "parents": [
        {
          "id": "route-on-verdict",
          "branch": "default"
        },
        {
          "id": "route-on-verdict",
          "branch": "on_unavailable"
        },
        {
          "id": "isolate-host"
        }
      ]
    },
    {
      "id": "close-out",
      "type": "task",
      "label": "Close out",
      "config": {
        "assignee": "analyst",
        "description": "Document the hunt results and record any tuning notes.",
        "instructions": "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."
      },
      "parents": [
        {
          "id": "gate-to-forensics",
          "branch": "on_refutes"
        },
        {
          "id": "route-on-verdict",
          "branch": "on_refutes"
        }
      ]
    }
  ]
}