Saturday, April 15, 2006

Reassembling an image file from a memory dump

Andreas Schuster posted a tutorial on his blog for reassembling the executable image of a process from a dump of physical memory a bit ago. As I've already got Perl code for parsing PE headers, why not automate the process?

So far, I've completed the first step in reassembling the image...parsing the PE headers. To do this, locate the PEB for the process (from the information located in the EPROCESS block...use lsproc and then lspd from my SourceForge site to get the necessary information) and from there, get the value for the ImageBaseAddress (a DWORD located at offset 0x08 within the PEB). Convert that virtual address to a physical offset within the dump file (done by the code) and, if the physical offset is "present", read in the 4K page located at that address. Now, the PE header isn't usually 4K (4096 bytes) in size, so most of the page will be zeros. However, we can parse out the information we need. For example, I ran some tests using the process named "nc.exe"...

The initial information looked good:

DOS header located.
e_lfanew = 128 (0x00000080)
NT Header = 0x4550

The "DOS Header" is "MZ", and the value for e_lfanew is something that we're going to use for several calculations. The NT Header is valid, as it translates to "PE". Next, we read the Image File Header and find that there are 4 sections, and the image has the following characteristics:


From the Image Optional Header, we get:

Opt Header Magic = 0x10b
Entry Pt Addr : 0x00004c00

Notice the value for the entry point address. This will be important later, particularly when we perform detailed analysis of the image file itself. Tools such as PeID use entry point analysis to determine things such as packers and encryption used on obfuscated binaries (mostly malware). If you know what you're doing, you can get a lot of information by determining not only the location of the entry point, but also the contents (first 100 bytes or so) of the entry point.

Moving on, we pull out the Image Data Directories:

Data Directory RVA Size
-------------- --- ----
ResourceTable 0x00000000 0x00000000
DebugTable 0x00000000 0x00000000
BaseRelocTable 0x00000000 0x00000000
DelayImportDesc 0x00000000 0x00000000
TLSTable 0x00000000 0x00000000
GlobalPtrReg 0x00000000 0x00000000
ArchSpecific 0x00000000 0x00000000
CLIHeader 0x00000000 0x00000000
LoadConfigTable 0x00000000 0x00000000
ExceptionTable 0x00000000 0x00000000
ImportTable 0x00012000 0x0000003c
unused 0x00000000 0x00000000
BoundImportTable 0x00000000 0x00000000
ExportTable 0x00000000 0x00000000
CertificateTable 0x00000000 0x00000000
IAT 0x000121a0 0x00000164

We see from this that the only data directories are the Import (Name) Table and the Import Address Table (IAT). Once we reassemble the image, we will be able to use this information to determine which DLLs the image accesses, and which functions from those DLLs it imports.

Finally, we look at the Image Section Headers:

Name Virt Sz Virt Addr rData Ofs rData Sz Char
---- ------- --------- --------- -------- ----
.text 0x00009770 0x00001000 0x00000400 0x00009800 0x60000020
.data 0x00005244 0x0000c000 0x0000a200 0x00003e00 0xc0000040
.idata 0x0000075c 0x00012000 0x0000e000 0x00000800 0xc0000040
.rdata 0x00000417 0x0000b000 0x00009c00 0x00000600 0x40000040

Remember, from the Image File Header, we found that there were 4 sections. Now we have more detailed information about those sections.

Using the code I have now, I took a look at the same process that Andreas used in his tutorial...dd.exe, PID 284. I extracted the same information he listed, down to the section headers. Now, to begin automatically reassembling the image, we simply need to follow the advice given by Andreas; specifically, given the information we've extracted from the PE header, go back into the physical dump file, extract those pages and reassemble them in order. The test will then be not only to view the complete PE header information, Import Table and resources of the file using something like File::ReadPE (or use tools such as pedump or PEView), but to also actually launch the image.

No comments: