Sunday, July 22, 2012

Get-PEHeader - A Scriptable In-memory and On-disk PE Parsing Utility

Introducing, yet another PE parsing utility! Where Get-PEHeader differentiates itself though is that it will parse 32 and 64-bit executables both on disk and loaded in memory. Where it really shines is in its scriptability. For example, you can pipe the output of ls (Get-ChildItem) or ps (Get-Process) right to Get-PEHeader and it will return to you a fully parsed PE header.

In this post, I'm going to show you how to:

1) Set it up and get help
2) Use Get-PEHeader to analyze every loaded module in a process
3) Interactively inspect the in-memory PE header of kernel32.dll
4) Do some quick and dirty memory forensics using a reflectively loaded meterpreter sample
5) Analyze PE headers on disk

Setting things up

I've decided to package all of my PE tools from the PowerSploit project into a module for increased portability. For those who aren't terribly familiar with PowerShell, importing a module isn't initially straightforward. Just follow the following steps and refer to the screenshot below to get things up and running:

1) Download the PETools folder from the PowerSploit project
2) Drop the folder into one of your module paths. You can view your default module paths in Powershell by typing:

Now you can start digging deeper. Let's check out kernel32.dll. In particular, I'm interested in looking at all of its exported functions.

$Kernel32PE = $CmdModules[2]$Kernel32PE.Exports

You'll see that listing the module's exports lists the virtual address, exported ordinal, name, and forwarded name (if available)

Inspecting the exported functions of kernel32.dll in memory

Doing some quick and dirty memory forensics using a reflectively loaded meterpreter sample

Now let's move beyond the novelties and start doing some in-memory malware analysis. I injected meterpreter into one of my running processes. For the armchair malware analyst, you probably wouldn't stumble upon anything terribly suspicious when attempting to view the loaded dlls of the infected process. That's because meterpreter gets reflectively loaded - i.e. it has a self-loading stub that loads itself in memory rather than having Windows do it. Since the main meterpreter dll - metsrv.dll is not visible to Windows in user-mode, you have to dig in a little deeper to find the address where it was loaded in memory. To quickly find the address, I attached to the process in WinDbg and used the .imgscan command to quickly determine the base address of metsrv.dll - 0x02560000. Armed with the knowledge of the infected process ID and the base address of the malicious module, you can use Get-PEHeader to dissect the PE header of meterpreter in memory.

Tip to malware authors: if you're loading your own module in memory, the executable doesn't need to start with 'MZ.' Just sayin'

As can be seen in the screenshot below, there are some things that just don't look right. First, if you've looked at enough DOS headers, you'd notice that some of those values don't look right. So if you broke out a hex editor and a disassembler, you'd see that the DOS header was comprised of an x86 assembly self-loader stub. Fortunately, you don't even have to get that sophisticated. If you look at the exports, you'll see '_ReflectiveLoader@0' and 'Init' - a sure sign you're dealing with meterpreter. By the way, the name decoration around ReflectiveLoader tells you that it's a stdcall function that takes zero arguments.

Finally, you can use Get-PEHeader to analyze the PE headers of files on disk:

$CalcHeader = Get-PEHeader C:\Windows\System32\calc.exe

Parsing the calc.exe PE header on disk

Get-PEHeader in its current form is not nearly as sophisticated as dumpbin or CFF Explorer. Those tools are only able to parse PEs on disk, however. Currently, Get-PEHeader will parse and return the following:

I have checked out that poster. Ange does awesome work. My main references though were this poster from openrce.org: http://www.openrce.org/reference_library/files/reference/PE%20Format.pdf and winnt.h.

This is awesome! If you decide to add the authenticode/sigcheck-type functionality - that would be amazing... Also, since I haven't had the time to go through the code, my question is 'can this function be administered remotely like icm?' If so, I'm in heaven.

Thanks. I agree that certificate parsing would be awesome but it's not a priority for me right now.

You can certainly run it remotely with Invoke-Command but you'll have to pass the Get-PEHeader function definition along with the Get-PEHeader command itself since the remote machine doesn't have the function defined. I wrote an Invoke-Command proxy function to seamlessly automate this process so that the function definition will be automatically passed to the remote machine. https://gist.github.com/sunnyc7/8e947c02ca0fec828044