T1587

Develop Capabilities

Resource Development Last updated:

This detection identifies indicators that adversaries have deployed custom-developed capabilities within the target environment. Because T1587 (Develop Capabilities) occurs outside the victim network during the adversary lifecycle, direct detection is impossible; instead, this rule focuses on second-order indicators: unsigned or self-signed executables executing from non-standard paths, low-prevalence binaries making network connections, and novel tooling patterns associated with bespoke malware frameworks. Groups such as Kimsuky, Moonstone Sleet, and Contagious Interview are known to develop custom tools—including malicious NPM packages, spearphishing toolkits, and custom implants—that exhibit these characteristics upon deployment. The detection correlates signature anomalies, environmental prevalence, and behavioral signals to surface likely custom-developed tools used in targeted intrusions.

What is T1587 Develop Capabilities?

Develop Capabilities (T1587) maps to the Resource Development tactic — the adversary is trying to establish resources they can use to support operations in MITRE ATT&CK.

This page provides production-ready detection logic for Develop Capabilities, covering the data sources and telemetry it touches: Microsoft Defender for Endpoint. The queries below are rated high severity at low confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Resource Development
Technique
T1587 Develop Capabilities
Canonical reference
https://attack.mitre.org/techniques/T1587/
Microsoft Sentinel / Defender
kusto
let ExcludedPaths = dynamic([
    @"C:\Windows\System32",
    @"C:\Windows\SysWOW64",
    @"C:\Program Files",
    @"C:\Program Files (x86)",
    @"C:\Windows\WinSxS"
]);
let SuspiciousSignatureStates = dynamic(["Unsigned", "SignedByUntrustedCertificate", "SignedByInvalidCertificate"]);
let LookbackWindow = ago(1d);
// Step 1: Find low-prevalence unsigned executables executing from non-standard paths
let UnsignedExecs = DeviceProcessEvents
| where TimeGenerated > LookbackWindow
| where ProcessSignatureStatus in (SuspiciousSignatureStates)
| where not(FolderPath has_any (ExcludedPaths))
| extend SuspiciousLocation = case(
    FolderPath startswith @"C:\Users\" and FolderPath has "\AppData\Local\Temp", true,
    FolderPath startswith @"C:\Users\" and FolderPath has "\Downloads", true,
    FolderPath startswith @"C:\ProgramData\", true,
    FolderPath startswith @"C:\Temp\", true,
    FolderPath startswith @"C:\Windows\Temp\", true,
    false
)
| extend RiskScore = case(
    ProcessSignatureStatus == "Unsigned" and SuspiciousLocation == true, 40,
    ProcessSignatureStatus == "SignedByUntrustedCertificate" and SuspiciousLocation == true, 35,
    ProcessSignatureStatus == "SignedByInvalidCertificate", 30,
    ProcessSignatureStatus == "Unsigned" and SuspiciousLocation == false, 20,
    10
)
| where RiskScore >= 30
| project TimeGenerated, DeviceName, AccountName, FileName, FolderPath, ProcessCommandLine, SHA256, ProcessSignatureStatus, InitiatingProcessFileName, InitiatingProcessCommandLine, RiskScore;
// Step 2: Correlate with network events to identify beaconing custom implants
let UnsignedWithNetwork = UnsignedExecs
| join kind=leftouter (
    DeviceNetworkEvents
    | where TimeGenerated > LookbackWindow
    | where RemoteIPType != "Private"
    | summarize NetworkConnections=count(), UniqueRemoteIPs=dcount(RemoteIP), RemoteIPList=make_set(RemoteIP, 5), RemotePorts=make_set(RemotePort, 5) by InitiatingProcessSHA256
) on $left.SHA256 == $right.InitiatingProcessSHA256
| extend NetworkRiskBonus = case(
    NetworkConnections > 10, 20,
    NetworkConnections > 0, 10,
    0
)
| extend TotalRisk = RiskScore + NetworkRiskBonus;
// Step 3: Deduplicate by SHA256 to surface unique custom tools
UnsignedWithNetwork
| summarize
    AlertCount = count(),
    AffectedDevices = dcount(DeviceName),
    DeviceList = make_set(DeviceName, 5),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated),
    SampleCommandLine = take_any(ProcessCommandLine),
    SampleInitiatingProcess = take_any(InitiatingProcessFileName),
    MaxRisk = max(TotalRisk),
    HasNetworkActivity = max(NetworkConnections) > 0
    by FileName, SHA256, FolderPath, ProcessSignatureStatus
