Malware analysis with xdbg
Recently I've been playing with a tool called DarkArmour which encrypt windows binaries to execute inside memory. I thought it would be fun to take a look at how the ofuscated binary behaves while being executed. As you may expect, it will XOR the original PE file, which will then be unpacked and loaded inside memory; This is a typical behaviour of malware.
First of all, lets compile our own super-l33t malware.
#include <Windows.h>
#include <WinUser.h>
int showMessageBox() {
int messageID = MessageBox(NULL, "oh no! you're infected!", "Ransomware INC.", NULL);
return messageID;
}
int main() {
showMessageBox();
return 0;
}
In case you need info about the MessageBox function, here you got the documentation.
As expected, if we execute the file will show up this:
Taking a look at the Import Table we can see that the PE is loading the Windows API MessageBoxA
function.
Also, the binary is loading some other functions, but I wanted to show that LoadLibraryA
or VirtualAlloc
it's not between them. As we will see soon, the obfuscated PE file will have those functions between the imports, probably to do dynamic linking and process injection.
Obfuscate the malware and analyze it
Now lets obfuscate our PE file to avoid detection. You can follow the instructions in the DarkArmour github, but here is the line I used:
./darkarmour.py -f ransomware_l33t.exe --encrypt xor --jmp -o /tmp/obfuscated.exe
Now the fun begins. Lets load the obfuscated PE file and check its import table. We can see some new functions are imported, but more important, our MessageBoxA
it's not there!
VirtualAlloc
, as said before, can be used to do process injection.
VirtualProtect
will change the protection on a region of memory. Malware use this function to change a read-only section of memory to an executable.
LoadLibraryA
will load DLL into a process that may not have been loaded when the program started.
The idea is to find where the deobfuscation is happening and then try to dump the code to compare it with the original. Load the executable in xdbg and let it run until user code.
If you start steping into your binary functions, eventually will show up the deobfuscation loop. You can see that it will XOR the value of eax
registry to 44
and then move the result to edx
registry. Finally, it will write the result to memory.
How can we be sure? Well, if you let it run a few iterations you will start seeing the PE header:
We could start spamming the "step over" button until the deobfuscation is done, but we are better than that, so lets toggle a breakpoint at the end of the loop; right after the jle obfuscated.401927
instruction and let it run.
You can now see the memory is full with something that looks like a PE file. Lets dump this to disk and further analyze it! To do this, on xdbg you can use the savedata
command to dump the memory region you're interested in. We know the size of the exact data we want to dump because we got the original code, so lets run it:
savedata C:\\temp\\memory.dmp, 6B17E0, E5F8
The second argument is the start address of the section we want to dump, and the third one is the size of the section.
Cool! If we compare the hex bytes with our original PE file, it looks kinda the same.
In fact, if we check the imports within this memory dump we can see that are the same as our original file.
Going back to xdbg, we will eventually see that VirtualAlloc
is being called with the following arguments:
VirtualAlloc(0x140000000, 0x25000, 0x3000, 0x40)
If we check the documentation we can see that the third argument is being setted to MEM_COMMIT | MEM_RESERVE
, and the fourth to PAGE_EXECUTE_READWRITE
, which will turn the memory region executable.
Following the execution flow, we can see that finally the LoadLibraryA
will call USER32.dll, and then call GetProcAddress
to retrieve the address of the function MessageBoxA
.
Final thoughts
We could keep digging and check what strings the dumped memory section had, but I think we've reached an interesting point to start with malware analysis. Of course, this was a unharmful, simple example to start. Malware will usually be harder to analyze, so good luck!