[Studying] Inside WannaCry: Exploit, Worming, and TOR Communication Explained

First Post:

Last Update:

Word Count:
1.5k

Read Time:
9 min

TOR, EternalBlue and DoublePulsar!

Introduction

This article is part of my series: Inside Different Generations of Ransomware.

If you are interested in the full series, please refer to the mentioned page.

In the previous article, I analyzed the underlying mechanism of WannaCry, focused on encryption and anti-forensics mechanisms.

However, the previous analysis did not fully cover the communication protocol due to the incomplete payload.

Today, I finally found the missed part of the malware on MalwareBazaar. Therefore, I decided to write this article to complete the entire analysis of WannaCry.

This article focuses on the communication and exploitation method of WannaCry.

Key Takeaways

  • TOR-based C2 communication enabling anonymized infrastructure
  • Integration of EternalBlue (RCE) and DoublePulsar (kernel implant)
  • Fully automated worming and payload injection pipeline

Attack Architecture Overview

WannaCry can be decomposed into three core architectural components:

  1. C2 communication via TOR
  2. Exploitation via EternalBlue (initial access)
  3. Worming automation via DoublePulsar

The following sections analyze each component in detail.

TOR Communication

Since 2017, the identity threat actors behind WannaCry has remained unclear, one of the main reasons is WannaCry adopts TOR network for C2 communication. Compared to the previous ransomware that I analyzed (e.g., CryptoLocker and Jigsaw), WannaCry uses TOR network to enhance anonymity. The advantage of using TOR is not only anonymity, but also preventing direct cyberattack to the C2 server (e.g., DDoS attack).

As mentioned in the previous article, WannaCry malware releases different files on the disk:

Here s.wnry is actually a ZIP file without password protection:

c.wnry is used for saving bitcoin address and *.onion domains of the C2 servers:

Onion domains and TOR project URL

The malware copies TaskData\Tor\tor.exe to TaskData\Tor\tasksche.exe and executes it:

It reads *.onion domains for C2 communication:

Bind 127.0.0.1:9050 (hexadecimal 0x235a is 9050 in decimal representation):

After binding a host for TOR proxy, the malware is capable of communicating to the C2 servers.

This mechanism enables WannaCry to communicate with its C2 infrastructure via the TOR network.

In the next section, I am going to explain the worming method of WannaCry.

Exploitation

WannaCry uses EternalBlue and DoublePulsar to achieve worming. As mentioned in the previous article, the underlying principle of this vulnerability and kernel backdoor are very complicated. Despite that, I will briefly explain how they work.

SMB

Server Message Block (SMB) is a communication protocol used to share files, printers, serial ports, and miscellaneous communications between nodes (mostly Windows devices) on a network. 1

EternalBlue

EternalBlue is a sophisticated Remote Code Execution (RCE) exploit that targets the Windows SMBv1 protocol.

EternalBlue is based on an integer overflow vulnerability in the SMBv1 protocol.

The core of the exploit lies within the srv.sys kernel driver. When processing a specially crafted FEA (File Extended Attributes) list in an SMB_COM_TRANSACTION2 request, a calculation error occurs. If the total size exceeds 65535 bytes, the value wraps around, leading to an undersized buffer allocation.

The attacker sends groomed SMB packets to shape the kernel’s non-paged pool memory, ensuring that the vulnerable buffer is placed adjacent to a controllable memory region.

When the oversized FEA data is sent, it overflows the allocated buffer and overwrites adjacent kernel memory with attacker-controlled shellcode.

This gives the attacker the ability to execute code with SYSTEM privilege (Ring 0) without any user interaction.

DoublePulsar

DoublePulsar is a Kernel-Mode implant (backdoor) developed by the Equation Group (who developed EternalBlue). It is often delivered by EternalBlue to provide a fileless, persistent foothold.

DoublePulsar does not exist as a file on the disk (fileless). It resides entirely in the Kernel Memory. If the computer reboots, the backdoor is wiped (unless re-infected). This is the reason why WannaCry implemented a persistence method for itself.

