← All hunts high TLP:CLEAR Part 1 of 2

Linux System Daemon Trojanization and Credential Harvesting

An adversary has established long-term persistence and credential harvesting by replacing legitimate Linux system daemons with trojanized versions that log passwords and monitor process health.

Based on research by Rapid7 2026-09-28 11 steps · 3 queries T1056.001 T1059.004 T1190 T1195.002

Brief

Why hunt for trojanized daemons

A recent report from Rapid7, DPRK APTs: Ted backdoor and curlRAT target South Korean media and automotive sectors, describes a campaign where adversaries replace legitimate Linux system binaries with malicious versions. These trojanized daemons log credentials and monitor process health to maintain persistence. Detecting these changes via simple file integrity monitoring often fails or generates excessive noise because legitimate system updates frequently modify these same paths.

How the Hunt Flows

The first phase focuses on lead discovery using the hb_file_activity surface. The query searches for specific encrypted log paths and stager configuration files associated with the Ted and CurlRAT toolkits, such as /tmp/jasper-log or specific hidden paths in /var/lib/snapd/. This step acts as a high-confidence trigger. If an analyst confirms these leads, the hunt moves into a broader expansion phase.

The expansion phase runs two parallel pivots. First, it performs a fleet-wide stack-count of binary hashes for common system daemons like sshd, crond, and agetty using hb_process_activity. The goal is to identify SHA256 hashes that appear on only one or two hosts, which suggests a non-standard or modified binary. Simultaneously, the hunt queries hb_vulnerability_finding to identify hosts running unpatched edge applications like HAProxy or vulnerable versions of polkit.

In the final stage, an analyst correlates these three signals. A host showing a rare daemon hash, known toolkit artifacts, and a high-severity edge vulnerability provides high-confidence evidence of compromise. This layered approach ensures that we only investigate binary variations that occur in a suspicious context.

What this hunt cannot see

This hunt faces two primary blind spots. First, it relies on file and process telemetry within a specific lookback window. If the adversary trojanized the system months ago and the initial file creation events have rotated out of the telemetry retention, the lead discovery step will return no results. In such cases, the hunt relies entirely on the rarity of the process hash.

Second, the effectiveness of stack-counting depends on the agent's ability to hash system daemons. If the endpoint security configuration excludes standard system paths from hashing to save performance, the hunt cannot identify trojanized outliers.

How to run the hunt

This hunt is published as an open hunt.md playbook. You can import it into Huntbase or any runtime that supports the hunt.md format. The playbook includes the necessary SQLite queries to baseline your fleet and the logic to gate the investigation, preventing unnecessary overhead on your security stack. Because this hunt targets system-level persistence, we recommend running it as a periodic check on all Linux-based edge infrastructure.

In this series

