Fishing for Malware — Part Three: WannaCry

Published 2022-01-25
Edited 2023-10-25 (git:05b41b4)

Catching WannaCry

One very interesting binary uploaded to my honeypot not only once, but several times from multiple hosts around the world, was WannaCry. Yes, nearly five years after the Shadow Brokers sold the NSA’s EternalBlue exploit to the notorious Pyongyang-based (alleged) Lazarus Group, who then developed and released WannaCry, one of the most damaging ransomware packages is still in active distribution.

Even after Marcus Hutchins discovered and published WannaCry’s “kill switch” and Microsoft patched EternalBlue, WannaCry remains a dangerous binary. After all, the age-old logic that it is somehow more reasonable to risk the exorbitant cost of malware damages than to pay for sound security architecture sadly remains to this day. So, given that I am now in possession of over a dozen permutations of WannaCry, what is the obvious next step? Of course, to execute it!

Executing WannaCry

Preparing the Environment

Because I care quite deeply about the security of my home network, I have offloaded the risk of knowingly running malware onto Microsoft via Azure. Thank you for supporting my student endeavors, Microsoft. Azure still supports Windows 7, so I deployed an image of Windows 7 Enterprise with the following technical specs:

1Security type   Standard
2Image           Windows 7 Enterprise - Gen1
3Size            Standard B2ms (2 vcpus, 8 GiB memory)
4OS disk type    Premium SSD LRS

To ensure maximum damage by WannaCry, I also uninstalled every Windows update via a generated Batch script using the kind advice of users M.Josh and imansejati on the Microsoft Forums. Removing feature updates was unnecessary, but it was easier to simply remove every KB* update, which includes all of those intended for security purposes. The full script can be found here, a preview of which is below:

1wusa /uninstall /KB:2849697 /quiet /norestart
2wusa /uninstall /KB:2849696 /quiet /norestart
3wusa /uninstall /KB:2841134 /quiet /norestart
4wusa /uninstall /KB:2670838 /quiet /norestart
5wusa /uninstall /KB:2479943 /quiet /norestart
6wusa /uninstall /KB:2491683 /quiet /norestart
7... (+188 more)

Screenshot of my Windows 7 image
Screenshot of my Windows 7 image

While I waited for the updates to be uninstalled, I was struck by just how unbearably nostalgic the Windows 7 acrylic design scheme is. Sadly, it seems that Azure images of Windows 7 aren’t provisioned with MS Solitaire or Purble Place… Good memories, nonetheless; it was on Windows 7 that I gained an appreciation for computing and security in general. I recall creating prank “games” with my friends on the computers in middle school that would power off the PC if the user lost, or make the LOCK indicators on the keyboards flash non-stop with VBA. A time bound to the past, for sure. I can’t imagine shell access on middle school student accounts these days, let alone unrestricted, editable access to student registration information on network drives mounted to every PC in the domain.

I also disabled Windows Firewall, and then proceed on to Windows Defender — right, Windows 7 doesn’t have Windows Defender, or any real-time AV, configured by default. A notification in the Action Center urgently warned me to “Find an antivirus program online (Important).” Combined with the way Windows handles privilege escalation, it is no wonder that Windows is notorious for security issues.

Finally, after waiting for significantly longer than I had anticipated, all updates were uninstalled, and the PC restarted.

C:\Users\slak>wmic qfe get hotfixid


As a reminder, I had also uninstalled feature updates, which left the desktop post-reboot with all the classical charm of Windows 2000.

Screenshot of my Windows post-downgrade
Screenshot of my Windows post-downgrade

Of course, the desktop didn’t look like this for long — executing wannacry.exe yielded the following shortly after.


Screenshot of my Windows after execution of WannaCry
Screenshot of my Windows after execution of WannaCry

Success! WannaCry was active and my files were encrypted, all with strange WannaCry-specific file extensions… In a different context, I’m sure I would be quite upset here.