DoublePulsar hijacks the SMB Dispatch Table. Every incoming SMB request is intercepted by DoublePulsar before the OS sees it.

It uses the Multiplex ID (MID) field in the SMB header as a covert communication channel. The attacker sends an SMB request with MID = 0x41 (65). If the backdoor is present, it intercepts the packet and responds with MID = 0x51 (81, character “Q” in ASCII).

Once the handshake is confirmed, the attacker can send the following commands:

  • OutputInstall: Generate a shellcode binary file for RunShellcode
  • Ping: Check if DoublePulsar exists
  • RunDLL: Run a shellcode and load DLL
  • RunShellcode: Run a shellcode
  • Uninstall: Uninstall DoublePulsar

Note: Again, the underlying mechanism is sophisticated. Therefore, I will study it in future articles.

Spreading

Now, let’s analyze how WannaCry infects other machines via EternalBlue and DoublePulsar.

I found the malware on MalwareBazaar.

The payload is a DLL file without any packing. Therefore, I opened it using Ghidra. It releases an executable from resource and copies it as C:\Windows\mssecsvr.exe:

It then launches the executable:

I opened the DLL payload using Resource Hacker and extracted the executable:

Resource Hacker

ExeInfo PE

Then, I started to analyze the executable payload. This executable payload is the worming tool. First, it obtains network adapters for spreading:

APIs such as GetAdapterInfo() and inet_addr()

Next, it enters worming phase:

Note that hexadecimal 0x1bd is 445 in decimal representation.

For readability, I renamed the original subroutines based on their functionality:

The entire infection procedure can be summarized as follows:

FUN_ScanSMB

FUN_ScanSMB

graph TD Start([Start Scan]) --> CreateSocket[Create TCP Socket] CreateSocket --> SetTimeout[Set Connection Timeout - 3s] SetTimeout --> Connect{Connect to Port 445} Connect -- Failed --> Return0[Return 0: Target Down] Connect -- Success --> CloseAndReturn[Close Socket & Return 1: Target Active] Return0 --> End([End]) CloseAndReturn --> End

FUN_DoublePulsar

FUN_DoublePulsar

graph TD Start([Check for DoublePulsar]) --> SMB_Neg[Send SMB Negotiate/Session Setup] SMB_Neg --> SendPing[Send Trans2 Request - MID=0x41] SendPing --> RecvResponse[Receive SMB Response] RecvResponse --> CheckQ{Is MID == 0x51 'Q'?} CheckQ -- Yes --> IsPayload{Need to Inject DLL?} IsPayload -- Yes --> Inject[Call FUN_004072a0: DLL Injection] IsPayload -- No --> Return1[Return 1: Backdoor Confirmed] CheckQ -- No --> Return0[Return 0: No Backdoor]

FUN_EternalBlue

FUN_EternalBlue

graph TD Start([Execute EternalBlue Exploit]) --> ReadTable[Read Instruction Table DAT_00431480] ReadTable --> OpType{Parse OpCode uVar2} OpType -- 2 --> Connect[Establish Socket Connection] OpType -- 0 --> FillTemplate[Call FUN_00401190: Fill UID/TID Placeholders] FillTemplate --> SendExploit[Send Malicious Overflow Packet] OpType -- 1 --> UpdateSession[Receive & Update Session Parameters] OpType -- 3 --> CloseSocket[Close Connection] SendExploit --> Next{More Instructions?} Next -- Yes --> ReadTable Next -- No --> End([Exploit Sequence Finished])

The payload and exploit generation procedure is shown below:

graph TD subgraph DataSection ["Static Data (.data)"] RawTemplate[Raw Exploit Template] Placeholders["'__USERID__PLACEHOLDER__'
'__TREEID__PLACEHOLDER__'
'__TREEPATH_REPLACE__'"] end subgraph Step1 ["Step 1: UNC Path Generation (4017b0)"] GetIP[Get Target IP] --> FormatPath["sprintf: \\IP\IPC$"] FormatPath --> ReplacePath[Replace '__TREEPATH_REPLACE__'] end subgraph Step2 ["Step 2: ID Patching (401190)"] GetSess[Get Current SMB Session IDs] --> ReplaceUID[Replace '__USERID__PLACEHOLDER__'] ReplaceUID --> ReplaceTID[Replace '__TREEID__PLACEHOLDER__'] end subgraph Step3 ["Step 3: Final Assembly"] FixLen[Calculate & Fix NetBIOS Length Field] --> FinalPayload[Final Exploit Packet Ready] end RawTemplate --> Step1 Step1 --> Step2 Step2 --> Step3 FinalPayload --> Send[Network Socket Send] style RawTemplate fill:#eee,color:#000 style FinalPayload fill:#d4edda,stroke:#28a745,stroke-width:2px,color:#000

FUN_PayloadInjector

FUN_PayloadInjector

graph TD Start([Start Payload Injection]) --> Connect[Connect to Target Port 445] Connect --> Auth[Send SMB Negotiate & Session Setup] Auth --> Establish[Establish SMB Tree Connection] Establish --> GetSessionID[Capture Session/User IDs from Response] GetSessionID --> SendPing[Send DoublePulsar Ping MID=0x41] SendPing --> CheckQ{Is Response 'Q' 0x51?} CheckQ -- No --> Fail[Abort: Backdoor Not Ready] CheckQ -- Yes --> PrepPayload[Call FUN_00406eb0: Prepare Shellcode/DLL] PrepPayload --> ExecRun[Call FUN_00406f50: Send DoublePulsar 'RUN' Command] ExecRun --> Close[Close Socket] Close --> End([Payload Injected Successfully])

Overall (WannaCry Infection Kill Chain)

graph TD Main([Start Infection Thread]) --> Scan[FUN_ScanSMB: Port 445 Check] Scan -- Closed --> Terminate([End Thread]) Scan -- Open --> CheckDP1[FUN_DoublePulsar: Initial 'Q' Check] CheckDP1 -- 'Q' Found --> Inject[FUN_PayloadInjector: Upload & Run DLL] CheckDP1 -- Not Found --> ExploitLoop{Exploit Attempt Loop: Max 5} ExploitLoop --> EB[FUN_EternalBlue: Execute Heap Overflow] EB --> CoolDown[Sleep 3s for Memory Stability] CoolDown --> CheckDP2[FUN_DoublePulsar: Verify Success] CheckDP2 -- 'Q' Found --> Inject CheckDP2 -- Not Found --> Retry{Retries < 5?} Retry -- Yes --> ExploitLoop Retry -- No --> Terminate Inject --> Success([System Compromised: Encryption Starts])

From a research perspective, this sample provides a rare opportunity to observe the complete integration of exploit, kernel backdoor, and ransomware components within a single automated kill chain.

Conclusion

This article presents an analysis of the network communication of WannaCry. It focuses on C2 communication via TOR and worming functionality.

As mentioned in the previous article, WannaCry creates a mutex to ensure only a single instance is running. It also prevents multiple instances caused by re-infection.

This completes the full kill chain of WannaCry, from initial exploitation to lateral movement and C2 communication.

flowchart TD A["SMB Scan"] B["Check DoublePulsar"] C["EternalBlue"] D["DoublePulsar"] E["Payload Injector"] F["WannaCry Execution"] G["Ransom"] H["TOR Communication"] I["Infect other devices"] A --> B B --> C C --> D D --> E E --> F F --> G F --> H F --> I

Compared to traditional ransomware, WannaCry demonstrates a hybrid design combining worm-like propagation with ransomware monetization, which significantly amplified its global impact.

If you have any comments and suggestions, please feel free to leave them below!

References

1. https://en.wikipedia.org/wiki/Server_Message_Block

THANKS FOR READING