jafeeri/wannacry-malware-analysis

GitHub: jafeeri/wannacry-malware-analysis

一份针对 WannaCry 勒索蠕虫的全面恶意软件分析报告,涵盖静态分析、动态分析和逆向工程。

Stars: 0 | Forks: 0

# WannaCry Ransomware — Full Malware Analysis **Static analysis · Dynamic analysis · Reverse engineering of a self-propagating ransomware worm** ![Type](https://img.shields.io/badge/Sample-WannaCry%20%2F%20WanaCryptor-critical) ![Class](https://img.shields.io/badge/Class-Ransomware%20%2B%20Worm-red) ![Arch](https://img.shields.io/badge/Binary-PE32%20x86-blue) ![Tools](https://img.shields.io/badge/Tools-Ghidra%20%7C%20PEStudio%20%7C%20FLOSS%20%7C%20Wireshark-informational) ![Detection](https://img.shields.io/badge/VirusTotal-68%2F70-critical) **Analyst:** Ali Mehdi Jafeeri · **Date:** July 2026 ## ⚠️ Safety Notice ## Table of Contents - [Executive Summary](#executive-summary) - [Why This Sample](#why-this-sample) - [Laboratory Environment](#laboratory-environment) - [Phase 1 — Sample Identification](#phase-1--sample-identification) - [Phase 2 — Static Analysis](#phase-2--static-analysis) - [Phase 3 — Dynamic Analysis](#phase-3--dynamic-analysis) - [Phase 4 — Payload Extraction & Reverse Engineering](#phase-4--payload-extraction--reverse-engineering) - [MITRE ATT&CK Mapping](#mitre-attck-mapping) - [Indicators of Compromise](#indicators-of-compromise) - [YARA Detection Rule](#yara-detection-rule) - [Defensive Recommendations](#defensive-recommendations) - [What I Learned](#what-i-learned) - [References & Prior Work](#references--prior-work) ## Executive Summary WannaCry is a **hybrid threat**: a self-propagating network worm carrying a file-encrypting ransomware payload. This analysis established its full behaviour through three coordinated phases — static characterisation without execution, controlled detonation under instrumentation, and source-level reverse engineering in Ghidra. ### Key findings | # | Finding | |---|---| | 1 | The sample masquerades as a **Microsoft disk utility**, is **unsigned**, carries a **forged 2010 compile timestamp**, and was distributed as `invoice_greenanimals.pdf.exe` — a double-extension lure. 68/70 engines detect it. | | 2 | **Three capabilities were proven statically, without executing the file:** mass file encryption (AES round tables + CryptoAPI in the image), autonomous SMBv1 propagation (a full downgrade-negotiation client), and privileged persistence (complete service-control API set). | | 3 | The file is a **three-layer nested container** — a readable ~5% loader wrapping a 94.4% high-entropy resource, which is itself a PE containing a password-protected 36-file archive. | | 4 | Behaviour is gated by a single network check (the **kill switch**), demonstrated experimentally **in both directions** and then confirmed in the decompiled code. | | 5 | On detonation: dropped its toolkit to `C:\ProgramData`, installed auto-start service **`mssecsvc2.0`** granting **SYSTEM**, destroyed all recovery options, encrypted files at 6.65 MB/s, demanded Bitcoin, and scanned the internet for further SMB victims. | | 6 | **Propagation failed** against a patched target — a direct demonstration that MS17-010 patching neutralises the worm. | | 7 | Complete **C2 infrastructure (5 Tor hidden services)** was recovered **statically**, with zero network contact. | ## Why This Sample This is the second specimen in a two-sample series. The first was **RedLine Stealer** — a covert infostealer. WannaCry inverts every one of its assumptions, and the contrast drives several observations throughout this analysis: | | RedLine (sample 1) | WannaCry (sample 2) | |---|---|---| | **Objective** | Harvest credentials covertly | Deny access and extort | | **Delivery** | Delivered by operator | **Self-propagating (SMBv1 / MS17-010)** | | **Concealment** | Packed loader + **process hollowing** | **Nested container** (PE → PE → encrypted ZIP) | | **Code visibility** | Hidden until unpacked in memory | **Loader readable; only cargo encrypted** | | **Payload recovery** | Memory dump (pe-sieve / dnSpy) | **Static resource extraction — no execution** | | **Persistence** | None — grab-and-go | Service `mssecsvc2.0`, auto-start, SYSTEM | | **Privileges** | User context | **SYSTEM** | | **Attacks** | Confidentiality | **Availability + integrity** | **The lesson:** the concealment strategy an attacker chooses dictates the recovery strategy the analyst must use. RedLine hid its *code* and forced a memory dump. WannaCry hides its *cargo* but leaves its *brain* in the open — so its entire decision structure was recoverable from a file that was never executed. ## Laboratory Environment Because the specimen is both destructive and self-propagating, containment was designed **before** the sample was unpacked. A worm does not need a second manual execution to spread — one run is enough for it to begin attempting outbound connections. Containment therefore could not depend on operator discipline during the run; it had to be **structural**, enforced by the hypervisor. | Host | Address | Role | |---|---|---| | Windows 10 (FLARE-VM) | `192.168.56.20` | Victim / detonation host, static tooling | | REMnux | `192.168.56.102` | Gateway, DNS sinkhole (dnsmasq), fake services (INetSim) | | Network | `192.168.56.0/24` | VirtualBox **Host-Only** — no external route | The victim's gateway and DNS both pointed at REMnux, so every packet and name resolution passed through infrastructure under observation. Shared folders, clipboard, drag-and-drop and USB passthrough were all disabled; the VM was reverted to a clean snapshot between every experiment. **Toolset:** VirusTotal · MalwareBazaar · HashMyFiles · Detect It Easy · PE Detective · CFF Explorer · PEStudio · FLOSS · Ghidra 12.1.2 · Resource Hacker · 7-Zip · HxD · Process Monitor · Process Hacker · Regshot · Wireshark · dnsmasq · INetSim ## Phase 1 — Sample Identification Analysis began by confirming the specimen obtained is the specimen intended for study. Malware families have thousands of variants, and analysing one while reasoning from notes on another produces conclusions that are confidently wrong. | Property | Value | |---|---| | **SHA-256** | `24d004a104d4d54034dbcffc2a4b19a11f39008a575aa614ea04703480b1022c` | | **SHA-1** | `e889544aff85ffaf8b0d0da705105dee7c97fe26` | | **MD5** | `db349b97c37d22f5ea1d1841e3c89eb4` | | File size | 3,723,264 bytes (3.55 MiB) | | Distribution name | `invoice_greenanimals.pdf.exe` (double-extension lure) | | Masquerade name | `lhdfrgui.exe` (genuine Disk Defragmenter filename) | | imphash | `9ecee117164e0b870a53dd187cdd7174` — shared with 82 WannaCry samples | ![VirusTotal](https://static.pigsec.cn/wp-content/uploads/repos/cas/b1/b14b5fb140705b3b907a5c9611dbe0d39e64f3270a590b37ce933453ee68ddf5.png) *68 of 70 engines flag the file. Threat categories: **trojan**, **ransomware** and **worm** simultaneously.* Three details here outweigh the detection ratio. The **triple categorisation** announces a hybrid — a component that spreads autonomously bolted onto a component that extorts. The **behavioural tags** (`detect-debug-environment`, `checks-network-adapters`, `long-sleeps`, `exploit`) each predict a mechanism to confirm or refute from the binary. Most informative are the **CVE tags**: `CVE-2017-0144` and `CVE-2017-0147` are the MS17-010 SMBv1 vulnerabilities. Their presence means the sample does not merely *use* the network — it *attacks* it, with a pre-authentication RCE against a service enabled by default. **This single observation justified the entire Host-Only lab design.** ![MalwareBazaar hashes](https://static.pigsec.cn/wp-content/uploads/repos/cas/84/847e75dc8149e7ec454c5be130562589061882ba87bbf40d48318529bbbf546b.png) *Repository metadata — already signature-tagged WannaCry, imphash shared with 82 samples.* ![TrID](https://static.pigsec.cn/wp-content/uploads/repos/cas/a6/a67c49c6540c8b419f56088dbb9cac97328738fc9a890ff43c8c2045c7fc8055.png) *Content-based typing identifies a Win32 MSVC executable independent of its deceptive filename.* ![Download](https://raw.githubusercontent.com/jafeeri/wannacry-malware-analysis/main/images/F02-malwarebazaar-download.png) *Samples are distributed password-protected so they cannot execute accidentally or be quarantined mid-download.* ![Staged](https://static.pigsec.cn/wp-content/uploads/repos/cas/6e/6e7e34d9ccb3fb4f7cd396aa7cc00e430505b9124463da5c6062e018a21db1ab.png) *Sample staged inside the isolated VM, still archived. Transfer used a temporary NAT adapter inside the guest, returned to Host-Only before extraction — the file never touched the host filesystem.* ![Hash verification](https://static.pigsec.cn/wp-content/uploads/repos/cas/ee/ee55f8416f36b18cbdf845daa0efdab81ad1df809c74fc1633d8b28010b138ff.png) *Independent verification: byte-identical to published values. Every subsequent finding is anchored to this exact artefact.* ## Phase 2 — Static Analysis ### 2.1 File type, provenance and packing ![Detect It Easy](https://static.pigsec.cn/wp-content/uploads/repos/cas/39/39c38dbae317d3b1eb9ed65e056f58fda1f1d829775f24eaa51d0a36363a7b96.png) *The densest single result of the static phase.* DIE identifies a **PE32 (32-bit) GUI executable** built with **Visual Studio 6.0**. Three results drove everything that followed: 1. The heuristic flags `.rsrc` as **compressed/packed high-entropy data** 2. A **nested PE32** at offset `0x000320A4`, size `0x0035A000` — an entire second executable 3. Inside that, an **encrypted ZIP archive (Zip 2.0), 55.8%, 36 files** **On the compile timestamp:** DIE reads November 2010, yet the sample carries exploits for vulnerabilities patched in March 2017. A binary cannot contain a working exploit for a bug that will not be publicly known for another six years. The timestamp is **forged** — and forged consistently with the version resource, which claims to be a 2010 Windows 7 component. That is deliberate provenance falsification, not a compiler artefact. **On the compiler:** Visual Studio 6.0 was obsolete by 2017. It produces small binaries linking against `MSVCRT.DLL`, present on every Windows install without redistributables. For a worm that must run on arbitrary unknown hosts, maximum compatibility beats modern language features. ![Entropy](https://static.pigsec.cn/wp-content/uploads/repos/cas/e9/e92af0f5b5fe9ece58ca12d19802959babf4f8c8acff9077d2dc14fc0d92d035.png) *Overall file entropy 7.96/8.0 ("packed, 99%") — but `.text` measures only 6.13.* Entropy measures information density per byte; encrypted or compressed data approaches 8.0 because it removes the redundancy that lowers the score. The **per-region breakdown is what makes this diagnostic**: | Region | Entropy | Status | |---|---|---| | PE header | 0.727 | not packed | | `.text` (code) | **6.135** | **not packed** | | Whole file | **7.964** | **packed** | The executable code is **not** packed. This distinguishes a **container** (a readable loader shipping an encrypted cargo) from a **packer** (compressed code reconstructed at runtime). WannaCry is a container — an enormous analytical advantage, because the loader's logic is fully available to static analysis, which is exactly why Phase 4 succeeded without execution. ![PE Detective](https://static.pigsec.cn/wp-content/uploads/repos/cas/04/04cf345b0ac235bebfaa9e699d985e6e8bf576f50fa7bbab1268229ca27e5195.png) *Independent corroboration: Microsoft Visual C++ 6.0, nine signature families.* The low-confidence `Armadillo v1.71` match is a **known false positive** keyed on entry-point byte patterns that plain MSVC 6.0 also produces. I record it rather than discarding it silently — reporting only the convenient result is how analysis becomes advocacy. ### 2.2 Metadata and the masquerade ![CFF Explorer](https://raw.githubusercontent.com/jafeeri/wannacry-malware-analysis/main/images/F22-cff-explorer.png) *Header parsing and version resource: "Microsoft® Disk Defragmenter", `lhdfrgui.exe`.* ![PEStudio overview](https://static.pigsec.cn/wp-content/uploads/repos/cas/d4/d44adb7b767e80a026cd398ac2fdba8c9bb1c39d72ed90f0bd31102987d2f452.png) *Note `certificate > n/a` — **the file is unsigned**.* ![DIE version strings](https://static.pigsec.cn/wp-content/uploads/repos/cas/f9/f9b1e80c1bb229891cd61805636df2056f688b2946f7da3fa7aa35d5a006a637.png) *The raw version-resource strings as stored in `.rsrc` — the free-text fields that constitute the masquerade.* Every claimed value is false. The author copied authentic metadata from a real Microsoft binary. But **the file is unsigned**, and that collapses the masquerade: authentic Microsoft binaries are Authenticode-signed, whereas version strings are free text any compiler embeds on request. ### 2.3 String and capability extraction (FLOSS) FLOSS runs conventional extraction, then *emulates* each function to recover **stack strings** (assembled character-by-character at runtime, so they never appear contiguously) and **decoded strings**. This matters against malware specifically, because authors know `strings` is the first tool anyone runs. ![FLOSS launch](https://static.pigsec.cn/wp-content/uploads/repos/cas/72/725b97de02414eb67e96b9dd6e8d2bf47b5b4a56327c892e4f406c13bb08bb7d.png) **87 functions analysed · 15 stack strings · 6 decoded strings · 299 UTF-16 strings** #### SMB protocol strings — the worm component ![SMB dialects](https://static.pigsec.cn/wp-content/uploads/repos/cas/3e/3e76175bca8486ef850a89ab795b3804546144342cbd10bd7be6bdb933d8b5d1.png) SMBu SMBr SMBs SMB2 PIPE PC NETWORK PROGRAM 1.0 LANMAN1.0 Windows for Workgroups 3.1a LM1.2X002 LANMAN2.1 NT LM 0.12 Windows 2000 2195 /K__USERID__PLACEHOLDER__ This is the most informative static evidence of propagation. The list from `PC NETWORK PROGRAM 1.0` through `NT LM 0.12` is the **dialect array sent in an SMB negotiation request**. A modern Windows client negotiates SMB2 or SMB3; offering the *complete historical list* beginning with 1980s LAN Manager dialects is code deliberately negotiating **downward to SMBv1** — because MS17-010 exists only in SMBv1. **The exploit does not work against SMB2**, so the malware must first talk the victim's server into speaking an obsolete protocol. `IPC$` is the named-pipe endpoint the exploit targets. ![Stack strings](https://static.pigsec.cn/wp-content/uploads/repos/cas/f6/f6e1082d15d93b51ecb789792b74e2a40c83565ccc72fe354a1be6d428fb2ad5.png) *FLOSS summary. The "decoded" output (`AWAVAUATSQRUWVPP`, `XX^_]ZY[A\A]A^A_H`) is not text — these are **x86-64 register save/restore sequences** misread as strings. Their presence matters: 64-bit instruction patterns inside a 32-bit binary indicate **embedded 64-bit shellcode**, which is what MS17-010 requires to run in the kernel-mode SMB driver on x64 targets.* #### Target file extensions — the encryption scope ![Extensions](https://static.pigsec.cn/wp-content/uploads/repos/cas/ce/cebc957a7bb88e6386c4ffbe7c0da54bc32e57769fe13e711b6b4ce2fae95b77.png) The list is notable not for its length but its **composition**, segmented by victim type: - **Office/productivity** (`.doc`, `.docx`, `.ods`) — general users - **Databases** (`.mdf`, `.ldf`, `.myd`, `.myi`, `.ibd`, `.accdb`) — SQL Server, MySQL, Access. *Server* artefacts - **Source code** (`.cpp`, `.java`, `.asm`, `.sln`, `.suo`) — developer machines - **Scripts** (`.ps1`, `.bat`, `.cmd`, `.vbs`) — administrator tooling; attacks the *recovery capability itself* - **Engineering** (`.max`, `.3dm`, `.brd`, `.sch`) — irreplaceable professional work Ransomware pricing depends on the victim's cost of *not* paying. A list weighted toward databases, source code and engineering data is optimised for victims whose downtime is expensive and whose data is unique — exactly the profile that pays. #### Component filenames and 28 localisations ![Components](https://static.pigsec.cn/wp-content/uploads/repos/cas/f3/f327ce8626852603ccda12afbe66d1e0f620360520ac536057bfce8f8f6299a9.png) Twenty-eight localisations of the ransom note, bundled **before a single victim is infected**. Localisation is expensive and pointless for a targeted attack, where one language suffices. Twenty-eight languages selected at runtime from the victim's system locale is the signature of an operation designed for **indiscriminate global distribution** — consistent with a worm, which cannot choose whom it reaches. ![Version impersonation](https://static.pigsec.cn/wp-content/uploads/repos/cas/bf/bf9956dbcac5d5f66e2a49d926475dacbd6837a0a0d27152f941a81d979cb33b.png) *Two distinct version-info blocks in one binary.* The outer file poses as **Disk Defragmenter** (`lhdfrgui.exe`); a second complete block impersonates **DiskPart** (`diskpart.exe`). Since a PE has exactly one version resource of its own, the second belongs to the **embedded executable**. The masquerade is layered — and both choices are deliberate: disk utilities are exactly the class of program a user *expects* to consume CPU and touch every file on the volume, which is a precise description of ransomware encrypting. *(Confirmed at runtime in Phase 3 — the running payload displays the description "DiskPart".)* The path templates `%s\ProgramData` and `%s\Intel` in the same view predicted the install location, also later confirmed. ![UTF-16 strings](https://static.pigsec.cn/wp-content/uploads/repos/cas/43/4330e1bffaced49f80b891703e3299ed837bc76f377c0688a77e3a0d811d8a52.png) *Predominantly C-runtime diagnostics and calendar names — library noise distinguished from author-written content.* ![Entropy noise 1](https://static.pigsec.cn/wp-content/uploads/repos/cas/b3/b3fa3f8d5170d7b712ed68fecdc4866bd7238118523f425631718bc5e7e930ff.png) ![Entropy noise 2](https://static.pigsec.cn/wp-content/uploads/repos/cas/95/954910424b806f4ea63d52e596c49d62975532617f220f804ff92211cd27bd04.png) *The visual signature of the encrypted archive occupying ~94% of the file — no intelligible strings.* ### 2.4 Imports — capability inference ![Imports](https://static.pigsec.cn/wp-content/uploads/repos/cas/40/40aa9c37c83f6ca358685a1aaf69dfdf56f640281ecf1490270d8c1217ec5a29.png) *91 imports across 7 libraries, 30 flagged.* The import table is a **declaration of intent** — a program cannot call an API it has not resolved. | Library | Key functions | Capability | |---|---|---| | **ADVAPI32** | `OpenSCManagerA`, `CreateServiceA`, `StartServiceA`, `StartServiceCtrlDispatcherA` | **Service install + service-mode execution → persistence at SYSTEM** | | **ADVAPI32** | `CryptAcquireContextA`, `CryptGenRandom` | Cryptographically secure key generation | | **WS2_32** | `socket`, `connect`, `send`, `recv`, `select` *(by ordinal)* | Raw TCP client — SMB propagation | | **WININET** | `InternetOpenA`, `InternetOpenUrlA`, `InternetCloseHandle` | **The kill-switch check** | | **IPHLPAPI** | `GetAdaptersInfo`, `GetPerAdapterInfo` | Network enumeration — deriving the subnet to scan | | **KERNEL32** | `FindResourceA`, `LoadResource`, `LockResource`, `SizeofResource` | Embedded payload extraction | Four observations beyond reading the table: - **The service APIs form a complete set** covering both *installation* and *service-mode execution* — so the binary runs in **two modes**: once as a user-launched installer, again as the service. - **`GetAdaptersInfo` is targeting infrastructure.** Reading the local interface config yields the subnet to scan. Combined with `rand`/`srand`, it supports the dual local-sweep + random-internet strategy. - **`CryptGenRandom` is the cryptographically secure choice.** Ransomware families that used a predictable PRNG have been broken by researchers reconstructing the seed. This forecloses that route. - **WS2_32 is imported by ordinal**, so networking function *names* never appear as strings — naive string-based triage finds nothing. **What's absent is also informative:** neither `WriteFile` nor any `CreateProcess` variant appears, despite both being used at runtime, while `GetProcAddress` and `GetModuleHandle` *are* present. This indicates **dynamic API resolution** — the noisiest, most-monitored functions are looked up at runtime to keep them out of the static import table. ### 2.5 Cryptographic and anti-analysis signatures ![Crypto signatures](https://static.pigsec.cn/wp-content/uploads/repos/cas/a9/a901e255b22861166db055111c5f58470b08e7babaa2e58f9fbcbb4bbfaffa7f.png) | Offset | Signature | Significance | |---|---|---| | `0x0003AAA0` | AES Rijndael S-box | AES substitution table | | `0x0003ACA0`–`0x0003B8A0` | Rijndael `Te0`–`Te3` | AES **encryption** round tables | | `0x0003C0A0`–`0x0003C8A0` | Rijndael `Td1`–`Td3` | AES **decryption** round tables | | `0x000411A4` / `0x00041174` | `CryptImportKey` / `CryptDecrypt` | CryptoAPI key handling | | `0x0003EF10`–`0x0003F080` | `zinflate_*` | DEFLATE — the ZIP extractor | | **`0x000197F4`** | **anti-debug: `IsDebuggerPresent`** | **Anti-analysis** | Locating **full AES round tables statically** confirms symmetric encryption is implemented natively. The presence of *both* forward (`Te`) and inverse (`Td`) tables shows the same code can encrypt **and** decrypt — architecturally necessary, because the operator must be able to decrypt for payment to be plausible. **The decryption capability ships with the malware; only the key is withheld.** Combined with the CryptoAPI imports this is the classic **hybrid scheme**: AES for fast bulk file encryption, RSA to wrap the AES key so only the operator's private key recovers it. `IsDebuggerPresent` confirms the `detect-debug-environment` tag and establishes the author anticipated analysis. A shallow check, but a real one. ### 2.6 The embedded payload — the decisive finding ![Resources](https://static.pigsec.cn/wp-content/uploads/repos/cas/a0/a0e0d2acce9ed6a3bdea3e85f879e192f78e679c882da35389b398d9af2f2ba1.png) | Name | Location | Size | Entropy | Signature | First bytes | |---|---|---|---|---|---| | `version` | `0x0038C0A4` | 944 B | 3.532 | version | `B0 03 34 00` | | **`R` / 1831** | **`0x000320A4`** | **3,514,368 B** | **7.995** | **executable** | **`4D 5A` = `MZ`** | Resource **`R`/1831 contains 94.4% of the entire file** at essentially maximum entropy, and PEStudio identifies it as an **executable** beginning with the `MZ` magic. The outer program is a **delivery wrapper**: ~5% is code that runs; 94% is cargo. Cross-referencing the DIE scan, the complete architecture resolves to **three layers**: wannacrymalware.exe ← Layer 1: worm / dropper (readable, ~5%) └── .rsrc → resource "R" / 1831 ← Layer 2: tasksche.exe, a full PE (94.4%) └── .rsrc → encrypted ZIP, 36 files ← Layer 3: the ransomware toolkit └── password: WNcry@2ol7 ← recovered in Phase 4 Each layer serves a distinct purpose. Layer 1 decides *whether* to act (kill switch) and *how to spread* (SMB). Layer 2 handles installation, persistence and encryption. Layer 3 holds supporting assets. **A scanner must defeat all three layers to reach the payload**, and the innermost is protected by a password existing only in the middle layer's code — so static signatures written against the payload *never match the delivered file*. ## Phase 3 — Dynamic Analysis ### 3.1 The kill switch — the controlling variable Static analysis established the binary's first action is an HTTP request to one hardcoded domain, and that the result governs everything. It could not determine the **polarity** of that decision — so it was derived experimentally, then confirmed in the disassembler. hxxp://www[.]iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea[.]com - **Request succeeds** → the sample **terminates**. Nothing is encrypted. - **Request fails** → **full ransomware and worm routine**. The logic is **inverted** relative to normal sandbox evasion. Rather than looking for evidence a sandbox is *present*, it looks for evidence a domain that *should not exist* resolves anyway. On the real internet a long random domain resolves to nothing; inside a sandbox faking all DNS, it resolves fine. **Successful resolution is treated as proof of an artificial environment.** #### Run A — kill switch REACHABLE (predicted: no encryption) ![Run A dnsmasq](https://static.pigsec.cn/wp-content/uploads/repos/cas/3d/3d1ece9d108b5f78147c0ff93d00f7ab354d2fbe84348603749fefe80f7fbd88.png) *The first packet the malware generates — before touching a single file, it asks whether this domain exists.* ![Run A Wireshark](https://static.pigsec.cn/wp-content/uploads/repos/cas/42/421a8b1c253e9602e3a1a309c2d781ed21b5c58bed9daee96126afb27b876e72.png) *The complete transaction: DNS resolution (5–6), TCP handshake (7–9), `GET /` (10), `HTTP/1.1 200 OK` from INetSim (15), `RST` (16).* **Result: the process exited.** No encryption, no wallpaper change, no ransom note, no service. A synthetic `200 OK` from my own fake web server was enough to shut the malware down completely. *(The ICMP traffic to 8.8.8.8 / 1.1.1.1 in the capture is Windows' own connectivity checking, not malware activity. Distinguishing guest-OS noise from sample behaviour is a necessary discipline.)* ![Run A nslookup](https://static.pigsec.cn/wp-content/uploads/repos/cas/b7/b7e4abac0ba316a300c42baa82674dd960fc3c91ec4ed423ca842860a244782b.png) *Manual confirmation of the Run A DNS state.* #### Run B — kill switch UNREACHABLE (predicted: full detonation) Reverted to clean snapshot, then broke **only** that domain — keeping the rest of the sinkhole intact to retain full DNS visibility. dnsmasq applies specific rules ahead of the wildcard: sudo dnsmasq -d --conf-file=/dev/null --no-resolv \ --listen-address=192.168.56.102 --bind-interfaces \ --address=/iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com/0.0.0.0 \ --address=/#/192.168.56.102 --log-queries ![Run B nslookup](https://static.pigsec.cn/wp-content/uploads/repos/cas/23/23d0a7ded20f0d2204dcb12a1a438ac0fae8c4148ec0f8a1c478830e2fb8d8e4.png) *Verified **before** execution: the kill-switch domain now resolves to `0.0.0.0` while every other domain still sinkholes normally.* This state was verified rather than assumed — the entire experiment depends on this one resolution being different. **Result: full detonation.** ### 3.2 Process behaviour and privilege ![Process tree](https://static.pigsec.cn/wp-content/uploads/repos/cas/ba/ba4bf124c2bf21078cf4ac82c852cf73baf53cada96e454a98ff8bc7429c0421.png) ![Process tree commands](https://static.pigsec.cn/wp-content/uploads/repos/cas/2c/2cfba6171f21e8f4ab382a13f7ad1d0dd34a5be3deff2349e791bf69063a73cd.png) Explorer.EXE └── wannacrymalware.exe ← exits immediately after handoff └── tasksche.exe [C:\ProgramData\rgltpxbykpoo197\] "DiskPart" └── @WanaDecryptor@.exe "Load PerfMon Counters" └── taskhsvc.exe [TaskData\Tor\] — bundled Tor client └── conhost.exe **The parent exits immediately after dropping the payload** — the same handoff pattern seen in RedLine, achieved differently (RedLine hollowed a legitimate process; WannaCry drops a fresh executable). In both cases the artefact the user launched is gone before anything interesting happens. **Both process descriptions confirm static predictions:** `tasksche.exe` reports as **"DiskPart"** — exactly the second version-info block found in §2.3. ![SYSTEM privileges](https://static.pigsec.cn/wp-content/uploads/repos/cas/73/734d38b600a4ef2ed8587d4907e64ca736c76c92d85e3981acfa7afb0e863aef.png) *The entire chain runs as **NT AUTHORITY\SYSTEM**.* This is one of the most consequential observations. The escalation route is the service mechanism identified statically: **a service created through the SCM runs as `LocalSystem` by default**, so registering a service is *simultaneously* the persistence mechanism **and** the privilege escalation. SYSTEM permits encrypting all users' files, deleting Volume Shadow Copies (an administrative operation), and sitting above user-context security tooling. ![Encryption I/O](https://static.pigsec.cn/wp-content/uploads/repos/cas/76/7685269c184196d38f44a7b5dca9c13dbdb36310e233c4e936969004b7b7ad8c.png) *`tasksche.exe` during active encryption: **7.92% CPU, 6.65 MB/s sustained disk I/O** — the encryption loop executing.* The sustained I/O rate is the clearest quantitative signature of mass encryption, and the most practical basis for behavioural detection: sustained high-volume writes from a single non-backup process are anomalous in a way the malware cannot easily disguise. ![VSSVC](https://static.pigsec.cn/wp-content/uploads/repos/cas/fc/fcf8ac72081ef73847e4cb9d1c6ebe641d8568e7bbf0726f0387fd57bdf447a1.png) *`VSSVC.exe` (Volume Shadow Copy Service) and `WmiPrvSE.exe` active — the observable consequence of the malware invoking them to destroy recovery options.* ### 3.3 Dropped toolkit ![Working directory](https://static.pigsec.cn/wp-content/uploads/repos/cas/bb/bbcf929223697489455b1ad80c82b857b2d3b11114e41e8fb904ebfc7192afac.png) *`C:\ProgramData\rgltpxbykpoo197\` — the complete deployed toolkit (18 items).* Three files are the **cryptographic heart of the extortion**, visible on disk: per-file AES key → encrypted with victim RSA public key (00000000.pky) victim RSA private key → encrypted with operator RSA public key (00000000.eky) operator RSA private key → NEVER present on the victim machine Everything needed to decrypt is physically present on the victim's disk **except one value**, which exists only on the operator's infrastructure. That single missing item is what is being sold. The design is sound — there is no implementation flaw to exploit from the files alone. ![28 languages](https://static.pigsec.cn/wp-content/uploads/repos/cas/01/0140e49992bcbf7e8560bd0a18c3913e71a27da3c94d788e54e8819597d97253.png) *All 28 localisations deployed to disk — exactly as predicted from the filenames recovered by FLOSS.* ![Tor directory](https://static.pigsec.cn/wp-content/uploads/repos/cas/8f/8fde775cbb8dc59e4d950a48b00b11a82cbb372f9e9a7dcd606cc7c3566549da.png) *A complete, self-contained Tor client with its OpenSSL dependencies (`taskhsvc.exe` is `tor.exe` renamed).* The malware carries its **own** onion router rather than relying on anything installed on the victim. This is a deliberate OPSEC choice: it removes any dependency on victim software and routes all C2 through Tor, so the operator's real infrastructure is not exposed by traffic analysis. ### 3.4 Recovery destruction and the ransom demand vssadmin delete shadows /all /quiet wmic shadowcopy delete wbadmin delete catalog -quiet bcdedit /set {default} bootstatuspolicy ignoreallfailures bcdedit /set {default} recoveryenabled no **This is the step that converts an inconvenience into an extortion, and its ordering is the point.** Encryption alone is survivable — Windows keeps Volume Shadow Copies precisely so previous versions can be restored. By deleting shadow copies, destroying the backup catalog and disabling recovery **before** presenting the demand, the malware removes every escape route while the victim isn't looking. The victim is only told the game has started after they have already lost every alternative move. This is also **why SYSTEM was a prerequisite, not a luxury** — `vssadmin` requires administrative privilege. The chain is: service → SYSTEM → shadow deletion → irreversibility → leverage. ![Ransom GUI](https://static.pigsec.cn/wp-content/uploads/repos/cas/8f/8f8feac631a2836b76d35fcfb4a1e08632cd0a8825ff3fa93c642b8530554a0c.png) *"Wana Decrypt0r 2.0" — $300 in Bitcoin, two countdown timers, language selector populated from the 28 bundled localisations.* The interface is engineered around **behavioural pressure**: a 72-hour price increase manufactures urgency, a 7-day deletion threat forecloses waiting for a public decryptor, free-sample decryption establishes credibility, and a *Contact Us* channel provides the reassurance of a support process. *(No control was interacted with beyond capturing it.)* ![Regshot](https://static.pigsec.cn/wp-content/uploads/repos/cas/53/53df7b2320c0c5b62b7dd32e07fb00851a71d095b22fd22283cddbdacb800ca7.png) *Regshot differential: 36 files modified, **44,728 total changes** — the aggregate footprint of a SYSTEM-level infection.* ### 3.5 Network behaviour — the worm ![445 volume](https://static.pigsec.cn/wp-content/uploads/repos/cas/c0/c0f49d0bec3b396e2cfd0e646f7592f8049af555c8c836595effefffd1afcfe5.png) *4,025 packets captured — 98% of them a single behaviour.* ![445 scan](https://static.pigsec.cn/wp-content/uploads/repos/cas/7e/7ee1809b2f8f135a84c3b90132e25647c25e9d10604da8b889776a6e4a5a7d26.png) ![445 continued](https://static.pigsec.cn/wp-content/uploads/repos/cas/0c/0c48c416418e0041af7149e7874617713ebea746a3262483bb481c5e66be75ab.png) 192.168.56.20 → 24.6.203.21 TCP 62408 → 445 [SYN] 192.168.56.20 → 99.190.59.122 TCP 62409 → 445 [SYN] 192.168.56.20 → 95.39.4.236 TCP 62413 → 445 [SYN] 192.168.56.20 → 21.153.46.222 TCP 62416 → 445 [SYN] ... Every packet is a SYN to **port 445**, directed at **randomly generated public IPv4 addresses** spanning unrelated allocations worldwide. Source ports increment rapidly in microsecond-spaced bursts, consistent with the multi-threaded scanner predicted by the `_beginthreadex` import. Every connection remained `SYN_SENT` with no response. **Containment held completely: not one packet left the lab.** ![PTR flood](https://static.pigsec.cn/wp-content/uploads/repos/cas/1f/1ff12a42270931fd0ce69613ab5cbd421e7307a86c240dc410b9aec7ae5ba5ad.png) *Reverse-DNS flood for randomly generated public addresses — corroborating the Wireshark evidence from an independent vantage point.* ## Phase 4 — Payload Extraction & Reverse Engineering ### 4.1 Why static extraction was possible The outer loader is **not packed** (`.text` entropy 6.13). The payload is *contained*, not compressed around the code — so it is a static object at a known file offset, sealed with a password present in the binary. It can be lifted out with a resource editor and an archive tool **while the sample never executes**. | | RedLine | WannaCry | |---|---|---| | Concealment | Packed + process hollowing | Nested encrypted container | | Payload location | Reconstructed in memory only | Static resource at `0x000320A4` | | **Recovery requires execution** | **Yes** | **No** | | Risk during recovery | High — live malware running | **None — file is only read** | ### 4.2 Extraction, and a documented failure The first attempt **failed**, and it is documented here because the failure mode is instructive and omitting it would give a misleadingly clean account of how analysis actually proceeds. ![Wrong password](https://static.pigsec.cn/wp-content/uploads/repos/cas/36/36b38aea2190fab8175f48649cb0b313e68783240b7ab388ef61cf9752abd0cf.png) ![36 errors](https://static.pigsec.cn/wp-content/uploads/repos/cas/7b/7bef3be00229bd0c00c39e43d5e6a0744ce5be6035ba04e3a23e5609c8619179.png) ![Empty c.wnry](https://static.pigsec.cn/wp-content/uploads/repos/cas/53/53dc404d483f48aff79dc966e56fe2b93d86274d389ebd37a0c5d47ec8fd693f.png) 7-Zip created all 36 output files as **empty placeholders before authenticating**, then failed to populate them — so the downstream symptom (a zero-byte hex view) *masqueraded as a corrupt payload* rather than an authentication failure. The actual fault was **a single character**. The confirmed count of 36 entries matched DIE's static prediction exactly, confirming the correct resource had been dumped even while authentication was failing. ![Component hashes](https://static.pigsec.cn/wp-content/uploads/repos/cas/26/26207088d1322fb2ded8d4e60c4f90bed8b9ae5a25ccb139420579233f35c20b.png) *Verified hashes of the recovered components. **Note the modification dates: all May 2017.*** **The timestamps are the notable detail.** Every component carries a May 2017 build date, preserved inside the archive. This **directly contradicts the outer binary's forged 2010 timestamp**: the author falsified the PE header a scanner reads, but did not alter archive metadata buried three layers deep. ### 4.3 Ghidra — the kill-switch decision ![Ghidra import](https://static.pigsec.cn/wp-content/uploads/repos/cas/57/577d56545c9086fcb7fda531f7d8c84a2e19bb2f3f97365c8ffd18a1770962f9.png) *Only **55 functions** identified for a 3.5 MB binary — confirming the container architecture: very little actual code, mostly inert data.* ![CodeBrowser](https://static.pigsec.cn/wp-content/uploads/repos/cas/db/db598d971a9da8932276547600af8d2b46caa420b08dd8c4839aeb5ea4d518d2.png) ![rsrc listing](https://static.pigsec.cn/wp-content/uploads/repos/cas/92/92d14df3503c5eb5732f2c363d520e64dcf531e8a49e46bce7202ae0892ca237.png) ![rsrc strings](https://static.pigsec.cn/wp-content/uploads/repos/cas/16/16cd3e9e244d30230e622240c381c51fa180a5e2724caab05bd147840c4f613d.png) ![String search](https://static.pigsec.cn/wp-content/uploads/repos/cas/1d/1d98d4688b4334f711f5eabbf268a73739487a06261016fde17f361062fd8a09.png) *Of **857 strings**, filtering on `iuqer` returns **exactly one** result at `0x004313D0`.* ![Xrefs](https://static.pigsec.cn/wp-content/uploads/repos/cas/99/99a1edae0a5d8fdcea3120dc28fbbf597422ee279a600a76f8f8acf232dc2aad.png) *Referenced from a **single** function, `FUN_00408140`. The decision is centralised — no redundant or obfuscated second check.* ![Decompile raw](https://static.pigsec.cn/wp-content/uploads/repos/cas/23/2312cde8f856c8c58a7b713704dac512168ade451ffa3c97b7492dddd4fa98a3.png) ![Renamed](https://static.pigsec.cn/wp-content/uploads/repos/cas/df/df0e617b83e40d2b03dd832b8f50f85bc725a4fd7333b21d4cd51bbdaed972d1.png) undefined4 killswitch_check(void) { pcVar3 = s_http://www.iuqerfsodp9ifjaposdfj_004313d0; pcVar4 = local_50; for (iVar2 = 0xe; iVar2 != 0; iVar2 = iVar2 + -1) { // copy URL to stack *(undefined4 *)pcVar4 = *(undefined4 *)pcVar3; pcVar3 = pcVar3 + 4; pcVar4 = pcVar4 + 4; } uVar1 = InternetOpenA(0,1,0,0,0); // INTERNET_OPEN_TYPE_DIRECT iVar2 = InternetOpenUrlA(uVar1,local_50,0,0,0x84000000,0); // RELOAD | NO_CACHE_WRITE if (iVar2 == 0) { // ── URL UNREACHABLE ── InternetCloseHandle(uVar1); InternetCloseHandle(0); FUN_00408090(); // → PAYLOAD: service install + worm return 0; } // ── URL REACHABLE ── InternetCloseHandle(uVar1); // → close handles InternetCloseHandle(iVar2); // → return, do nothing return 0; } **Every element is deliberate:** - **The URL is copied to the stack before use.** Functionally unnecessary — the API would accept the `.rdata` pointer directly. Its purpose is **anti-analysis**: a breakpoint on `InternetOpenUrlA` shows a stack address rather than a recognisable data-section reference. - **`INTERNET_OPEN_TYPE_DIRECT`** bypasses any proxy. On a corporate network the proxy is what would log or block the request — so going direct makes the request *more likely to fail* in a proxied enterprise, **biasing the branch toward detonation exactly where the target is most valuable**. - **`0x84000000`** = `INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE` — forces a fresh, uncached answer every time. - **`if (iVar2 == 0)`** is the whole decision. **The response content is never examined** — nothing is read, no status code checked, no body parsed. *Any* reply satisfies the check, which is exactly why Run A terminated the instant INetSim answered. - **`FUN_00408090` is the payload entry point** — it references `OpenSCManagerA` and `StartServiceCtrlDispatcherA`. The kill switch is the gate in front of everything else. **On design intent:** the mechanism is *inverted sandbox detection*. Its weakness is that the domain is a **single hardcoded external dependency gating all malicious behaviour** — anyone who registers it can reach every infected host worldwide. It is a case study in an evasion technique that is clever in the small and catastrophic in the large. ### 4.4 Ghidra — service creation and persistence ![Service API pointers](https://static.pigsec.cn/wp-content/uploads/repos/cas/65/65550fb61d1279bbc733537c8399efe003989b9a34d3e3c8471f66ffe4c0b20e.png) ![CreateServiceA signature](https://static.pigsec.cn/wp-content/uploads/repos/cas/ab/abb73b06cd670d0f49b6e6a31cbc02cf8b264fe03646c305907476caa4fe15cd.png) ![CreateServiceA xref](https://static.pigsec.cn/wp-content/uploads/repos/cas/bc/bc118ce6562859632b361b78e66d0acad589fcc8e28c769f029ad201c7135f48.png) ![Service decompile](https://static.pigsec.cn/wp-content/uploads/repos/cas/03/03f1737eca1eb602d8b9777a7771be10504cc8bb7d6fa4fc447f00a3e445694b.png) undefined4 FUN_00407c40(void) { sprintf(local_104, "%s -m security", &DAT_0070f760); hSCManager = OpenSCManagerA(NULL, NULL, 0xf003f); if (hSCManager != NULL) { hService = CreateServiceA(hSCManager, "mssecsvc2.0", // lpServiceName "Microsoft Security Center (2.0) Service", // lpDisplayName 0xf01ff, // SERVICE_ALL_ACCESS 0x10, // SERVICE_WIN32_OWN_PROCESS 2, // SERVICE_AUTO_START ← persistence 1, // SERVICE_ERROR_NORMAL local_104, // lpBinaryPathName NULL, NULL, NULL, NULL, NULL); if (hService != NULL) { StartServiceA(hService,0,NULL); CloseServiceHandle(hService); } CloseServiceHandle(hSCManager); } } | Parameter | Value | Intent | |---|---|---| | `lpServiceName` | **`mssecsvc2.0`** | Reads as "Microsoft Security Service" — passes a visual scan of `services.msc` | | `lpDisplayName` | **`Microsoft Security Center (2.0) Service`** | Impersonates a real security component. Deleting it *looks* like disabling security | | `dwServiceType` | `0x10` `WIN32_OWN_PROCESS` | Own process, not shared in `svchost` | | **`dwStartType`** | **`2` `AUTO_START`** | **Starts at every boot, before user logon — this is the persistence** | | `dwErrorControl` | `1` `ERROR_NORMAL` | Logs failures but does not halt boot — avoids attention if it crashes | | `lpBinaryPathName` | `" -m security"` | Implements the **two-mode design** predicted from the imports | **Three conclusions:** 1. **Persistence and privilege escalation are the same operation.** `CreateServiceA` with a `NULL` account defaults to `LocalSystem` — so the service starts as **SYSTEM** at every boot with no separate escalation step. The SYSTEM process chain in §3.2 is the observed consequence of *this single call*. 2. **The naming is defensive, not decorative.** Choosing a *security* service specifically maximises an administrator's hesitation to disable it. 3. **The `-m security` argument confirms the two-mode design** — one binary, two behaviours, selected by command-line argument. **Service name `mssecsvc2.0` was read directly from the disassembly, not assumed.** ### 4.5 The archive password and extraction routine ![KERNEL32 imports](https://static.pigsec.cn/wp-content/uploads/repos/cas/d6/d6ad62af0e6d328f22fa75100d697e40faced57e014bcc6cba6e18ee41f90446.png) ![FindResourceA refs](https://static.pigsec.cn/wp-content/uploads/repos/cas/0c/0c920eb1b4fe305fe734482afb232b38ebd60298328a025bdf8bfd99094c06b3.png) *`FindResourceA` has exactly **one** reference — the payload is unpacked in a single routine.* ![Password string](https://static.pigsec.cn/wp-content/uploads/repos/cas/47/478ff80621491044d9059e21d2303d2553cbada77536ea1d9e20d054ab874232.png) Location 0071f5d0 Code Unit db 57h (byte[3514368][62764]) String "WNcry@2ol7" **The addressing detail is the most precise finding of this phase.** Ghidra places the password at **offset 62,764 inside the 3,514,368-byte embedded resource** — exactly the size of resource `R`/1831. ![File read function](https://static.pigsec.cn/wp-content/uploads/repos/cas/07/0790cb3afdcdf2c1cb8f573d11976b279933c98dede08e3c4a5cde5e863ea3fa.png) *`FUN_00407a20` opens the malware's **own** image with `GENERIC_READ`, reads its entire size, and processes it in a heap buffer — how a self-contained dropper treats its own file as a data source. The `FILE_ATTRIBUTE_SYSTEM` flag hides dropped files from Explorer under default settings.* ### 4.6 Recovered C2 and ransom text ![Onion addresses](https://static.pigsec.cn/wp-content/uploads/repos/cas/9a/9a58738e96deb24a38ff1f757894616732fd62131c6893cea548244e3117a533.png) gx7ekbenv2riucmf[.]onion 57g7spgrzlojinas[.]onion xxlvbrloxvriy2c5[.]onion 76jdd2ir2embyv47[.]onion cwwnhwhlz52maqm7[.]onion hxxps://dist[.]torproject[.]org/torbrowser/6.5.1/tor-win32-0.2.9.10.zip **Five Tor hidden-service addresses recovered by hand, with no network contact.** The addresses are stored in **plaintext** inside a layer already protected by three layers of encryption — the author judged the outer layers sufficient. Five redundant addresses provide resilience against takedown, and the Tor Project URL is a **fallback** if the bundled client fails. These are **v2 onion addresses** (16 characters), which dates the campaign — v2 has since been deprecated in favour of 56-character v3. ![Ransom note](https://static.pigsec.cn/wp-content/uploads/repos/cas/3a/3a592a501cdaf90025efdd3b920c62053f5e558e8602f8f5b6e797b329c144cf.png) *`r.wnry` with `sprintf` format specifiers intact for the amount, Bitcoin address and decryptor filename.* Two lines are social engineering rather than technique: - *"You may need to disable your antivirus for a while"* — a **defence-evasion instruction disguised as helpful troubleshooting**, arriving at the moment the victim is most compliant. - *"Nobody will trust us if we cheat users"* — an explicit **reputation argument**, presenting the operation as a going concern. Combined with free-sample decryption and a *Contact Us* channel, the extortion is deliberately packaged as a **transaction** rather than an attack, because a victim who believes they are dealing with a rational counterparty is more likely to pay. ## MITRE ATT&CK Mapping | Tactic | Technique | Evidence | |---|---|---| | Initial Access | T1566.001 Spearphishing Attachment | `invoice_greenanimals.pdf.exe` double-extension lure | | Execution | T1569.002 Service Execution | Service created and started; chain runs as SYSTEM | | Persistence | T1543.003 Windows Service | `mssecsvc2.0`, `SERVICE_AUTO_START` (§4.4) | | Privilege Escalation | T1543.003 | Service runs as `LocalSystem` → SYSTEM (§3.2) | | Defense Evasion | **T1497 Virtualization/Sandbox Evasion** | **Kill switch, demonstrated both directions (§3.1)** | | Defense Evasion | T1036.005 Masquerading | "DiskPart" / security-service impersonation | | Defense Evasion | T1140 Deobfuscate/Decode Files | Encrypted ZIP in `.rsrc`, password `WNcry@2ol7` | | Defense Evasion | T1622 Debugger Evasion | `IsDebuggerPresent` (§2.5) | | Discovery | T1046 Network Service Discovery | Mass TCP/445 scanning (§3.5) | | Discovery | T1016 System Network Config Discovery | `GetAdaptersInfo` import | | Lateral Movement | T1210 Exploitation of Remote Services | MS17-010 / CVE-2017-0144, -0147 | | Command & Control | T1090.003 Multi-hop Proxy | Bundled Tor client; five `.onion` addresses | | **Impact** | **T1486 Data Encrypted for Impact** | Encryption I/O (§3.2); ransom UI | | **Impact** | **T1490 Inhibit System Recovery** | `vssadmin` / `wbadmin` / `bcdedit`; VSSVC activity | | Impact | T1491.001 Internal Defacement | Desktop wallpaper replaced (`b.wnry`) | ## Indicators of Compromise ### Host | Type | Indicator | |---|---| | SHA-256 | `24d004a104d4d54034dbcffc2a4b19a11f39008a575aa614ea04703480b1022c` | | SHA-1 | `e889544aff85ffaf8b0d0da705105dee7c97fe26` | | MD5 | `db349b97c37d22f5ea1d1841e3c89eb4` | | imphash | `9ecee117164e0b870a53dd187cdd7174` | | Working directory | `C:\ProgramData\\` (observed: `rgltpxbykpoo197`) | | Dropped executables | `tasksche.exe`, `taskdl.exe`, `taskse.exe`, `@WanaDecryptor@.exe`, `taskhsvc.exe` | | Dropped data files | `b.wnry`, `c.wnry`, `f.wnry`, `r.wnry`, `s.wnry`, `t.wnry`, `u.wnry` | | Key artefacts | `00000000.pky`, `00000000.eky`, `00000000.res` | | **Service name** | **`mssecsvc2.0`** | | **Service display name** | **`Microsoft Security Center (2.0) Service`** | | Ransom note | `@Please_Read_Me@.txt` | | Encrypted extension | `.WNCRY` (temporary: `.WNCRYT`) | | Archive password | `WNcry@2ol7` (letters `o`, `l` — not digits) | | Masquerade filenames | `lhdfrgui.exe`, `diskpart.exe` | ### Network | Type | Indicator | |---|---| | Kill-switch domain | `iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea[.]com` | | Behaviour | High-volume TCP/445 SYN to random public IPv4 addresses | | C2 (Tor v2) | `gx7ekbenv2riucmf[.]onion` | | C2 (Tor v2) | `57g7spgrzlojinas[.]onion` | | C2 (Tor v2) | `xxlvbrloxvriy2c5[.]onion` | | C2 (Tor v2) | `76jdd2ir2embyv47[.]onion` | | C2 (Tor v2) | `cwwnhwhlz52maqm7[.]onion` | | Bitcoin | `13AM4VW2dhxYgXeQepoHkHSQuy6NgaEb94` | | Exploited CVEs | CVE-2017-0144, CVE-2017-0147 (MS17-010) | Machine-readable indicators: [`iocs/iocs.csv`](iocs/iocs.csv) ## YARA Detection Rule Full rule: [`iocs/wannacry.yar`](iocs/wannacry.yar) rule WannaCry_Dropper_Static { meta: author = "Ali Mehdi Jafeeri" description = "WannaCry outer dropper - masquerade, SMBv1 downgrade, nested payload" reference = "SHA-256 24d004a104d4d54034dbcffc2a4b19a11f39008a575aa614ea04703480b1022c" date = "2026-07-21" strings: // SMBv1 downgrade negotiation - the worm component $smb1 = "PC NETWORK PROGRAM 1.0" ascii $smb2 = "LANMAN1.0" ascii $smb3 = "Windows for Workgroups 3.1a" ascii $smb4 = "NT LM 0.12" ascii $smb5 = "LM1.2X002" ascii // Kill-switch domain $ks = "iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea" ascii // Payload component names $c1 = "c.wnry" ascii $c2 = "t.wnry" ascii $c3 = "s.wnry" ascii $c4 = "b.wnry" ascii // Masquerade metadata $m1 = "lhdfrgui.exe" ascii wide $m2 = "diskpart.exe" ascii wide condition: uint16(0) == 0x5A4D // MZ and filesize > 3MB and filesize < 4MB and ( $ks // kill switch alone is conclusive or (4 of ($smb*) and 2 of ($c*)) or (all of ($m*) and 3 of ($smb*)) ) } **Design reasoning.** The rule anchors on the **SMBv1 dialect strings** rather than the ransom note or `.WNCRY` extension. Those latter strings live in the *innermost encrypted layer* and are **invisible in the delivered file**, so a rule built on them would fail against the artefact a defender actually intercepts. The dialect strings sit in the readable outer layer. Requiring co-occurrence of both masquerade filenames plus SMB dialects guards against false positives — a legitimate SMB implementation would not also claim to be two different Microsoft disk utilities. ## Defensive Recommendations Each recommendation is the direct counter to a mechanism demonstrated above — an observed dependency read backwards. | Control | Why it works against this sample | |---|---| | **Patch MS17-010 / disable SMBv1** | The propagation mechanism has exactly **one** dependency. The dialect list (§2.3) shows it must negotiate *down* to SMBv1 to attack. The failed propagation in §3.5 is the proof. | | **Block outbound TCP/445 at the perimeter** | §3.5 shows the worm scanning the public internet on 445. No legitimate traffic requires port 445 to leave an organisational network. | | **Offline, immutable backups** | §3.4 shows shadow copies and the backup catalog are deliberately destroyed. **Any backup the malware can reach as SYSTEM is not a backup.** | | **Restrict & monitor service creation** | Persistence and privilege escalation are the same act (§4.4). Creation of an auto-start service is a high-fidelity alert. | | **Alert on shadow-copy deletion** | `vssadmin delete shadows /all` from a non-backup process is almost never legitimate, and fires **immediately before impact** — an ideal last-line trigger. | | **Network segmentation** | A worm that cannot route cannot spread. The containment that held in this lab is the same control that limits blast radius in production. | | **Enforce code signing, not appearances** | The sample passes visual inspection as a Microsoft utility and **fails signature verification** (§2.2). Verify cryptographic identity, not displayed names. | ## What I Learned Beyond the findings, three methodological lessons generalise past this sample: **1. Concealment strategy dictates recovery strategy.** RedLine packed its *code* and forced a memory dump; WannaCry contained its *cargo* and left its brain readable. Recognising which kind of protection you face — packer vs. container — tells you immediately whether to reach for a resource editor or a debugger. That single distinction saved hours here. **2. A sandbox that simulates the internet too well defeats itself.** The kill switch is inverted sandbox detection, and my default lab configuration silently satisfied it. If I had run the sample once and written "no observable behaviour," I would have been confidently wrong. **Always ask what external dependency a sample checks before concluding it is inert.** **3. Centralised decisions are single points of failure — for both sides.** The kill switch was simultaneously WannaCry's cleverest anti-analysis feature and its fatal flaw: one hardcoded, unauthenticated check gating all malicious behaviour. When analysing any sample, *"what one thing does the whole payload depend on?"* is now among my first questions, because that thing is both the author's best idea and the defender's best lever. I also kept a set of **attacker's-design-rationale notes** alongside the technical write-up — working through *why* each choice was made and what trade-off it accepted. Reconstructing the engineering reasoning turned this from cataloguing artefacts into actually understanding the sample. ## References & Prior Work WannaCry is among the most extensively documented malware families in existence, and every indicator in this report has been public since 2017. **Nothing here claims novel discovery of the family.** What this repository documents is my **own end-to-end analysis**: my isolated lab, my sample, my tool runs, my screenshots, my Ghidra session, and — the part I consider genuinely my own contribution — the **paired kill-switch experiment** designed to demonstrate the branch in both directions before confirming it in the disassembly. Methodology draws on standard practical malware-analysis workflow (the PMAT-style static → dynamic → reverse-engineering progression), and public WannaCry write-ups were consulted for orientation. All findings presented were independently reproduced and verified in my own environment; where a result was ambiguous or a tool artefact (see the FLOSS `IPC$` note in §2.3), I have said so explicitly rather than presenting it as clean. **Sample source:** [MalwareBazaar](https://bazaar.abuse.ch/) · **Vulnerability:** [MS17-010](https://learn.microsoft.com/en-us/security-updates/securitybulletins/2017/ms17-010) · **Framework:** [MITRE ATT&CK](https://attack.mitre.org/) ## Repository Contents . ├── README.md ← this analysis ├── images/ ← 64 evidence screenshots ├── report/ │ └── WannaCry_Malware_Analysis_Report.docx ← formatted report ├── iocs/ │ ├── iocs.csv ← machine-readable indicators │ └── wannacry.yar ← YARA detection rule └── LICENSE **No malware samples or extracted payload components are included in this repository.** Analysis by **Ali Mehdi Jafeeri** · July 2026
Published for educational and defensive purposes. Indicators are provided for detection engineering only.