Steps

  1. Lead discovery: Known toolkit artifacts

    Query · scoping

    Find hosts where specific encrypted log paths or stager configuration files have been touched.

    reads hb_file_activitysql
    SELECT device_hostname, file_path, activity_name, time FROM hb_file_activity WHERE (instr(',' || '{{toolkit_files}}' || ',', ',' || LOWER(file_path) || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Any row naming a toolkit path on a host. Silence proves these specific IOCs are absent but does not rule out the campaign.

  2. Evaluate lead findings

    Agent triage

    Decide if the lead file activity matches the reported toolkit behavior enough to warrant expansion.

  3. Gate: Proceed to expansion

    Decision

    Restrict expensive fleet-wide stack-counting to when a lead indicator is confirmed.

  4. Stack-count daemon hashes

    Query · baseline

    Find system daemons with rare binary hashes that differ from the fleet baseline.

    reads hb_process_activitysql
    SELECT process_hash_sha256, process_path, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE (instr(',' || '{{daemon_paths}}' || ',', ',' || LOWER(process_path) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_hash_sha256, process_path HAVING host_count <= 2

    What a hit looks like. A rare SHA256 for a standard path like /usr/sbin/crond on a small number of hosts.

  5. Check for edge vulnerabilities

    Query · enrichment

    Identify if the suspected hosts run unpatched edge applications that match the reported entry vectors.

    reads hb_vulnerability_findingsql
    SELECT device_uid, affected_package_name, affected_package_version, severity_id, cve_uid FROM hb_vulnerability_finding WHERE severity_id >= 4 AND (LOWER(affected_package_name) LIKE '%haproxy%' OR LOWER(affected_package_name) LIKE '%sshd%' OR LOWER(affected_package_name) LIKE '%at%' OR LOWER(affected_package_name) LIKE '%cron%' OR LOWER(affected_package_name) LIKE '%polkit%')

    What a hit looks like. High-severity vulnerabilities on edge servers that validate the initial compromise hypothesis.

  6. Final triage of compromise

    Agent triage

    Correlate artifact findings, rare hashes, and vulnerabilities to confirm a host compromise.

  7. Route verdict

    Decision

    Initiate containment for confirmed malicious activity.

  8. Isolate host

    Response action

    Halt credential harvesting and HAProxy traffic interception.

  9. Forensic verification

    Analyst task

    Verify timestomping and log tampering on the suspect host.

  10. Close out hunt

    Analyst task

    Record final results and decide on follow-on hunts.

Coverage

Scenario coverage

StageCoveredHow, or why not
Exploitation of Edge Applications
T1190
Yes vulnerable-edge-apps
Trojanized SSHD Keylogger
T1056.001 · T1195.002
Yes lead-file-discovery
Daemon Replacement via Stager
T1195.002 · T1059.004
Yes rare-daemon-hashes
CurlRAT Command and Control
T1041 · T1059.004
Out of scope Belongs to another part of the 'DPRK APTs: Ted backdoor and curlRAT target South Korean media and automotive sectors' series.
HAProxy Traffic Interception
T1195.002 · T1056.001
Out of scope Belongs to another part of the 'DPRK APTs: Ted backdoor and curlRAT target South Korean media and automotive sectors' series.

Blind spots

  • Needs long-term file creation telemetry. A host compromised months ago will not show file-activity rows for the initial replacement, making the hunt dependent on hash rarity. It would answer Was the trojanized crond dropped before the telemetry retention window?.
  • Needs hb_process_activity with SHA256. If hashes are not captured for standard system daemons, the stack-counting step cannot identify trojanized outliers. It would answer Does the agent hash every execution of system daemons?.

Parameters & data

Parameters

ParameterTypeDefaultWhat it is
daemon_pathslist[path]/usr/sbin/sshd, /usr/sbin/crond, /usr/sbin/agetty, /usr/sbin/atd, /usr/sbin/polkitd, /usr/sbin/haproxySystem binaries targeted for replacement or backdoor insertion.
lookback_daysnumber14Days of history to examine.
scope_hostslist[host]—Hosts identified in the lead query; leave empty to scan the full estate.
toolkit_fileslist[path]/var/lib/sshd/c8c68e629bba773a10ac80012d10bf19, /tmp/jasper-log, /var/lib/snapd/g580, /var/lib/snapd/g105, /usr/lib/libvirtlog.so.0Hidden log and configuration files associated with the SSH keylogger and CurlRAT.

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 rule firing on every sshd modification causes excessive false positives
  during legitimate updates. This hunt uses a gated flow to only run expensive fleet-wide
  stack-counts when specific toolkit artifacts are found, then correlates rarity with
  vulnerability context.
blind_spots:
- id: pre-existing-compromise
  question: Was the trojanized crond dropped before the telemetry retention window?
  requires: long-term file creation telemetry
  risk: A host compromised months ago will not show file-activity rows for the initial
    replacement, making the hunt dependent on hash rarity.
  stage: persistence-stager-binary-replacement
- id: unhashed-executables
  question: Does the agent hash every execution of system daemons?
  requires: hb_process_activity with SHA256
  risk: If hashes are not captured for standard system daemons, the stack-counting
    step cannot identify trojanized outliers.
  stage: persistence-stager-binary-replacement
coverage:
- stage: initial-access-exploit
  status: covered
  steps:
  - vulnerable-edge-apps
- stage: credential-harvesting-sshd
  status: covered
  steps:
  - lead-file-discovery
- stage: persistence-stager-binary-replacement
  status: covered
  steps:
  - rare-daemon-hashes
- reason: 'Belongs to another part of the ''DPRK APTs: Ted backdoor and curlRAT target
    South Korean media and automotive sectors'' series.'
  stage: curl-rat-c2
  status: out_of_scope
- reason: 'Belongs to another part of the ''DPRK APTs: Ted backdoor and curlRAT target
    South Korean media and automotive sectors'' series.'
  stage: ted-backdoor-interception
  status: out_of_scope
guardrails:
  claims: no_unsupported
  evidence: citation_required
  missing_data: not_benign
  telemetry: untrusted
hunt:
  applicability: campaign-specific
  handoff: keep-as-periodic-hunt
  justification: DPRK APTs use deeply integrated trojanized system binaries that are
    invisible to standard monitoring; a proactive baseline of system daemon hashes
    is required to detect these modifications.
  methodology: model-assisted
  trigger: intel-report
hypothesis: An adversary has established long-term persistence and credential harvesting
  by replacing legitimate Linux system daemons with trojanized versions that log passwords
  and monitor process health.
labels:
- hunt
- attack.t1056.001
- attack.t1195.002
- attack.t1059.004
- attack.t1190
name: Linux System Daemon Trojanization and Credential Harvesting
parameters:
  daemon_paths:
    default:
    - /usr/sbin/sshd
    - /usr/sbin/crond
    - /usr/sbin/agetty
    - /usr/sbin/atd
    - /usr/sbin/polkitd
    - /usr/sbin/haproxy
    description: System binaries targeted for replacement or backdoor insertion.
    from:
      kind: article
      observed: '2026-09-04'
      ref: rapid7-dprk-ted
    type: list[path]
  lookback_days:
    default: '14'
    description: Days of history to examine.
    from:
      kind: manual
      observed: '2026-09-04'
      ref: standard-retention
    type: number
  scope_hosts:
    default: []
    description: Hosts identified in the lead query; leave empty to scan the full
      estate.
    from:
      kind: manual
      observed: '2026-09-04'
      ref: analyst-scoping
    type: list[host]
  toolkit_files:
    default:
    - /var/lib/sshd/c8c68e629bba773a10ac80012d10bf19
    - /tmp/jasper-log
    - /var/lib/snapd/g580
    - /var/lib/snapd/g105
    - /usr/lib/libvirtlog.so.0
    description: Hidden log and configuration files associated with the SSH keylogger
      and CurlRAT.
    from:
      kind: article
      observed: '2026-09-04'
      ref: rapid7-dprk-ted
    type: list[path]
provenance:
  authors:
  - name: Huntbase hunt generation
    org: huntbase.io
  generated:
    by: huntbase-hunt-generation
    from: https://www.rapid7.com/blog/post/tr-dprk-apts-ted-backdoor-curlrat-target-south-korean-media-automotive-sectors
    gates:
    - dry-run
    - lint
    model: hb_google/gemini-3-flash-preview
rationale: Focus on Linux servers running HAProxy or edge mail servers (Postfix, Exim).
  Start with a 14-day window for file activity but extend to 90 days for process hash
  baseline if results are inconclusive.
references:
- name: "Rapid7 \u2014 DPRK APTs: Ted backdoor and curlRAT target South Korean media\
    \ and automotive sectors"
  url: https://www.rapid7.com/blog/post/tr-dprk-apts-ted-backdoor-curlrat-target-south-korean-media-automotive-sectors
related:
- hunt: curl-rat-c2-behavior
  reason: If a trojanized daemon is found, the next hunt investigates its specific
    network communication patterns.
  relation: follows
scenario:
  stages:
  - name: Exploitation of Edge Applications
    observables:
    - External ports 80, 443, 25
    - Groupware login portal
    - Mail server access
    slug: initial-access-exploit
    tactic: initial-access
    techniques:
    - T1190
  - name: Trojanized SSHD Keylogger
    observables:
    - Trojanized /usr/sbin/sshd
    - Encrypted log file /var/lib/sshd/c8c68e629bba773a10ac80012d10bf19
    - Hardcoded master passwords in userauth_passwd()
    slug: credential-harvesting-sshd
    tactic: credential-access
    techniques:
    - T1056.001
    - T1195.002
  - name: Daemon Replacement via Stager
    observables:
    - Stager file /tmp/jasper-log
    - Replacement of /usr/sbin/crond
    - Timestomping crond to match /usr/bin/ssh creation date
    - Trojanized versions of agetty, atd, and polkitd
    - Filtering /root/.bash_history and /var/log/messages
    slug: persistence-stager-binary-replacement
    tactic: persistence
    techniques:
    - T1195.002
    - T1059.004
  - name: CurlRAT Command and Control
    observables:
    - HTTP POST to img.darklights.store
    - HTTP POST to img.monderhouse.space
    - User-token header containing MD5 victim ID
    - Directory /var/lib/snapd/ containing files g580, g105
    - Configuration file /tmp/nimon.unix-docbase.8564479396043450766-db6fb4443bc
    slug: curl-rat-c2
    tactic: c2
    techniques:
    - T1041
    - T1059.004
  - name: HAProxy Traffic Interception
    observables:
    - HAProxy version 2.8.12
    - Custom HAProxy filter plugin 'ted backdoor'
    - File /usr/lib/libvirtlog.so.0
    - Watchdog thread monitoring /var/run/haproxy.pid
    - Cookie stealing and script injection into web traffic
    slug: ted-backdoor-interception
    tactic: collection
    techniques:
    - T1195.002
    - T1056.001
  summary: DPRK-linked actors (likely Kimsuky or APT37) deployed a sophisticated Linux
    toolkit targeting South Korean media and automotive sectors for long-term espionage.
    The campaign features the 'TED backdoor,' a custom HAProxy filter for traffic
    interception and script injection, and 'CurlRAT,' which is embedded in trojanized
    system daemons like crond and sshd to facilitate credential harvesting and remote
    command execution.
series:
  index: 1
  slug: dprk-apts-ted-backdoor-and-curlrat-target-south-korean-media-and-automotive-sectors
  title: 'DPRK APTs: Ted backdoor and curlRAT target South Korean media and automotive
    sectors'
  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
---


# Linux System Daemon Trojanization and Credential Harvesting

This hunt targets the endpoint artifacts of the Ted and CurlRAT toolkit used against South Korean automotive and media sectors. It focuses on identifying trojanized system binaries like sshd and crond by first searching for known hidden log and configuration files. If these leads are found, the hunt expands to stack-count binary hashes across the estate to identify outliers and correlates these with high-severity vulnerabilities in edge-facing applications.

## lead-file-discovery
<!-- Lead discovery: Known toolkit artifacts -->
Find hosts where specific encrypted log paths or stager configuration files have been touched.

```sqlite target=endpoint role=scoping params=(toolkit_files=toolkit_files, lookback_days=lookback_days)
~~~yaml
expected: Any row naming a toolkit path on a host. Silence proves these specific IOCs
  are absent but does not rule out the campaign.
reads:
- activity_name
- device_hostname
- file_path
- time
silence: not_evidence_of_absence
source: hb_file_activity
verified: dry-run
verified_at: '2026-09-28'
~~~
SELECT device_hostname, file_path, activity_name, time FROM hb_file_activity WHERE (instr(',' || '{{toolkit_files}}' || ',', ',' || LOWER(file_path) || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## agent-gate-read
<!-- Evaluate lead findings -->
```agent target=hunter
cite: required
context:
- lead-file-discovery
max_iterations: 3
objective: Determine if any host shows activity matching the specific file artifacts
  of the Ted and CurlRAT toolkit.
success_criteria: A verdict citing specific hosts and paths.
tools:
- endpoint
```

## gate-decision
<!-- Gate: Proceed to expansion -->
if~: "the agent-gate-read verdict is malicious because at least one host shows a reported toolkit artifact" (confidence: high, judge=hunter)
then: → parallel-expansion
indeterminate: → close-out-task
unavailable: → close-out-task (blind_spot: pre-existing-compromise)
else: → close-out-task

## parallel-expansion
<!-- Expand investigation -->
parallel:
- → rare-daemon-hashes
- → vulnerable-edge-apps
join: → agent-final-triage

## rare-daemon-hashes
<!-- Stack-count daemon hashes -->
Find system daemons with rare binary hashes that differ from the fleet baseline.

```sqlite target=endpoint role=baseline params=(daemon_paths=daemon_paths, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
baseline:
  compare: first_seen
  window: '{{lookback_days}}d'
expected: A rare SHA256 for a standard path like /usr/sbin/crond on a small number
  of hosts.
prevalence:
  by: device_hostname
  key:
  - process_hash_sha256
  rare_below: 3
reads:
- device_hostname
- process_hash_sha256
- process_path
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-28'
~~~
SELECT process_hash_sha256, process_path, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE (instr(',' || '{{daemon_paths}}' || ',', ',' || LOWER(process_path) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_hash_sha256, process_path HAVING host_count <= 2
```

## vulnerable-edge-apps
<!-- Check for edge vulnerabilities -->
Identify if the suspected hosts run unpatched edge applications that match the reported entry vectors.

```sqlite target=endpoint role=enrichment
~~~yaml
expected: High-severity vulnerabilities on edge servers that validate the initial
  compromise hypothesis.
reads:
- affected_package_name
- affected_package_version
- cve_uid
- device_uid
- severity_id
silence: not_evidence_of_absence
source: hb_vulnerability_finding
verified: dry-run
verified_at: '2026-09-28'
~~~
SELECT device_uid, affected_package_name, affected_package_version, severity_id, cve_uid FROM hb_vulnerability_finding WHERE severity_id >= 4 AND (LOWER(affected_package_name) LIKE '%haproxy%' OR LOWER(affected_package_name) LIKE '%sshd%' OR LOWER(affected_package_name) LIKE '%at%' OR LOWER(affected_package_name) LIKE '%cron%' OR LOWER(affected_package_name) LIKE '%polkit%')
```

## agent-final-triage
<!-- Final triage of compromise -->
```agent target=hunter
cite: required
context:
- agent-gate-read
- rare-daemon-hashes
- vulnerable-edge-apps
max_iterations: 6
objective: Determine if the host is compromised by correlating toolkit artifacts,
  rare binary hashes, and edge-facing vulnerabilities.
success_criteria: A final verdict citing rows from both lead and expansion steps.
tools:
- endpoint
```

## route-verdict
<!-- Route verdict -->
if~: "the agent-final-triage verdict is malicious for at least one host" (confidence: high, judge=hunter)
then: → isolate-host
indeterminate: → forensic-verification
unavailable: → forensic-verification (blind_spot: unhashed-executables)
else: → close-out-task

## isolate-host
<!-- Isolate host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the compromised host immediately to stop the trojanized system daemons. Collect the suspect binaries for forensic analysis before reimaging.
```
→ forensic-verification

## forensic-verification
<!-- Forensic verification -->
```manual target=analyst
Inspect the suspect host for timestomping: compare the modification time of /usr/sbin/crond with /usr/bin/ssh. Search for keyword-based line removals in /var/log/secure and .bash_history using strings like 'jasper-log' or 'cron'.
```
→ close-out-task

## close-out-task
<!-- Close out hunt -->
```manual target=analyst
Document whether malicious artifacts or rare daemon hashes were confirmed. If a compromise was found, move to the CurlRAT C2 behavior hunt.
```
→ 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.