Building on my last post, I’m going to take a deeper look at the AccessEnum.exe binary, and cover the basic reverse-engineering process (not entirely the way I’ve been taught) using objdump and a GUI for Radare. The following is the kind of work that goes into producing anti-malware vendors’ threat reports.
Portable Executable File Headers
The good thing about UNIX systems is they handle .exe files as archives, which means their contents can be extracted and viewed as a file/directory structure. Most the Portable Executable headers are shown as individual files and directories:
There are nine possible section headers in the executable format, which marks it out as an application for Windows NT, but AccessEnum.exe uses just the following:
* .text: Main code instructions here.
* .debug0: Debug information and references to debug sections in .rdata
* .rdata: Generally read-only data and persistent handles go here.
* .data: Strings used and displayed by the executable at runtime.
* .rsrc: Resources used within the executable. Icons, bitmaps, etc.
But this doesn’t tell us much about the resources the program uses when running. For that, something like objdump is needed again. Using objdump we can get the section headers used and their virtual memory addresses:
$objdump -h AccessEnum.exe
As seen before, objdump also provides a list of DLLs, their associated handles used by the executable and their virtual memory addresses:
$objdump -p AccessEnum.exe
Out of curiosity, I also ran objdump against XeroCrypt.exe, and as expected, the import tables were instead found in .text because my application simply consisted of calls to .NET components.
Content and Assembler Instructions
Moving on… Now the memory addresses and general purpose of each section is known, it’s possible to start making deductions about what the program does by examining the contents of those memory locations in a disassembler. The information should be displayed in a text field in whatever disassembler’s being used for this.
I loaded AccessNum.exe into Bokken, and moved directly to the .text section where the program’s instructions themselves should be. To the left, we can see the virtual memory address (0x1000) and the size (0xf18) match the objdump output, so this was definitely the right section.
Here we have x86 assembler instructions, and certain sequences are directly translatable to generic C programming structures, which is how a disassembled program’s function could be derived. See the first chapter of The Shellcoder’s Handbook and Appendix E of Programming From the Ground Up for examples of this.
The sections of code separated by dashed lines are discrete functions. Taking just one of these functions:
mov esi, ecx
mov ecx, [esi+0x1c]
test ecx, ecx
Memory register ESI seems the main one used here, and as I understand it, ESI differs from other registers in that it holds 32 bits, unlike the 8-bit or 16-bit segment registers.
The first instruction pushes the contents of ESI (which could be anything) onto the stack, then the contents of ESI are replaced with whatever’s in ECX. The contents of ECX in turn is replaced with whatever’s stored at address ESI +0x1c.
The last two instructions check the value stored in register ECX, and if ECX=0 the program jumps to address 0x0000103d.
So what does that mean? It seems like our function was designed simply to check a specific value within a memory register. It’s almost impossible to determine exactly why – that would be a matter of translating every function into pseudo-code before stringing it all together. Probably.
Also interesting, moving onto the memory address where the .rdata section begins (0x8000), are the readable text strings. These are clearly static and intended to be what the user sees during runtime.
Slightly further on, from address 0x09ad0, we can see what looks like .NET code for creating dialogues and GUI components.