Lab 6 - Disassemblers and Debuggers

In this lab, you will familiarize yourself with the x64dbg interactive disassembler and debugger.

Deliverables

Upload the following items to the Lab 6 Assignment on Canvas when finished.

  • The PDF file containing the required documentation

Part 1 - File I/O and Decryption

The malware creates a file on disk, but the contents are encrypted. Rather than laboriously reverse engineering the decryption algorithm, let the malware decrypt the file normally, and use x64dbg to steal it from memory. The ReadFile() function is a logical first place to look for file I/O, and hope that the decryption occurs afterwards.

Question Answer
What is the name of the calling convention for 64-bit Windows executables? Provide an example of this calling convention for the hypothetical function int returnCode = myFunction(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
Take a screenshot of PEStudio showing that the malware imports ReadFile().
Take a screenshot of x64dbg showing calls to ReadFile() from all modules.
(Right click in CPU panel, and choose Search for->All Modules->Intermodule Calls)
Take a screenshot of x64dbg showing calls to ReadFile() from just the brbbot.exe module.
(Confirm that the EntryPoint breakpoint is set, run to that breakpoint, and do Search for->Current Module->Intermodule Calls)
Take a screenshot of x64dbg showing the 5 arguments to the first call to ReadFile(). Document which argument corresponds to which value, e.g. "Argument 1: 'hfile' : Register ecx : Value ###".
(Set a breakpoint on any calls to ReadFile via the command "SetBPX ReadFile". Run to that breakpoint).
Take a screenshot of x64dbg confirming that the hFile argument to ReadFile() does reference the encrypted file you seek.
(Switch to the Handles panel and right-click to refresh the view.)
Take a screenshot of x64dbg showing the user-space assembly code (not library code) that immediately follows the call to ReadFile(). Scroll up by one line to ensure that your view starts with the call to ReadFile().
(Use Debug->Run to User Code to quickly run through the implementation of ReadFile and return from it.)
What function is likely used to decrypt the file?
Take a screenshot of x64dbg showing the 6 arguments to this decryption function. Document which argument corresponds to which value, e.g. "Argument 1: 'hKey' : Register ecx : Value ###".
(Highlight the decryption function line, and then Debug->Run until Selection, at which point all the function arguments should be visible.)
Take a screenshot of x64dbg showing the encrypted memory region in the Dump panel.
(Select the memory address, right-click and choose Follow in Dump)
Take a screenshot of x64dbg showing the decrypted memory region in the Dump panel.
(Step over the decryption function, and watch the Dump panel change)

Part 2 - Networking

The malware communicates over the network to an HTTP server to exfiltrate data and for command and control purposes.

Question Answer
What is the request sent by the malware to the remote web server? (Capture with behavioral analysis tools from prior labs)
Take a screenshot of x64dbg showing where the malware passes the HTTP User Agent to a Win32 API function for Internet communication. Document exactly which argument this value corresponds to in the Win32 API.
Take a screenshot of x64dbg showing where the malware passes the file to GET on the remote server to a Win32 API function. This argument includes both the filename and the associate form data. (i.e. file.dat?key1=value2,key2=value2, etc...). Document exactly which argument this value corresponds to in the Win32 API. (Take a close look at HttpOpenRequestA().)

Part 3 - Hidden Library Functions

Malware authors often call functions in the Win32 API that are not listed in the import table in the Portable Executable (PE) file. Sometimes this is done to obfuscate their program - more on this in a future lab. Other times, they are trying to call undocumented, internal Microsoft functions to gain access to additional functionality, or access conventional functionality in a different manner to fly under the radar.

If a function is not imported when the PE file is loaded, then the programmer must import it at runtime from the Dynamic Link Library (DLL) using the GetModuleHandle() and GetProcAddress() functions. The pseudo-code to import a function and then use it is:

handle = GetModuleHandle("FILE.DLL");
newFunction = GetProcAddress(handle,"desiredFunction");
result = newFunction(arg1,arg2,arg3,...);

Task: Set a breakpoint on calls to GetModuleHandle() and answer the following questions regarding the second call to GetModuleHandle() and the events immediately following.

Question Answer
For the second call to GetModuleHandle(), what DLL name is being imported? Provide a screenshot clearly showing this DLL name as an argument.
What memory address stores the string with the DLL name?
For the call to GetProcAddress() immediately following the above call to GetModuleHandle(), what function in the previously identified DLL is being requested? Provide a screenshot clearly showing this function name as an argument.
What memory address stores the string with the function name?
When the call to GetProcAddress() returns, where specifically is the pointer to the function stored?
When the call to GetProcAddress() returns, what function does x64dbg say (in its comments fields) is being pointed to? Is it the same? If not, speculate on why.
Where is the pointer to the function stored next? (It can't stay in its original location, which will soon be overwritten)
Using the highlight mode in x64dbg, find where the function imported from the DLL is actually called. What is the assembly instruction? What is the memory address of the instruction?
From visual inspection of the surrounding function, there are two calls to RtlAllocateHeap(). When this function returns, where specifically is the pointer to the newly-allocated memory stored?
Investigate these heap locations. Set Dump 1 to show the first location allocated by RtlAllocateHeap() and Dump 2 to show the second location allocated. Then, execute to the end of the function. Is there anything interesting in Dump 1? Is there anything interesting in Dump 2? Hint: One location should have interesting contents. Provide a screenshot of the contents.