0. Preface
These samples were pulled from a Phorpiex drop server — a bare open directory on 178.16.54.109 serving numbered executables at /1.exe through /6.exe. A shell loop asked for 2.exe up to 13.exe; everything from 7.exe onward came back empty, so the live payload set at collection time was six files. 1.exe was retrieved separately.
All six are the same program. The .text and .rdata sections are byte-identical across every build; the only differences are the PE timestamp, the PE checksum, and eleven bytes of .data holding a mutex name and an obfuscated URL path. This writeup therefore analyses one binary and treats the other five as configuration variants of it.
What the binary does is narrow and it does it at volume: it downloads lists of email addresses from its C2, and mails every address on them a sextortion note demanding $1400 in Bitcoin, with the victim’s own address forged into the From header. It has no dropper, no persistence, no credential access and no camera access. The email’s central claim — that a R.A.T. is installed and has recorded the recipient — is false, and the binary that sends it is the proof.
Everything below is static analysis. Nothing was executed, no VM was detonated, and no request was made to 178.16.54.109 during the analysis. Decompilation was done with kuna driven from the shell, cross-checked against objdump disassembly everywhere a constant or an argument order mattered.
C2, up front: http://178.16.54.109/<path>/ over plain HTTP, where <path> is one of c, cry_, ot, spm, spmm, us depending on the build. Wallet: 16pQ54sHsqQrUR2nYQsf2r7g93nwc37k2j, shared by all six.
1. The Threat at a Glance
| Attribute | Assessment |
|---|---|
| Malware type | Spam bot — sextortion mailer |
| Family | Phorpiex (Trik) spam module |
| Delivery | Dropped by a Phorpiex loader from 178.16.54.109 |
| File type | PE32 i386, Windows GUI subsystem, 18,432 bytes, not packed |
| Toolchain | MSVC 2008, linker 9.0.30729, links MSVCR90.dll by manifest |
| C2 | http://178.16.54.109/<path>/n.txt and /<path>/<k>.txt (HTTP, no TLS) |
| Target lists | email:password combo lists, cached to %temp% as .jpg |
| Outbound | Direct-to-MX SMTP on TCP/25, sender spoofed as the recipient |
| Throughput | 5,000 threads per list, roughly 19,000 messages/hour |
| Persistence | None |
| Evasion | Port-25 reachability gate, Mark-of-the-Web removal, XOR-encoded C2 path |
| Anti-analysis | None. No packing, no anti-debug, no anti-VM |
| Attribution | Phorpiex. High confidence — drop-server provenance plus an architecture match to the documented spam module |
2. The Drop Set — Six Builds in Six Minutes
Six files, six distinct hashes, one program:
| File | SHA-256 | MD5 | PE timestamp | Mutex | C2 path |
|---|---|---|---|---|---|
1.exe | 837f3b41…6503 | 7868f2ac2276680a3ddcc0ef9f886650 | 21:46:35 | 775567 | /c/ |
2.exe | 14bc3a77…fc3f | 3638e23d5a94ceaf66a65af2d3b69a75 | 21:48:33 | 9787567 | /cry_/ |
3.exe | b23943dc…1b7b | 22cebd3ccdd8efab543383d38df54381 | 21:49:52 | 6346346 | /ot/ |
4.exe | 7ec862ee…45cc | a408b814a64621c15f42b4ddfa92540b | 21:50:54 | 662466 | /spm/ |
5.exe | 02c7d7ff…15e4 | aca7c39c5104d3ce16117e040783f853 | 21:51:51 | 2525425 | /spmm/ |
6.exe | 5462d033…4ccc | 7143db771d9cd4cc578cd3117368cbbb | 21:53:08 | 277246 | /us/ |
All six timestamps fall on 2026-09-12 within six minutes and thirty-three seconds of each other. Diffing any build against 4.exe gives twelve to sixteen differing bytes, in exactly four places:
0x000e0 PE TimeDateStamp
0x00130 PE CheckSum
0x03e14 mutex name (.data, VA 0x406014)
0x03e39 tail of encoded URL (.data, VA 0x406024)
Nothing in .text or .rdata differs — cmp -l over the file range 0x400–0x3e00 returns zero differing bytes for all five comparisons. The operator rebuilt one source tree six times in one sitting, changing two config strings each time. Because the import table is identical across the set, so is the imphash: edd9caae8565fbe43a73e0ad530f325e.
The six C2 paths look like list pools rather than campaign identifiers — us reads as a region, spm and spmm as a pair, c and cry_ as something the operator tracked separately. The distinct mutex per build is what lets all six run concurrently on one infected host: each only checks for its own name.
A note on the timestamps. wget preserved the server’s Last-Modified on each download, and those values sit exactly seven hours behind the PE timestamps, consistently, with a one-to-two second build-to-upload gap:
| File | PE TimeDateStamp | HTTP Last-Modified | Delta |
|---|---|---|---|
1.exe | 21:46:35 | 14:46:36 | +6:59:59 |
4.exe | 21:50:54 | 14:50:56 | +6:59:58 |
6.exe | 21:53:08 | 14:53:10 | +6:59:58 |
Two readings fit. Either the build host wrote local time into the field and sits at UTC+7, or the web server’s clock runs seven hours slow. The first is the more economical explanation, and it would place the builder in a UTC+7 zone — but PE timestamps are a single field anyone can set to anything, so this is a weak signal and is recorded here only because the offset is so consistent. Under either reading, each file reached the server within two seconds of being built.
3. Execution Flow