| where AffectedDevices < 5  // Low environmental prevalence — likely custom tooling
| order by MaxRisk desc, AffectedDevices asc

Detects execution of unsigned or untrusted-certificate-signed binaries from non-standard filesystem paths with low environmental prevalence, optionally correlated with external network connections. This pattern is characteristic of custom-developed malware or bespoke implants deployed by threat actors following their own capability development phase. The query scores each observed binary by signature state and execution path suspiciousness, then surfaces only low-prevalence samples (seen on fewer than 5 devices) to minimize commodity software noise.

high severity low confidence

Data Sources

Microsoft Defender for Endpoint

Required Tables

DeviceProcessEvents DeviceNetworkEvents

False Positives

  • Internal development teams executing locally compiled utilities or test binaries that have not yet been signed
  • Open-source or portable applications distributed without code signing (e.g., command-line utilities, Python scripts compiled with PyInstaller)
  • Legitimate penetration testing tools (Cobalt Strike, Metasploit, custom scripts) used by authorized red team engagements
  • Software distributed via internal package managers or deployment tools that bypasses standard code signing workflows
  • Vendor-supplied diagnostic utilities that are unsigned by design

Sigma rule & cross-platform mapping

The detection logic for Develop Capabilities (T1587) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: process_creation
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Execute Self-Signed Binary from User-Writable Path (Windows)

    Expected signal: DeviceProcessEvents: FileName=custom_capability_test.exe, ProcessSignatureStatus=SignedByUntrustedCertificate, FolderPath contains \AppData\Local\Temp. DeviceImageLoadEvents showing DLLs loaded with self-signed parent process.

  2. Test 2Deploy Malicious NPM Post-Install Script (Cross-Platform)

    Expected signal: Sysmon EventCode=1 (Linux auditd execve): process spawned with ParentImage=/usr/bin/node, Image=/bin/sh or /bin/id. audit.log entries showing execve syscall from node process with working directory in node_modules path.

  3. Test 3Compile and Execute Custom ELF Binary with Network Connection (Linux)

    Expected signal: auditd: EXECVE record for /tmp/atomic_custom_tool with ppid matching shell. SOCKADDR audit record showing connect() call to 192.0.2.1:4444. Sysmon for Linux EventCode=3 (Network Connect) if deployed. /proc/<pid>/exe pointing to /tmp path.


Response Playbook

Triage

  1. Step 1: Hash enrichment — Submit the SHA256 of the flagged binary to VirusTotal, MalwareBazaar, and internal threat intelligence platforms. A zero or low detection count does NOT exonerate it — custom tools are designed to evade AV, and zero detections with no known publisher strengthens the suspicion.
  2. Step 2: Publisher verification — Check the code signing certificate issuer. Self-signed certificates or certificates issued by unknown CAs (especially with short validity windows or generic organizational names) are strong indicators of custom capability development. Verify against known legitimate publishers in your environment baseline.
  3. Step 3: Prevalence baseline — Query DeviceProcessEvents for the SHA256 across the entire tenant for the past 30 days. If this binary has appeared on only 1-2 endpoints, correlate with the user's role and recent activity. Custom implants will often appear first on initial access targets.
  4. Step 4: Behavioral analysis — Examine all child processes, network connections, registry modifications, and file writes initiated by the flagged process. Custom malware exhibits behavioral patterns inconsistent with its claimed purpose. Look for: encoded command-line arguments, LOLBAS abuse, persistence mechanisms (registry Run keys, scheduled tasks, services), and encrypted C2 traffic on non-standard ports.
  5. Step 5: User and access context — Identify who executed the binary and from what context. Was it launched by a user, a scheduled task, a service, or another process? Compare the execution account to the endpoint's normal user population. Service account execution of unsigned user-space binaries is almost always suspicious.
  6. Step 6: NPM/package ecosystem check — If the alerting device is a developer workstation and the binary was spawned from a Node.js, Python, or npm context, inspect installed packages for recently added or modified entries. Contagious Interview and Moonstone Sleet distribute custom malware as malicious npm packages.
  7. Step 7: Timeline correlation — Pull all security events for the affected device in the 24 hours preceding and following the first binary execution. Look for reconnaissance activity (T1057, T1082), lateral movement indicators, or credential access attempts that would indicate the custom tool is part of an active intrusion.