Some elements of the WannaCry GUI stood out to me in particular: the Check Payment and Contact Us buttons. Both, of course, imply the requirement for outbound requests to a foreign server. In light of that, I attempted to set up Wireshark and TCPview to see where requests are sent. However, as can be seen below, neither program functioned as expected, both either crashing instantly or failing to bind to network interfaces. Whether this is due to interference by WannaCry or something else, I am not sure.

Screenshot of Wireshark and TCPview failure
Screenshot of Wireshark and TCPview failure

Even though TCPview nor Wireshark operated as expected, in blue below, I have boxed some outgoing connections found with netstat while requesting payment information:

Screenshot of netstat connections
Screenshot of netstat connections

Here are the highlighted addresses with relation to their associated WHOIS registration info:

Address         Location            Owner   Hong Kong Aberdeen  Microsoft Corp   Phoenix, AZ         Microsoft Corp    Phoenix, AZ         Microsoft Corp

I had either missed the connection or it had never originated in the first place; alternatively, the malware host was listening for connections using Azure. Further toying with WannaCry revealed that the timer could be modified using the system clock! Setting the time in Windows to several days in the future — thus missing the first payment deadline — raised the file ransom from USD 300 to USD 600.

Screenshot of changing the system time and WannaCry
Screenshot of changing the system time and WannaCry

So, then, what happens if the second deadline expires as well? Unfortunately, nothing, so it seems. The timer runs out but then… Well, the files remain. Not even a pop-up — rather anticlimactic. Further, resetting the system clock refilled the timers and lowered the requested payment back to USD 300.

Speaking of payment, the transaction history of the Bitcoin ransom address can be seen here, but to summarize:

This address has transacted 124 times on the Bitcoin blockchain. It has received a total of 14.87769994 BTC ($522,558.23) and has sent a total of 14.41067602 BTC ($506,154.68). The current value of this address is 0.46702392 BTC ($16,403.56).

Finally, attempting to send a message via the Contact Us link, which spawned a text entry box, revealed the following, which leads me to believe that finding a valid connection endpoint would have ultimately been useless, as it would have simply been a TOR node.

Screenshot of WannaCry TOR connection failure
Screenshot of WannaCry TOR connection failure

Overall, while WannaCry isn’t as intimidating as in times past, it was still fun to play around with. If the Bitcoin transaction history is indicative of anything, it’s that a very profitable subsection of users still open their computers to see WannaCry’s infamous red GUI.

Examining WannaCry with Ghidra

WannaCry has, so far, been only superficially exposed in this post, but Ghidra can be used to dive deeper. Before proceeding, I would like to note that I am not by any means proficient, or even knowledgeable, regarding the process of reverse engineering. I am still a student; it is my hope, however, that others might learn as much as I have by reading further.

First, some information regarding the executable:

1$ file wannacry
2wannacry: PE32 executable (GUI) Intel 80386, for MS Windows
$ strings wannacry










In particular, consider the following URL.

1$ strings wannacry | grep 'http\|https'
 1$ curl
 3<!DOCTYPE html>
 4<html lang="en-us" class="no-js">
 5    <head>
 6        <meta charset="utf-8">
 7        <title>Sinkholed by Kryptos Logic</title>
 8        <meta name="description" content="Kryptos Logic Sinkhole">
 9        <meta name="viewport" content="width=device-width, initial-scale=1.0">
10        <link href="//" rel="stylesheet" type="text/css"/>
11    </head>
12    <body class="flat">
13        <div class="content">
14            <div class="content-box">
15                <div class="big-content">
16                    <div class="clear"></div>
17                </div>
18                <h1>Sinkholed!</h1>
19                <p>This domain has been sinkholed by <a href="">Kryptos Logic</a>.</p>
20            </div>
21        </div>
22    </body>