4. Startup: Mutex, Mark-of-the-Web, and the Port-25 Kill Switch
Entry lands in sub_402690. It is short, and every line of it is a gate:
Sleep(2000);
CreateMutexA(0, 0, "662466");
if (GetLastError() == 0xB7) // ERROR_ALREADY_EXISTS
ExitProcess(0);
GetModuleFileNameW(0, path, 0x104);
wsprintfW(ads, L"%s:Zone.Identifier", path);
DeleteFileW(ads); // strip Mark-of-the-Web
WSAStartup(0x202, wsadata);
if (sub_401790() & 0xFF) { // port 25 reachable?
wsprintfA(cfg, "%s", sub_401030(0x406024)); // decode C2
CreateThread(0, 0, sub_402430, cfg, 0, 0);
do { Sleep(216000000); } while (1);
}
ExitProcess(0);
Three things are worth pulling out.
The mutex is the single-instance lock, and it is the only host artifact the bot creates that outlives a reboot-free session. Nothing is written to Run keys, no service is installed, no file is copied. Persistence is the loader’s job, not this module’s.
It deletes its own :Zone.Identifier alternate data stream. That stream is what records that the file came from the internet; removing it suppresses the SmartScreen and Office “downloaded from the internet” warnings for the file going forward. It is two API calls and it is the only anti-detection measure in the binary.
The main thread then sleeps for 60 hours in a loop (216000000 ms) and never exits on its own. All work happens on the controller thread.
The port-25 gate in sub_401790 is the most consequential branch in the program:
if (DnsQuery_A("yandex.ru", DNS_TYPE_MX /* 0x0F */, 0, 0, &rec, 0) == 0) {
s = sub_401710(rec->Data.MX.pNameExchange, 25);
if (s > 0) { closesocket(s); return TRUE; }
}
return FALSE;
It resolves the MX record for yandex.ru, opens a TCP connection to that host on port 25, and returns success only if the connection completes. If outbound SMTP is filtered — which it is on most consumer ISPs, most corporate egress paths, and a large share of sandbox networks — the bot calls ExitProcess and does nothing at all.
That has a practical consequence for analysis: on a host without outbound port 25, this sample looks inert. A sandbox run with no SMTP egress produces a mutex, one DNS query, one failed TCP connect, and an exit. Nothing about the mail behaviour is observable. The choice of yandex.ru is also a small shift from the publicly documented Phorpiex spam module, which probed yahoo.com and aol.com for the same purpose.
5. One Encoded String, and a Key That Collapses to a Byte
Exactly one string in the binary is obfuscated: the C2 base URL at VA 0x406024. The decoder is sub_401030:
char *decode(char *s) {
char key[] = "Tmlr"; // read from 0x4041c0
for (i = 0; i < strlen(s); i++) {
for (j = 0; j < strlen(key); j++)
s[i] ^= key[j]; // XOR against every key byte
s[i] = ~s[i];
}
return s;
}
The inner loop XORs each byte against all four key bytes in sequence, which is the same as XORing once with their cumulative XOR:
'T' ^ 'm' ^ 'l' ^ 'r' = 0x54 ^ 0x6D ^ 0x6C ^ 0x72 = 0x27
Followed by a bitwise NOT, so the whole four-byte-key scheme collapses to a single-byte XOR:
plaintext = ciphertext ^ 0x27 ^ 0xFF = ciphertext ^ 0xD8
Recovering the config is one line:
enc = bytes.fromhex('b0acaca8e2f7f7e9efe0f6e9eef6edecf6e9e8e1f7aba8b5f7')
print(bytes(b ^ 0xD8 for b in enc).decode())
# http://178.16.54.109/spm/
The key string Tmlr is identical in all six builds and sits in cleartext at 0x4041c0, four bytes ahead of the ciphertext it decodes. Everything else in the binary — the subject line, the entire email body, the wallet address, the User-Agent, the SMTP verbs — is stored as plain ASCII in .rdata and .data.
6. The Controller Thread — List Distribution
sub_402430 receives the decoded URL and runs the list loop.
It first establishes what IP the infected host presents to the world, because it needs one for the SMTP HELO:
InternetOpenA("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/202.0.4664.110 Safari/537.36", ...);
InternetOpenUrlA(h, "http://icanhazip.com/", ...);
InternetReadFile(h, buf, 99, &n);
wsprintfA(0x406058, "[%s]", buf); // "[203.0.113.7]", or "[0.0.0.0]" on failure
That User-Agent is worth noting on its own. Chrome/202.0.4664.110 is not a real Chrome build — the major version is fabricated and the rest of the string is a stale copy of a genuine one. It is used for every HTTP request the bot makes, which makes it a clean network signature.
Then the list loop:
n = atoi(download("http://178.16.54.109/spm/n.txt"));
if (n <= 0) ExitThread(0);
do {
Sleep(1000);
k = (rand() << 15 | rand()) % n + 1; // 1..n
url = L"http://178.16.54.109/spm/<k>.txt";
file = L"%temp%\\<r1><r2><r3>.jpg"; // three ints, each 1000..33766
download_to_file(url, file);
if (PathFileExistsW(file)) {
for (round = 0; round < 100; round++) {
for (t = 0; t < 50; t++) {
CreateThread(0, 0, sub_402300, 0, 0, 0);
Sleep(rand() % 50 + 50); // 50-99 ms
}
Sleep(6000);
}
DeleteFileW(file);
}
} while (atoi(download(".../n.txt")) >= 1);
n.txt is a single integer: how many lists the operator currently has published. The bot picks one at random rather than working through them in order, which spreads load across the botnet without the C2 having to assign work. The helper that picks it, sub_401000, builds a 30-bit value as (rand() << 15) | rand() before taking the modulus, because MSVC’s RAND_MAX is 32767 and the list count could exceed that.
The downloaded list is saved into %temp% with a .jpg extension and a filename built from three random integers. It is not an image; the extension is there so that a directory listing of %temp% full of JPEGs looks unremarkable. This is a long-standing Phorpiex trait and one of the better host-side indicators for the family.
The fan-out is 100 rounds of 50 threads, so 5,000 sender threads per list, with a 50–99 ms stagger inside a round and a 6-second pause between rounds. One list takes roughly 16 minutes, which puts sustained throughput near 19,000 messages per hour if delivery keeps up. The list file is deleted once the fan-out completes, and the loop re-reads n.txt and starts over. When n.txt drops below 1, the whole process exits.
7. The Sender Threads — Reservoir Sampling a Combo List
Each of the 5,000 threads runs sub_402300, which picks exactly one line from the list file:
srand(GetTickCount());
f = _wfopen(list_path, "r");
count = 0;
while (fgets(line, 0x104, f)) {
count++;
if ((double)rand() / 32767.0 <= 1.0 / (double)count)
strcpy(chosen, line); // keep this one
}
fclose(f);
That is textbook reservoir sampling with a reservoir of one — every line ends up equally likely regardless of file length, and the file is never held in memory. It is a neat choice for a thread that must handle a list of unknown size with a 260-byte stack buffer.
The line is then split:
sub_401430(chosen); // strip CR / LF in place
if (strstr(chosen, ":") && (addr = strtok(chosen, ":")))
sub_401a10(addr); // everything before ':' is the address
ExitThread(0);
The line format is email:password, and the password is parsed off and discarded. The bot never uses it, never exfiltrates it, and never attempts authentication with it. The lists are credential dumps, but this module wants only the address column — which is consistent with the email body’s claim to have “your password” being absent from this variant entirely.
Because each thread samples independently with replacement, the same address can be selected many times across 5,000 threads. The body text accounts for this directly: “To ensure you read this email, you will receive it multiple times.” That is not a threat, it is a description of a sampling bug turned into a feature.
8. The SMTP State Machine
sub_401a10 takes one address and delivers one message. It finds the domain with strchr(addr, '@') + 1, resolves that domain’s MX record via DnsQuery_A, and connects to it on port 25 directly — there is no relay, no authentication, and no TLS anywhere in the binary.
Reads go through a select with a 30-second timeout before recv. Every server response is validated by sub_4011f0, which accepts exactly three codes:
char *ok[] = { "220", "250", "354", NULL };
for (i = 0; i < 3; i++)
if (StrCmpNA(response, ok[i], 3) == 0) return 1;
return ok[3]; // NULL — any other code aborts the session
The conversation is a switch on a state variable that walks 1 → 3 → 4 → 5 → 6 → 7 → 8; any failed send or unexpected response sets it to 0 and drops the connection.
| State | Action |
|---|---|
| 1 | EHLO <public IP> if the greeting contains ESMTP, otherwise HELO <public IP> |
| 3 | MAIL FROM: <victim@example.com> |
| 4 | RCPT TO: <victim@example.com> |
| 5 | DATA |
| 6 | Forged headers, then the body in two writes |
| 7 | QUIT |
| 8 | Terminal — shutdown, closesocket |
MAIL FROM and RCPT TO carry the same address. The message is addressed from the victim to the victim, which is the mechanic behind the body’s claim: “Check the sender of this email - I have sent it from your email account!” No account was compromised; the envelope sender is simply unauthenticated text, and the bot is betting the recipient does not know that. Any receiving domain publishing SPF with a -all policy rejects this outright, since the connecting IP is a random consumer host claiming to be the recipient’s own domain.
One small implementation detail: QUIT is sent as a bare four-byte string with no trailing CRLF, unlike every other verb in the state machine. The session ends on the socket close rather than on the command.
9. Forged Headers
State 6 fabricates a plausible-looking relay history before the body. Two Received headers are prepended, both entirely synthetic:
Received: from <7 random lowercase letters> ([<1-210>.<1-254>.<1-254>.<1-254>])
by <5 random digits>.com with MailEnable ESMTP; <date>
Received: (qmail <5 random digits> invoked by uid <3 random digits>); <date>
The first octet of the fake relay IP is drawn from rand() % 210 + 1 while the other three use rand() % 254 + 1, which keeps the leading octet below the 224+ multicast range — a deliberate touch to keep the forged address in plausible unicast space. The two headers name two different mail servers (MailEnable, a Windows product, and qmail, a Unix one) in a chain that makes no sense, which is itself a signature.
The remaining headers are straightforward:
From: victim@example.com
To: victim@example.com
Subject: YOU GOT RECORDED!
Date: <weekday, day month year hh:mm:ss +zzzz>
Message-ID: <<6 digits>.<6 digits>@<5 digits>.com>
Mime-Version: 1.0
Content-type: text/plain;
Dates come from sub_4014c0, a hand-rolled RFC 5322 formatter that reads GetLocalTime and GetTimeZoneInformation and builds the offset itself from English day and month tables. It emits two variants — with and without the leading weekday — and uses the weekday-less form inside the Received headers and the full form for Date.
The random-string generator leaks a strong signature. sub_401350 builds an n-digit string, and it reseeds on every call:
char *sub_401350(int n, char *out) {
*out = 0;
srand(GetTickCount()); // reseeded every call
for (i = 0; i < n; i++)
sprintf(out, "%s%d", out, rand() % 10);
return out;
}
GetTickCount has roughly 15.6 ms resolution, and consecutive calls inside one message take microseconds. Two calls in the same tick therefore get the same seed and produce the same digit stream. This has two visible consequences in the generated mail:
- The
Message-IDis built from two separate 6-digit calls, so its two halves are normally identical —<451207.451207@38416.com>. - The qmail line’s 5-digit process id and 3-digit uid come from the same seed, so the uid is normally the first three digits of the process id —
(qmail 45120 invoked by uid 451).
Neither pattern occurs in genuine mail. Together they make a precise content signature that needs no hash and survives a rebuild.
10. The Email, and the Buffer It Overruns
The body is assembled in two chunks with strcpy followed by a chain of strcat calls, and sent as two writes. The content is the standard sextortion script: a claimed R.A.T. infection, a claimed webcam recording, a threat to share it with the recipient’s contacts, and a demand for $1400 USD in Bitcoin to 16pQ54sHsqQrUR2nYQsf2r7g93nwc37k2j, followed by a list of exchanges where the victim can buy it and a closing line advising them to change their passwords.
The assembly is careless in a way worth documenting, because it shows how little the author cared about the code once it produced output. The buffer sits at ebp-0x610 and is cleared with memset(buf, 0, 0x104) — 260 bytes. The next local up the frame is the 1,024-byte SMTP receive buffer at ebp-0x490, so there are 384 bytes of space before the two overlap. The chunks written into it are:
| Chunk | Bytes written | Space available |
|---|---|---|
| 1 (the extortion text) | 966 | 384 |
| 2 (exchanges and wallet) | 999 | 384 |
Both chunks run about 600 bytes past the end of their buffer and straight into the receive buffer. It is harmless in practice — the receive buffer is overwritten by the next recv anyway, and at 0x610 from the frame base the writes never reach the saved return address — but it is a genuine 600-byte stack overrun that the author either never noticed or never cared about. It also means the two Received headers and the body share overlapping stack memory during assembly.
11. What the Sample Is Not
Worth stating plainly, because the email works by claiming otherwise:
- There is no remote access trojan. No shell, no command handler, no file transfer, no screen or camera capture. The import table has no
gdi32, noavicap32, no COM. - There is no credential theft. The bot parses passwords out of its own target lists and throws them away. It reads no browser storage, no registry, no wallet paths.
- There is no persistence. No autorun key, no service, no scheduled task, no copy to a permanent location.
- There is no camera access of any kind. The claim to have recorded the recipient is the entire product, and it is a lie backed by nothing in the code.
The only genuine capability is outbound mail. Everything else in the message is social engineering, and a responder who finds this binary on a host should be reassuring the user on those four points rather than hunting for a stealer.
12. Attribution: Phorpiex
The provenance is the strongest part of the case — these came off a Phorpiex drop server — but the architecture matches the family’s documented spam module point for point, independently of where they were collected. Check Point’s 2019 teardown of the Phorpiex sextortion campaign describes the same design: a bot that downloads email databases from an HTTP C2, checks outbound SMTP reachability against a well-known provider’s MX record before doing anything, caches the databases in %temp% under a .jpg extension, and fans out thousands of threads that each take a random line and speak SMTP directly to the recipient’s mail exchanger.
The differences are version drift, not a different program:
| Trait | Documented 2019 module | This build |
|---|---|---|
| SMTP probe domain | yahoo.com, aol.com | yandex.ru |
| Threads per list | 15,000 | 5,000 (100 rounds of 50) |
| Demand | $800 | $1400 |
| User-Agent | Firefox 67 | Fabricated Chrome/202.0.4664.110 |
HELO identity | generated domain | public IP from icanhazip.com |
| Mark-of-the-Web | not described | :Zone.Identifier deleted at startup |
| Password column | used in some variants | parsed and discarded |
The n.txt / <k>.txt list protocol, the .jpg cache, the per-build mutex, the XOR-obfuscated C2 path and the victim-as-sender envelope are all unchanged. Confidence is high.
13. Indicators of Compromise
Files
1.exe 837f3b41488599ff02ffc32a795c073a32143349088c97f786b910c0cbe46503
2.exe 14bc3a778e14a6eef9eaec220b8902af61f153efef037280a7ce21af47ddfc3f
3.exe b23943dc5ab42e339bbc5a83bb1fa95b2bae70e7b00a8070d0de489ba9731b7b
4.exe 7ec862eeff86921c9f7c591820ca0780576d6ce13f4ddc1e690cc8342e0145cc
5.exe 02c7d7ffc279d2d791fac163ce8252bfb9f4fff406266fb69a4d381ab6e315e4
6.exe 5462d0338800b440fec5b6a6133cd943c9ef5c05883859c70fbd5326a8e54ccc
imphash (all six) edd9caae8565fbe43a73e0ad530f325e
Network
178.16.54.109 drop server and C2 (open directory, plain HTTP)
/1.exe … /6.exe payloads; /7.exe … /13.exe returned nothing
/c/ /cry_/ /ot/ /spm/ /spmm/ /us/ list directories
/<path>/n.txt list count
/<path>/<k>.txt email:password list
icanhazip.com public-IP lookup (legitimate service — do not block outright)
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/202.0.4664.110 Safari/537.36
MX lookup for yandex.ru followed by TCP/25 connect reachability probe
outbound TCP/25 to many distinct MX hosts the spam itself
Host
Mutexes: 775567 9787567 6346346 662466 2525425 277246
Files: %temp%\<3 random ints>.jpg email lists, not images
Action: deletion of the sample's own <path>:Zone.Identifier ADS
Mail content
Subject: YOU GOT RECORDED!
From and To identical, envelope sender equal to recipient
Received: from <7 lowercase letters> ([a.b.c.d]) by <5 digits>.com with MailEnable ESMTP;
Received: (qmail <5 digits> invoked by uid <3 digits>);
Message-ID: <<6 digits>.<6 digits>@<5 digits>.com> both halves usually identical
uid is usually the first three digits of the qmail process id
BTC wallet: 16pQ54sHsqQrUR2nYQsf2r7g93nwc37k2j
Demand: $1400 USD
Static markers
XOR key string "Tmlr" at VA 0x4041c0, immediately before the encoded URL at 0x406024
Effective decode: plaintext = ciphertext ^ 0xD8
18,432-byte GUI-subsystem PE32 with a manifest as its only resource — no icon, no version info
14. Detection Opportunities
- A workstation opening TCP/25 to more than a handful of distinct external hosts. Ordinary clients do not talk to arbitrary mail exchangers; mail goes to one configured server, usually on 465 or 587. This single rule catches the family regardless of build, and blocking egress on 25 for clients neutralises it entirely — the bot exits on its own when the probe fails.
- An MX lookup for
yandex.rufrom a process that is not a mail client, immediately followed by a TCP/25 connect and then a burst of further MX lookups. Message-IDwhose two dot-separated halves are identical, and qmailReceivedlines whose uid is a prefix of the process id. Both fall out of the reseeded PRNG and neither occurs in legitimate mail. These are the highest-fidelity content signatures available here.- A single message carrying both a MailEnable
Receivedand a qmailReceived, withFromequal toToand an envelope sender matching the recipient. - Files in
%temp%with a.jpgextension that are ASCII text containing@and:— the cached combo lists. Cheap to hunt for and specific to this family. - A process deleting its own
:Zone.Identifierstream within seconds of first execution. - The fabricated User-Agent.
Chrome/202.0.4664.110is not a version that exists; alerting on impossible Chrome major versions in plain-HTTP requests is a broadly useful rule. - A process creating thousands of threads in metronomic 50–99 ms intervals with 6-second pauses, each thread opening one outbound socket.
A YARA rule for this set is best anchored on the invariant content rather than the hashes: the subject string, the wallet address, the two Received format strings, and the Tmlr key sitting four bytes ahead of a byte sequence that decodes under ^ 0xD8 to http://. All of those survived six rebuilds unchanged.
15. MITRE ATT&CK Mapping
| Tactic | Technique |
|---|---|
| Execution | T1106 Native API |
| Defense Evasion | T1553.005 Subvert Trust Controls: Mark-of-the-Web Bypass; T1027 Obfuscated Files or Information; T1480 Execution Guardrails (the port-25 probe); T1070.004 Indicator Removal: File Deletion (list files) |
| Discovery | T1016.001 System Network Configuration Discovery: Internet Connection Discovery |
| Command and Control | T1071.001 Application Layer Protocol: Web Protocols; T1105 Ingress Tool Transfer (email lists) |
| Impact / downstream | T1566 Phishing — delivered to third parties from the infected host |
ATT&CK has no technique that cleanly covers “victim host used as an outbound spam relay”; the closest operator-side entry is T1584.005 Compromise Infrastructure: Botnet, which describes the resource being used rather than the behaviour on the host.
All six builds were analysed statically. Nothing was executed, no VM was detonated, and no request was made to 178.16.54.109 or to any mail server during the analysis — the C2 URLs were recovered by decoding the .data blob offline, and the SMTP conversation was reconstructed from the decompiled state machine rather than captured. The email body is reproduced only in summary; the wallet address and subject line are published because they are the useful indicators.