WannaCry Ransomware: Reverse Engineering and Malware Analysis
Dissecting WannaCry: A Deep Dive into Reverse Engineering and Malware Analysis
Blog Overview
In this blog, I will analyze the WannaCry ransomware using static and dynamic analysis methods. I will begin by examining the executable’s properties without executing it, followed by observing its behavior during runtime. Finally, I will reverse engineer the WannaCry executable with debugging tools and Cutter, exploring the assembly code to uncover its operational mechanisms.
Environment Setup
My environment setup includes the FLARE VM and REMnux VM for malware analysis. Additionally, I am using INetSim to create a fake web server; however, I will disable the web server to allow the malware to infect my system and observe its symptoms. I have also created adapters specifically for these two VMs to connect to each other and configured my DNS server to point to the REMnux IP address.
I started by using FLOSS (Fuzzy Hashing for Strings) to extract the strings from the WannaCry executable and output them to a file. This allowed me to identify any suspicious strings that might indicate malicious behavior or components within the ransomware.
I found several suspicious API functions, including CryptDecrypt
and CryptEncrypt
, which are commonly used for encryption and decryption operations. These functions suggest that the malware may be involved in encrypting files, a key behavior typically associated with ransomware.
I then decided to use PEStudio to further analyze the executable. This tool helped me discover additional suspicious API calls, strings, and other indicators that could reveal the malware’s behavior. PEStudio provided valuable insights into potential areas of concern within the binary.
Below, we can find some API functions used for network communication and for creating and deleting files. These functions are suspicious and could indicate that the ransomware is attempting to create additional executables or manipulate files on the infected system, beyond just executing the main payload.
Below, we can find a URL that is used by the WannaCry ransomware, which may be associated with its command-and-control server or other malicious activities.
I then decided to use Wireshark to monitor the network communication. I disabled the fake web server to detonate the ransomware and observe its symptoms in real-time, allowing me to capture any malicious traffic and understand how the ransomware interacts with the network.
I found that there was a DNS query to the URL below, which aligns with our earlier findings in PEStudio. This connection reinforces the idea that the ransomware is attempting to communicate with external servers, further indicating its malicious behavior.
When I detonated the malware, my desktop changed completely due to the ransomware’s effects, displaying malicious images and messages. This visual alteration served as a clear indicator of the ransomware’s successful infection and its attempt to intimidate the victim by showcasing its control over the system.
I decided to use Procmon to list the processes utilized by the malware and to monitor which files were created during its execution. Additionally, I examined any changes made to the Windows registry, allowing me to gather more information about the malware’s behavior and the extent of its impact on the system.
We can find below that the ransomware executable created a new executable. I pivoted to analyze this new executable further to understand its functionality and determine what additional actions it might perform in the context of the ransomware’s operations.
We can also observe below that this executable created a suspicious folder in the Program Data path. This unusual directory could be used by the ransomware for storing additional malicious files or configurations, indicating further attempts to establish persistence on the infected system.
Then I went to that folder to investigate its contents and discovered that the ransomware is attempting to maintain persistence and establish a backdoor. This behavior suggests that the malware aims to ensure continued access to the infected system, even after a reboot or other mitigating actions.
We can also utilize the process tree inside Procmon to observe any executed processes. As shown in the screenshots below, there is an executable responsible for maintaining persistence which was stored in Program Data as discussed previously, and we can see that cmd.exe
was used to execute various commands. This activity further indicates the ransomware's efforts to control the system and carry out its malicious objectives.
We can also see below here that there was .bat file created by cmd.exe, which is a good IOC to note.
Reverse Engineering WannaCry
Now, I will begin the reverse engineering process of the malware. First, I will restore the VM to its original condition to ensure a clean environment. Afterward, I will decompile the executable to analyze its code and gain a deeper understanding of its functionality and malicious behavior.
I started by using Cutter to analyze the code statically without executing it. This allowed me to observe how API calls were made in the main function and gain insights into the key operations of the malware, such as encryption, file manipulation, and network communication.
As shown below, I am now in the main function, going through the code. We can see the URL that was identified earlier, and it’s evident that this URL is going to be passed to the API calls listed below. This reinforces the connection between the malware’s code and its attempts to communicate with external servers for further instructions or data exfiltration.
Below here, we can see the API calls used by the ransomware: InternetOpenA
, InternetOpenUrl
, and InternetCloseHandle
. We can observe that the URL was passed to the InternetOpenUrl
API function. If we're not familiar with what these API calls do, we can refer to the Microsoft documentation to learn about their functions and parameters. Additionally, by analyzing the push functions in the assembly code, we can gain further insights into how these API calls interact with the malware’s operations and how they contribute to the communication with external servers.
Below, the InternetCloseHandle
API function is used to close an open handle to an internet resource, such as a URL or a connection. In this case, it would be used to close the handle associated with a URL that was previously opened using functions like InternetOpenA
or InternetOpenUrl
. It takes a single parameter, which is the handle (URL) to be closed.
Below, we can see that this API has two options: whether the connection will be terminated (killed) or not. If the connection does not get killed, the malware proceeds to the next function, which is responsible for encrypting the data on the infected system. This behavior indicates that the ransomware will continue with its encryption process if the killswitch is not activated, furthering its malicious actions. The arrow points to the function that is responsible for encrypting the data and if we click on it, we will be redirected to the function.
We can also notice that if the URL is reached, the zero flag will kill the program and use the return function to terminate it. If not, the zero flag will let the function go and start encrypting the data and doing other fun
Encrypting will start below
I will use the Debugger x32 tool to step through the malware’s execution, setting breakpoints to execute the program line by line. This will allow me to closely examine its behavior, track the flow of the program, and analyze key actions such as encryption routines and network communication, providing a deeper understanding of the malware’s malicious operations.
I started by searching for the URL by searching the string and I set a breakpoint on that instruction so we can start executing that program from this line.
From that point, I will step over every instruction by pressing F8 in the Debugger x32 tool. This will allow me to execute the program line by line, providing a detailed view of each operation and helping me identify critical actions, such as file manipulation or network communication, to better understand the ransomware’s behavior.
Before stepping over the code, we can see that the APIs below and the URL and see the parameters that were passed to the API functions. Also, in the InternetOpenUrlA, we can see the instruction esi was passed which refers to the URL as shown at the top of the code. We see that the esi=URL, and then the esi is passed to the API. We can also see the if else statements in the InternetCloseHandle function.
I began stepping over each instruction until I reached the InternetCloseHandle
function. Here, I tested the conditions by modifying the Zero Flag (ZF), toggling it between 0 and 1, to observe how the malware responds. This approach helped me understand how the ransomware determines whether to activate the killswitch or proceed with its encryption functions, depending on the flag’s state.
Also as shown below, the code performs a self-test, and then uses the jne
(Jump if Not Equal) instruction to decide the next action. This conditional jump depends on the result of the test
As shown at the bottom left below, if the Zero Flag is set to 0, the function will trigger a jump, skipping the remaining functions and reaching a return
instruction that terminates the executable. This effectively stops the ransomware’s execution, preventing it from continuing with its malicious actions.
Alternatively, if the Zero Flag is set to 1, the program proceeds by calling the remaining functions, initiating the ransomware’s encryption process. As shown below, this leads to the malware encrypting the files on my VM, demonstrating its full impact when the killswitch is bypassed.
Conclusion
In conclusion, this project provided an in-depth look into the inner workings of the WannaCry ransomware, from static and dynamic analysis to reverse engineering. By using tools like Flare VM, REMnux, Cutter, Procmon, and Debugger x32, I examined how the malware communicates with external servers, attempts to establish persistence, and initiates encryption based on specific conditions. Through careful step-by-step inspection, including testing flags and understanding API call behaviors, I was able to observe WannaCry’s encryption mechanism and explore its killswitch functionality. This analysis underscores the importance of understanding malware behavior at the assembly level.
Thank you for reading. I hope you found this analysis insightful!