Containment

  1. Isolate the affected endpoint from the network using the EDR console (Defender for Endpoint: Device Actions > Isolate Device) if active C2 communication is confirmed or strongly suspected. Preserve the device in isolated state for forensic imaging before remediation.
  2. Block the SHA256 hash at the EDR layer using a custom indicator of compromise. Propagate the block to email gateway, proxy, and endpoint protection to prevent re-delivery across the environment.
  3. If a self-signed or untrusted code signing certificate is identified, add the certificate thumbprint to your Certificate Revocation List and configure application control policies (AppLocker, WDAC) to block binaries signed with that certificate.
  4. Suspend or reset credentials for any accounts that executed the suspicious binary, particularly if privilege escalation was observed. Invalidate Kerberos tickets and OAuth tokens for affected accounts.
  5. If the binary was delivered via a package manager (npm, pip, gem), identify the source package name and version, remove from all affected systems, and report to the registry maintainer for takedown (npmjs.org abuse report, PyPI security contact).

Evidence Collection

  1. Acquire a full memory dump of the affected process using Process Hacker, ProcDump, or the EDR's live response memory acquisition capability. Custom malware frequently decrypts payloads only in memory.
  2. Collect the binary itself and all files written to disk by the process. Use EDR live response (Defender: collect investigation package) or manual acquisition via admin share. Hash all collected files with SHA256 and SHA1.
  3. Export Sysmon operational logs (Event ID 1, 3, 7, 8, 10, 11, 12, 13) for the affected host covering the incident window. Include at minimum 6 hours before first alert and through containment.
  4. Capture all network traffic associated with the suspicious process. Extract PCAP from endpoint (if available via EDR network capture) or pull NetFlow records from network infrastructure for the source IP during the incident window.
  5. Document code signing certificate details: issuer CN, subject CN, validity dates, serial number, and thumbprint. Export the certificate from the binary using: `Get-AuthenticodeSignature -FilePath <path> | Select-Object -ExpandProperty SignerCertificate | Export-Certificate -FilePath cert.cer`
  6. Collect prefetch files from `C:\Windows\Prefetch\` for evidence of prior execution history. Parse with WinPrefetchView or Velociraptor. Prefetch records the first 8 execution timestamps and all loaded files.
  7. Export the MFT ($MFT) or targeted file system artifacts using a forensic tool (Velociraptor, KAPE) to document file creation timestamps, alternate data streams, and Zone.Identifier data showing file origin (internet-downloaded files receive Zone 3).

Escalation Criteria

  • ! Escalate immediately to IR lead if the binary establishes persistent C2 communication with an external IP, particularly if traffic uses encrypted channels on non-standard ports or mimics legitimate protocols (HTTP/S beaconing with abnormal timing).
  • ! Escalate if the same SHA256 or certificate thumbprint is detected on more than 3 endpoints, indicating broader compromise rather than isolated initial access.
  • ! Escalate if the binary is associated with known threat actor TTPs (Kimsuky mailing toolkit characteristics, Contagious Interview npm delivery pattern) as identified through threat intelligence correlation.
  • ! Escalate if privilege escalation is observed post-execution (4672 special privileges assigned, UAC bypass indicators, token impersonation events) indicating the custom tool includes exploit capabilities (T1587.004).
  • ! Escalate if lateral movement is detected within 1 hour of the initial binary execution, suggesting the custom tool is an active post-exploitation implant rather than inadvertent execution.
  • ! Escalate if any data staging or exfiltration indicators are present (large outbound transfers, archiving of sensitive directories, cloud storage uploads) concurrent with the suspicious binary activity.

Investigation Guide

Forensic Artifacts

  • > Binary on disk with signature metadata: check Zone.Identifier ADS (Mark of the Web) for download source — absence may indicate internal delivery or ADS stripping
  • > Windows Prefetch files (C:\Windows\Prefetch\<binary>-*.pf) — record up to 8 execution timestamps and all DLLs loaded
  • > Authenticode signature embedded in PE binary — extractable with sigcheck.exe, Get-AuthenticodeSignature, or pe-parse; self-signed certs have Issuer == Subject
  • > AppCompat/ShimCache (SYSTEM hive: HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache) — records executable path and last modified time
  • > Amcache.hve (C:\Windows\AppCompat\Programs\Amcache.hve) — records SHA1 hash, file path, compile time, and publisher for executed binaries
  • > NPM package.json and node_modules for developer-targeted attacks — malicious packages modify post-install scripts to execute payloads
  • > Memory forensics: PE headers injected into legitimate processes (process hollowing, reflective loading) will not have corresponding disk artifacts — requires memory acquisition
  • > Network proxy/firewall logs for C2 domain/IP resolution correlated with binary execution timestamps
  • > EDR telemetry: DeviceImageLoadEvents showing DLLs loaded by the suspicious process, especially in-memory only modules
  • > Code signing certificate store: certmgr.msc or `Get-ChildItem Cert:\ -Recurse` — adversaries may install their CA cert to make self-signed binaries appear trusted

Tuning Guidance

Because T1587 is a PRE-ATT&CK technique detected indirectly, false positive rates will be highest on developer workstations and IT admin systems. Apply the following tuning steps: (1) Build an allowlist of SHA256 hashes for known unsigned internal tools using your software inventory; add to an exclusion watchlist. (2) Create a device group baseline — exclude developer machines (identifiable by IDE installation, Visual Studio paths) from the unsigned binary alert, or reduce their severity threshold. (3) For the NPM hunting query, allowlist specific package names known to invoke system binaries as part of legitimate build processes (node-gyp, electron-builder, esbuild). (4) Tune the low-prevalence threshold (currently <5 devices) based on your environment size — large enterprises may need <50; small teams may reduce to <2. (5) Integrate VirusTotal API enrichment to auto-close alerts where VT detection ratio >5/70, allowing focus on truly novel binaries. (6) For certificate-based detections, maintain a list of approved internal code signing certificates and exclude them from the untrusted certificate path.


Hunting Queries

Hunts for unsigned or untrusted-signed binaries that also make external network connections — the combination strongly suggests a custom implant communicating with adversary-controlled infrastructure.

Hunting — KQL
kql
// Hunt: Identify binaries signed with short-lived or recently-issued certificates — a hallmark of capability development
DeviceProcessEvents
| where TimeGenerated > ago(30d)
| where ProcessSignatureStatus in ("Valid", "SignedByUntrustedCertificate")
| extend CertAge = datetime_diff('day', TimeGenerated, todatetime(ProcessVersionInfoProductVersion))
| join kind=inner (
    DeviceNetworkEvents
    | where TimeGenerated > ago(30d)
    | where RemoteIPType != "Private"
    | summarize NetCount=count(), UniqueIPs=dcount(RemoteIP) by InitiatingProcessSHA256
    | where UniqueIPs >= 1
) on $left.SHA256 == $right.InitiatingProcessSHA256
| where ProcessSignerType != "MicrosoftWindowsComponent"
| summarize TotalExecutions=count(), AffectedDevices=dcount(DeviceName), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), AvgNetConnections=avg(NetCount) by FileName, SHA256, ProcessSignatureStatus
| where AffectedDevices < 10
| order by AffectedDevices asc, AvgNetConnections desc
Hunting — SPL
spl
index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
| eval NetworkHash=MD5
| join type=inner MD5 [
    search index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=7
    | where Signed="false" OR SignatureStatus IN ("Unavailable","Invalid")
    | stats count as ImageLoadCount, dc(Computer) as HostCount by MD5, ImageLoaded, Signed, SignatureStatus
    | where HostCount < 5
    | rename MD5 as NetworkHash
]
| where DestinationIsIpv6="false" AND NOT match(DestinationIp, "^(10\\.|172\\.(1[6-9]|2[0-9]|3[0-1])\\.|192\\.168\\.)")
| stats count as NetworkEvents, dc(Computer) as NetworkHosts, dc(DestinationIp) as UniqueC2, values(DestinationIp) as C2IPs, values(DestinationPort) as Ports by Image, ImageLoaded, SignatureStatus
| sort - NetworkEvents
| table Image, ImageLoaded, SignatureStatus, NetworkHosts, UniqueC2, NetworkEvents, C2IPs, Ports

Specifically hunts for malicious npm post-install script patterns where Node.js spawns shell interpreters or download utilities — the primary delivery mechanism used by Contagious Interview and Moonstone Sleet when distributing custom malware through package ecosystems.

Hunting — KQL
kql
// Hunt: Detect malicious NPM post-install scripts executing system commands — Contagious Interview / Moonstone Sleet pattern
DeviceProcessEvents
| where TimeGenerated > ago(30d)
| where InitiatingProcessFileName in~ ("node.exe", "npm.cmd", "npx.cmd", "yarn", "pnpm")
| where ProcessCommandLine has_any ("powershell", "cmd.exe", "wscript", "cscript", "mshta", "curl", "wget", "certutil", "bitsadmin")
    or FolderPath has "node_modules"
    or (ProcessCommandLine contains "node_modules" and ProcessCommandLine contains ".js")
| extend SuspiciousPattern = case(
    ProcessCommandLine has "IEX" or ProcessCommandLine has "Invoke-Expression", "PowerShell Injection",
    ProcessCommandLine has "FromBase64String", "Base64 Decode",
    FolderPath has "node_modules" and FileName !in~ ("node.exe", "npm.cmd"), "NPM Module Execution",
    ProcessCommandLine has_any ("curl", "wget") and ProcessCommandLine has_any (".sh", ".ps1", ".exe"), "Downloader",
    "Other"
)
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, SuspiciousPattern, SHA256
| order by TimeGenerated desc
Hunting — SPL
spl
index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
| where ParentImage IN ("*\\node.exe", "*\\npm.cmd", "*\\npx.cmd", "*\\yarn", "*\\pnpm")
| where Image IN ("*\\powershell.exe", "*\\cmd.exe", "*\\wscript.exe", "*\\cscript.exe", "*\\mshta.exe", "*\\certutil.exe", "*\\bitsadmin.exe", "*\\curl.exe", "*\\wget.exe")
    OR match(CommandLine, "(?i)(IEX|Invoke-Expression|FromBase64String|downloadstring|WebClient)")
    OR match(Image, "(?i)node_modules")
| eval Severity=case(
    match(CommandLine, "(?i)(IEX|Invoke-Expression|FromBase64String)"), "CRITICAL",
    match(Image, "(?i)node_modules"), "HIGH",
    match(CommandLine, "(?i)(curl|wget).*\\.(ps1|sh|exe)"), "HIGH",
    true(), "MEDIUM"
)
| table _time, Computer, User, ParentImage, Image, CommandLine, Severity
| sort - Severity _time

Hunts for execution of binaries from user-writable or temporary paths with low host prevalence — a broad signal for any custom-developed tool regardless of signature status. Excludes common developer runtimes to reduce noise.

Hunting — KQL
kql
// Hunt: Identify self-signed certificate usage in PE execution — T1587.002 indicator
DeviceProcessEvents
| where TimeGenerated > ago(14d)
| where ProcessSignatureStatus == "SignedByUntrustedCertificate"
| where FileName !in~ ("python.exe", "python3.exe", "ruby.exe", "perl.exe")  // exclude common unsigned interpreters
| extend IsUserSpaceExecution = FolderPath startswith @"C:\Users\"
| extend IsWritablePath = FolderPath has_any (@"\Temp\", @"\AppData\", @"\ProgramData\", @"\Downloads\")
| summarize
    ExecutionCount = count(),
    AffectedHosts = dcount(DeviceName),
    HostList = make_set(DeviceName, 10),
    UserList = make_set(AccountName, 10),
    SampleCmdLine = take_any(ProcessCommandLine),
    FirstSeen = min(TimeGenerated)
    by FileName, SHA256, FolderPath, IsUserSpaceExecution, IsWritablePath
| where AffectedHosts < 5
| extend RiskFactors = toint(IsUserSpaceExecution) + toint(IsWritablePath)
| where RiskFactors >= 1
| order by RiskFactors desc, AffectedHosts asc
Hunting — SPL
spl
index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
| rex field=Hashes "SHA256=(?<SHA256>[A-Fa-f0-9]{64})"
| eval IsUserPath=if(match(Image, "(?i)C:\\\\Users\\\\"), 1, 0)
| eval IsWritablePath=if(match(Image, "(?i)(Temp|AppData|ProgramData|Downloads)"), 1, 0)
| eval RiskScore=IsUserPath + IsWritablePath
| where RiskScore >= 1
| eval ProcBasename=mvindex(split(Image, "\\\\"), -1)
| where NOT ProcBasename IN ("python.exe", "python3.exe", "ruby.exe", "node.exe", "java.exe")
| stats
    count as ExecCount,
    dc(Computer) as UniqueHosts,
    values(Computer) as Hosts,
    values(User) as Users,
    max(RiskScore) as MaxRisk,
    min(_time) as FirstSeen
    by Image, SHA256
| where UniqueHosts < 5
| sort - MaxRisk UniqueHosts
| table Image, SHA256, UniqueHosts, Hosts, Users, ExecCount, MaxRisk, FirstSeen

Atomic Red Team Tests

Test 1 Execute Self-Signed Binary from User-Writable Path (Windows)
windows

Simulates deployment of a custom-developed binary by compiling a simple C program, self-signing it with a generated certificate, and executing from a user temp directory. Validates detection of unsigned/self-signed binary execution from suspicious paths.

Command

powershell
# Step 1: Generate a self-signed code signing certificate
$cert = New-SelfSignedCertificate -Subject "CN=TestSigner" -CertStoreLocation Cert:\CurrentUser\My -Type CodeSigningCert -KeyUsage DigitalSignature
$thumb = $cert.Thumbprint

# Step 2: Create a simple test executable (uses existing system binary as proxy)
copy C:\Windows\System32\calc.exe $env:TEMP\custom_capability_test.exe

# Step 3: Sign the test binary with the self-signed certificate
Set-AuthenticodeSignature -FilePath "$env:TEMP\custom_capability_test.exe" -Certificate (Get-Item Cert:\CurrentUser\My\$thumb) -Force

# Step 4: Execute from temp path to trigger detection
Start-Process -FilePath "$env:TEMP\custom_capability_test.exe" -Wait

Write-Output "Test complete. SHA256: $((Get-FileHash $env:TEMP\custom_capability_test.exe -Algorithm SHA256).Hash)"

Cleanup

powershell
Remove-Item $env:TEMP\custom_capability_test.exe -Force -ErrorAction SilentlyContinue
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Subject -eq 'CN=TestSigner'}
if ($cert) { Remove-Item $cert.PSPath -Force }

Expected Telemetry

DeviceProcessEvents: FileName=custom_capability_test.exe, ProcessSignatureStatus=SignedByUntrustedCertificate, FolderPath contains \AppData\Local\Temp. DeviceImageLoadEvents showing DLLs loaded with self-signed parent process.

Expected Detection

KQL query should surface custom_capability_test.exe with RiskScore >= 35 (SignedByUntrustedCertificate + SuspiciousLocation=true). SPL query should detect EventCode=7 image loads with SignatureStatus=Invalid from the temp path.

Test 2 Deploy Malicious NPM Post-Install Script (Cross-Platform)
linux

Simulates the Contagious Interview and Moonstone Sleet technique of distributing custom-developed malware via malicious npm packages with post-install execution hooks. Creates a local npm package with a postinstall script that spawns a system command.

Command

bash
# Step 1: Create a malicious npm package directory
mkdir -p /tmp/atomic-npm-test/malicious-pkg
cd /tmp/atomic-npm-test/malicious-pkg

# Step 2: Create package.json with postinstall hook
cat > package.json << 'EOF'
{
  "name": "atomic-test-pkg",
  "version": "1.0.0",
  "scripts": {
    "postinstall": "node -e \"require('child_process').execSync('id > /tmp/atomic-npm-test/npm_exec_evidence.txt')\""
  }
}
EOF

# Step 3: Create parent project and install malicious package
mkdir -p /tmp/atomic-npm-test/victim-project
cd /tmp/atomic-npm-test/victim-project
cat > package.json << 'EOF'
{"name": "victim", "version": "1.0.0"}
EOF

# Step 4: Install from local path (simulates install from compromised registry)
npm install /tmp/atomic-npm-test/malicious-pkg --no-save 2>&1

echo "Evidence file:"
cat /tmp/atomic-npm-test/npm_exec_evidence.txt 2>/dev/null || echo "Execution may have been blocked"

Cleanup

bash
rm -rf /tmp/atomic-npm-test

Expected Telemetry

Sysmon EventCode=1 (Linux auditd execve): process spawned with ParentImage=/usr/bin/node, Image=/bin/sh or /bin/id. audit.log entries showing execve syscall from node process with working directory in node_modules path.

Expected Detection

SPL NPM hunting query should detect node.exe spawning system commands. The process chain npm->node->sh->id represents classic postinstall script abuse pattern associated with custom malware delivery.

Test 3 Compile and Execute Custom ELF Binary with Network Connection (Linux)
linux

Simulates an adversary deploying a custom-developed Linux implant by compiling from source and establishing an outbound connection. Tests detection of low-prevalence unsigned ELF execution with network activity.

Command

bash
# Step 1: Write a simple C implant simulator
cat > /tmp/atomic_custom_tool.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    printf("[atomic-test] Custom capability simulation running\n");
    printf("[atomic-test] PID: %d\n", getpid());
    
    // Simulate C2 beacon attempt (connects to non-routable IP for safety)
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(4444);
    addr.sin_addr.s_addr = inet_addr("192.0.2.1");  // TEST-NET — non-routable
    
    // Connection will fail safely but generates socket/network telemetry
    connect(sock, (struct sockaddr*)&addr, sizeof(addr));
    close(sock);
    
    printf("[atomic-test] Network probe complete\n");
    return 0;
}
EOF

# Step 2: Compile without debug symbols (as adversary would)
gcc -o /tmp/atomic_custom_tool /tmp/atomic_custom_tool.c -s 2>&1

# Step 3: Execute from temp path
/tmp/atomic_custom_tool

echo "Binary SHA256: $(sha256sum /tmp/atomic_custom_tool | cut -d' ' -f1)"

Cleanup

bash
rm -f /tmp/atomic_custom_tool.c /tmp/atomic_custom_tool

Expected Telemetry

auditd: EXECVE record for /tmp/atomic_custom_tool with ppid matching shell. SOCKADDR audit record showing connect() call to 192.0.2.1:4444. Sysmon for Linux EventCode=3 (Network Connect) if deployed. /proc/<pid>/exe pointing to /tmp path.

Expected Detection

SPL hunting query for unsigned binaries with network connections should surface the process. The combination of execution from /tmp with outbound connection attempt matches the behavioral pattern of custom-developed C2 implants.

Related Detections