A bit ago, Andreas Schuster posted to his blog about reconstructing executable images from a RAM dump (1, 2, 3). The first method listed not only made the most sense to me at the time, but was also easy to implement, as it dovetailed right off of some code I'd written to parse PE file headers. As I blogged about earlier, getting the PE header information from the ImageBaseAddress offset is just the beginning.
I'm posting now to say that I recently got the code for automatic reassembly of executable images working. My results are identical to those shown in Andreas's first blog post. I suspect that Andreas may be correct in his third post that the reassembled binary won't run correctly due to changes in code as the program runs. However, there are other conditions to consider...for instance, what if pages from the image have been paged out to the pagefile?
After extracting the binary image for dd.exe from the first RAM dump used in the DFRWS 2005 Memory Challenge, I ran a script to extract the PE header info, and compared that to the PE header info for the original copy of the executable, retrieved from George Garner's site. Visually, the headers are identical. I've since used Jesse Kornblum's md5deep tool to verify that the .rsrc sections from both files (original and reconstructed) are identical.
More testing needs to be done, and the code needs to be cleaned up and brought in line with the other code already available. Once I've completed this, I'm going to redesign the format of the tools to be better suited to identifying the OS of the RAM dump, and then progressing on from there. At this point, like the other tools currently available, this code only works for RAM dumps from Windows 2000 systems.
You may be saying to yourself..."Yeah...and?" Some folks ask me why this kind of thing is important. Well, for one, if you're performing live response and suspect that there may be malware or a rootkit, you may want to actually get the executable for analysis. This may also be useful during dynamic analysis of malware, in which obfuscated malware is decompressed/decrypted when in memory.
Hey Harlan, thanks for the plug.
ReplyDeleteHow did you hash the individual sections? Write them out to separate files?
Jesse,
ReplyDeleteYes, that's what I started doing...write each section out to individual files and hash that file.
The plug is well-deserved.
Harlan
It's not necessary to write the sections to files. Once you've parsed the PE you know how big the sections are and their RVA.
ReplyDeleteAAron
(Jesse how's that project coming!)
AAron,
ReplyDeleteGiven your method, how would you then hash each individual section?
Harlan,
ReplyDeleteAhhh. Sorry I keep thinking in terms of how we do these things on our project. So with our project we rebuild the address spaces in memory with our accumulator functions. Thus I don't have to worry about the virtual to physical transformations or the relative virtual addressing since they are taken care of behind the scenes. In the end, it is pretty much the same thing as writing to a file, except we do it in memory. Once it is rebuilt, then we simply perform the hash of the data stream associated with each section in memory. Sorry for the confusion.
By the way, I've been working on a whitepaper about some of the stuff my group has been doing. Let me know if you'd be interested in reviewing it before I release it. Are you planning to go to DFRWS?
thanks,
AAron
Aaron,
ReplyDeleteWhat project are you working on? It sounds interesting, and yes, I would be interested in reading your whitepaper.
As for DFRWS, unfortunately, I won't be going. I'm slotted to present at GMU2006, though.
Harlan
Harlan,
ReplyDeleteThe FATkit project. Great!! I'm currently trying to clean it up but I will send it to you once I'm happy with it. I'm sorry you won't be able to make it. I was trying to see if people may be interested in a memory forensics bof.
thanks,
AAron
Aaron,
ReplyDeleteI'll check out FATkit.
Re: the BoF...I'd appreciate an opportunity to discuss this area, definitely.