Ransomware · Ransomworm · Worm
WannaCry - invoice_greenanimals.pdf.exe
- Author
- Moise Medici
- Updated
- 15 Feb 2026 · Completed
- Difficulty
- Medium
- Platform
- Capabilities
- Tags
Question 6 and Question 10
Opening the sample with Ghidra, Windows → Defined Strings can be used to locate the URL. From there, searching the URL, clicking on the reference found, and following it lands in the .data area of the PE file that stores the URL.
Right click on the address of the reference (in this case 004313d0): References → Show References To Addresses. There will be 3 entries:
- The one marked as “DATA” is the reference just clicked on.
- The two other entries marked as “READ” are addresses where the URL is read.
In this case it is safe to double-click on any of the “READ” addresses; if you look at the “location” address, they are just one instruction apart, the first at 00408155 and the second at 00408157.
This reveals a list of assembly instructions like this:
Notice that the URL has been saved in a memory space using MOVSD and MOVSB, which are just string versions of MOV 10.
Also notice that just a few lines after the MOV of the URL, there is an InternetOpenUrlA call. To confirm which URL the CALL is using, Ghidra usually helps by showing the arguments of functions that it is able to identify, but in this case it is not. This can be improved by going to the “Data Type Manager” (usually on the left side of the window), clicking on winapi_32 → Apply Function Data Types. Once that is done, go to Analysis → One Shot → WindowsPE x86 Propagate External Parameters.
Now all the parameters should be clearly named.
Before proceeding, looking at the Microsoft documentation 11 the parameters used are:
HINTERNET InternetOpenUrlA( [in] HINTERNET hInternet, [in] LPCSTR lpszUrl, [in] LPCSTR lpszHeaders, [in] DWORD dwHeadersLength, [in] DWORD dwFlags, [in] DWORD_PTR dwContext);The function “returns a valid handle to the URL if the connection is successfully established, or NULL if the connection fails.”
The first two parameters are those of most interest. The first one, hInternet, is a handle provided by InternetOpenA, which is called a couple of lines before InternetOpenUrlA. The second parameter of interest is lpszUrl, which is the actual URL. From here, it is useful to go backwards: look at which register contains the lpszUrl content, and see how it gets initialized.
This is the full function code up to the call under investigation:
******************************************************* * FUNCTION * ******************************************************* undefined FUN_00408140() assume FS_OFFSET = 0xffdff000 undefined AL:1 <RETURN> undefined1 Stack[-0x1] local_1 XREF[1]: 00408177(W) undefined2 Stack[-0x3] local_3 XREF[1]: 0040816c(W) undefined4 Stack[-0x7] local_7 XREF[1]: 00408168(W) undefined4 Stack[-0xb] local_b XREF[1]: 00408164(W) undefined4 Stack[-0xf] local_f XREF[1]: 00408160(W) undefined4 Stack[-0x13 local_13 XREF[1]: 0040815c(W) undefined4 Stack[-0x17 local_17 XREF[1]: 00408158(W) undefined1 Stack[-0x50 local_50 XREF[2]: 0040814f(*), 0040818a(*) FUN_00408140 XREF[1]: entry:00409b45(c)00408140 SUB ESP, 0x5000408143 PUSH ESI00408144 PUSH EDI ; HINTERNET hInternet for InternetCloseHandle00408145 MOV ECX, 0xe0040814a MOV ESI, s_http://www.iuqerfsodp9ifjaposdfj_004313 ; = ; "http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergw ; ea.com"0040814f LEA EDI=>local_50, [ESP + 0x8]00408153 XOR EAX, EAX00408155 MOVSD. ES:EDI, ESI=>s_http://www.iuqerfsodp9ifjaposdf ; = ; "http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergw ; ea.com"00408157 MOVSB ES:EDI, ESI=>s_http://www.iuqerfsodp9ifjaposdf ; = ; "http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergw ; ea.com"00408158 MOV dword ptr [ESP + local_17], EAX0040815c MOV dword ptr [ESP + local_13], EAX00408160 MOV dword ptr [ESP + local_f], EAX00408164 MOV dword ptr [ESP + local_b], EAX00408168 MOV dword ptr [ESP + local_7], EAX0040816c MOV word ptr [ESP + local_3], AX00408171 PUSH EAX ; DWORD dwFlags for InternetOpenA00408172 PUSH EAX ; LPCSTR lpszProxyBypass for InternetOpenA00408173 PUSH EAX ; LPCSTR lpszProxy for InternetOpenA00408174 PUSH 0x1 ; DWORD dwAccessType for InternetOpenA00408176 PUSH EAX ; LPCSTR lpszAgent for InternetOpenA00408177 MOV byte ptr [ESP + local_1], AL0040817b CALL dword ptr [->WININET.DLL::InternetOpenA] ; = 0000a7dc00408181 PUSH 0x0 ; DWORD_PTR dwContext for InternetOpenUrlA00408183 PUSH 0x84000000 ; DWORD dwFlags for InternetOpenUrlA00408188 PUSH 0x0 ; DWORD dwHeadersLength for InternetOpenUrlA0040818a LEA ECX=>local_50, [ESP + 0x14]0040818e MOV ESI, EAX00408190 PUSH 0x0 ; LPCSTR lpszHeaders for InternetOpenUrlA00408192 PUSH ECX ; LPCSTR lpszUrl for InternetOpenUrlA00408193 PUSH ESI ; HINTERNET hInternet for InternetOpenUrlA00408194 CALL dword ptr [->WININET.DLL::InternetOpenUrlA] ; = 0000a7c80040819a MOV EDI, EAXlpszUrl is contained in ECX. At line 0040818a ECX is loaded with the address of local_50. Tracing local_50 back shows that ESI is first initialized with the URL string at 0040814a, and that string is then copied into the buffer pointed to by EDI (local_50) via MOVSD and MOVSB at 00408155 and 00408157.
0040814a MOV ESI, s_http://www.iuqerfsodp9ifjaposdfj_004313 ; = ; "http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com"0040814f LEA EDI=>local_50, [ESP + 0x8]00408155 MOVSD. ES:EDI, ESI=>s_http://www.iuqerfsodp9ifjaposdf ; = ; "http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com"This shows how local_50 is populated and then used by InternetOpenUrlA as the URL parameter.
After the InternetOpenUrlA call, to understand what is done with the return value, the surrounding code is followed, focusing on the highlighted lines:
00408194 CALL dword ptr [->WININET.DLL::InternetOpenUrlA] ; = 0000a7c80040819a MOV EDI, EAX0040819c PUSH ESI ; HINTERNET hInternet for InternetCloseHandle0040819d MOV ESI, dword ptr [->WININET.DLL::InternetCloseHandle] ; = 0000a7b2004081a3 TEST EDI, EDI004081a5 JNZ LAB_004081bc004081a7 CALL ESI=>WININET.DLL::InternetCloseHandle004081a9 PUSH 0x0 ; HINTERNET hInternet for InternetCloseHandle004081ab CALL ESI=>WININET.DLL::InternetCloseHandle004081ad CALL FUN_00408090 ; undefined FUN_00408090()004081b2 POP EDI004081b3 XOR EAX, EAX004081b5 POP ESI004081b6 ADD ESP, 0x50004081b9 RET 0x10 ;004081bc is below hereThe return value of InternetOpenUrlA is in EAX, which is immediately moved into EDI and then tested. Since TEST is an implied AND instruction (it does not change the value of EDI but just computes EDI AND EDI and sets flags), the JNZ is used to check the zero flag set by TEST EDI, EDI, meaning:
- If the connection was successful →
EDIis not zero →TEST EDI, EDIsets ZF to0→ jump toLAB_004081bc. - If the connection was not successful →
EDIis zero →TEST EDI, EDIsets ZF to1→ execution continues to004081a7andFUN_00408090is executed.
When the connection is successful, the code at LAB_004081bc is straightforward: a call to InternetCloseHandle and end of the function.
LAB_004081bc XREF[1]: 004081a5(j)004081bc CALL ESI=>WININET.DLL::InternetCloseHandle004081be PUSH EDI ; HINTERNET hInternet for InternetCloseHandle004081bf CALL ESI=>WININET.DLL::InternetCloseHandle004081c1 POP EDI004081c2 XOR EAX, EAX004081c4 POP ESI004081c5 ADD ESP, 0x50004081c8 RET 0x10To see where it returns, Window → Function Call Tree shows the Incoming Calls menu containing entry. Double-clicking it shows the code that calls the function under examination, from the entry function. This shows that if the connection is successful, the program is terminated by calling MSVCRT.DLL::exit.
00409b45 CALL FUN_00408140 ; undefined FUN_00408140()00409b4a MOV dword ptr [EBP + local_6c], EAX00409b4d PUSH EAX ; int _Code for exit00409b4e CALL dword ptr [->MSVCRT.DLL::exit] ; = 0000a8c2If the connection fails, FUN_00408090 is executed. Looking briefly at this function shows calls to OpenSCManagerA, OpenServiceA, etc., implying that the rest of the program is executed.
This shows that the URL is actually used as a kill switch: if there is a connection to the URL, the program is terminated. The sample can be stopped from fully executing by simply allowing it to resolve the domain name.