The domain has since been captured, but from a cursory Google search, my understanding is that this was one of the kill-switch sites used to neutralize WannaCry. Here is Ghidra’s best attempt to reconstruct the function containing the URL:

 1undefined4 FUN_00408140(void)
 4  undefined4 uVar1;
 5  int iVar2;
 6  undefined4 *puVar3;
 7  undefined4 *puVar4;
 8  undefined4 uStack100;
 9  undefined4 uStack96;
10  undefined4 uStack92;
11  undefined4 local_50 [14];
12  undefined4 local_17;
13  undefined4 local_13;
14  undefined4 local_f;
15  undefined4 local_b;
16  undefined4 local_7;
17  undefined2 local_3;
18  undefined local_1;
20  puVar3 = (undefined4 *)s_http://www.iuqerfsodp9ifjaposdfj_004313d0;
21  puVar4 = local_50;
22  for (iVar2 = 0xe; iVar2 != 0; iVar2 = iVar2 + -1) {
23    *puVar4 = *puVar3;
24    puVar3 = puVar3 + 1;
25    puVar4 = puVar4 + 1;
26  }
27  *(undefined *)puVar4 = *(undefined *)puVar3;
28  local_17 = 0;
29  local_13 = 0;
30  local_f = 0;
31  local_b = 0;
32  local_7 = 0;
33  local_3 = 0;
34  uStack92 = 0;
35  uStack96 = 0;
36  uStack100 = 0;
37  local_1 = 0;
38  uVar1 = InternetOpenA(0,1);
39  iVar2 = InternetOpenUrlA(uVar1,&uStack100,0,0,0x84000000,0);
40  if (iVar2 == 0) {
41    InternetCloseHandle(uVar1);
42    InternetCloseHandle(0);
43    FUN_00408090();
44    return 0;
45  }
46  InternetCloseHandle(uVar1);
47  InternetCloseHandle(iVar2);
48  return 0;

It appears that InternetOpenA(), for example, is a system call to a function in Microsoft’s own WININET.DLL, as shown below, which is contained within the wininet.h header.

1ff 15 34 a1 40 00      CALL        dword ptr [WININET.DLL::InternetOpenA]

Microsoft says that InternetOpenA() “initializes an application’s use of the WinINet functions.” WannaCry then uses InternetOpenUrlA(), which, also per Microsoft documentation, “opens a resource specified by a complete FTP or HTTP URL.”

Consider, then, the following excerpt from The Conversation’s 2017 article about WannaCry, Here’s how the ransomware attack was stopped – and why it could soon start again:

In the case of WannaCry, a researcher using the pseudonym MalwareTech ended up accidentally activating the kill switch when he tried to create a sinkhole in order to study the software. WannaCry included code that looked to check if a specified domain had been registered. If it received a response from the domain, it shut down. If not, it continued to work. So when MalwareTech registered the domain, it effectively activated the kill switch.

So, then, Ghidra’s disassembly from above could presumably be annotated with comments like so:

 3  uVar1 = InternetOpenA(0,1); // Initialize WinInit capability
 4  iVar2 = InternetOpenUrlA(uVar1,&uStack100,0,0,0x84000000,0); // Check for a response from the URL 
 5  if (iVar2 == 0) { // If no reponse is received, as domain is unregistered
 6    InternetCloseHandle(uVar1); // Close the socket
 7    InternetCloseHandle(0); // Close the socket
 8    FUN_00408090(); // !! PROCEED WITH WANNACRY !!
 9    return 0;
10  } // Otherwise, just close the socket and quit without executing WannaCry
11  InternetCloseHandle(uVar1);
12  InternetCloseHandle(iVar2);
13  return 0;


By this point, my disassembly-related technical skill had been exhausted. Overall, this has certainly been one of the most interesting parts of my honeypot project thus far. Thank you so much for reading and stay tuned; more posts in my Fishing for Malware series will be published soon.

Fishing for Malware: Part 4 →
← Fishing for Malware: Part 2