Saturday, July 28, 2012

Deep Reflection - Defining Structs and Enums in PowerShell

One of the reasons PowerShell is so powerful is in its ability to access to .NET framework. In theory, this should make the transition for C# developers seamless. Unfortunately, PowerShell is not quite a one-to-one translation of C#. I demonstrated where this is not the case in a previous post by illustrating the hoops you need to jump through to declare a delegate type in PowerShell using reflection. Declaring an enum or struct is no different.

Before I jump into the technical details, it's worth addressing the question you may have already formed. Why don't you just compile C# code using the Add-Type cmdlet? Well, that is a perfectly valid method of declaring a struct, enum, delegate, etc. However, compiling C# code leaves artifacts on the disk. To prove my point, just run Procmon while compiling C# in PowerShell. As someone with an attacker's mindset, I prefer that all operations take place in memory unless absolutely necessary. Fortunately, true memory residence can be achieved using reflection.

As an example, here is a portion of the code from my last PowerSploit release - Get-PEHeader:

$code = @"
    using System;
    using System.Runtime.InteropServices;
 
    public class PE
    {
        public enum IMAGE_DOS_SIGNATURE : ushort
        {
            DOS_SIGNATURE =                 0x5A4D,      // MZ
            OS2_SIGNATURE =                 0x454E,      // NE
            OS2_SIGNATURE_LE =              0x454C,      // LE
        }


        [StructLayout(LayoutKind.Sequential, Pack=1)]
        public struct _IMAGE_DOS_HEADER
        {
            public IMAGE_DOS_SIGNATURE   e_magic;        // Magic number
            public ushort   e_cblp;                      // public bytes on last page of file
            public ushort   e_cp;                        // Pages in file
            public ushort   e_crlc;                      // Relocations
            public ushort   e_cparhdr;                   // Size of header in paragraphs
            public ushort   e_minalloc;                  // Minimum extra paragraphs needed
            public ushort   e_maxalloc;                  // Maximum extra paragraphs needed
            public ushort   e_ss;                        // Initial (relative) SS value
            public ushort   e_sp;                        // Initial SP value
            public ushort   e_csum;                      // Checksum
            public ushort   e_ip;                        // Initial IP value
            public ushort   e_cs;                        // Initial (relative) CS value
            public ushort   e_lfarlc;                    // File address of relocation table
            public ushort   e_ovno;                      // Overlay number
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
            public string   e_res;                       // May contain 'Detours!'
            public ushort   e_oemid;                     // OEM identifier (for e_oeminfo)
            public ushort   e_oeminfo;                   // OEM information; e_oemid specific
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=10)]
            public ushort[] e_res2;                      // Reserved public ushorts
            public int      e_lfanew;                    // File address of new exe header
        }
    }
"@


Add-Type -TypeDefinition $code -WarningAction SilentlyContinue | Out-Null

As you can see, the C# 'code' above defines an enum and a struct that are compiled when Add-Type is called. The need to compile the code above can be obviated with reflection. This however requires some understanding of the attributes that define the fields in the enum and struct above. Interrogating these attributes can be accomplished with ildasm or PowerShell. I'll show you how to do this in PowerShell.

First, let's view the attributes of the IMAGE_DOS_SIGNATURE enum:

PS > [PE+IMAGE_DOS_SIGNATURE] | Format-List BaseType, Attributes
BaseType   : System.Enum
Attributes : AutoLayout, AnsiClass, Class, NestedPublic, Sealed

Now, let's view all the relevant individual attributes of the _IMAGE_DOS_HEADER struct:

PS > [PE+_IMAGE_DOS_HEADER] | Format-List BaseType, Attributes
BaseType   : System.ValueType
Attributes : AutoLayout, AnsiClass, Class, NestedPublic, SequentialLayout, Sealed, BeforeFieldInit
PS > [PE+_IMAGE_DOS_HEADER].GetField('e_res').GetCustomAttributes($True) | Format-List Value, TypeId, SizeConst
Value     : ByValTStr
TypeId    : System.Runtime.InteropServices.MarshalAsAttribute
SizeConst : 8
PS > [PE+_IMAGE_DOS_HEADER].GetField('e_res2').GetCustomAttributes($True) | Format-List Value, TypeId, SizeConst
Value     : ByValArray
TypeId    : System.Runtime.InteropServices.MarshalAsAttribute
SizeConst : 10

Now we have everything we need to dynamically generate the enum and struct. The following code demonstrates how to accomplish this and returns the DOS header for calc.exe:


By now, you can see the additional overhead required to dynamically generate code. However, if your goal is to avoid compiling code and remain truly memory resident, this is the way to go. Expect to see an update to Get-PEHeader that will implement these changes in the near future.

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:

$Env:PSModulePath

Note:
 - After you drop the folder in the module path, restart PowerShell
 - The default per-user module path is: "$Env:HomeDrive$Env:HOMEPATH\Documents\WindowsPowerShell\Modules"
 - The default computer-level module path is: "$Env:windir\System32\WindowsPowerShell\v1.0\Modules"

3) Import all the scripts in the module

Import-Module PETools

4) You can view all the cmdlets that were imported by typing:

Get-Command -Module PETools

5) For individualized help on each command, Get-Help is your friend.

Setting up the PETools module for use


Using Get-PEHeader to analyze every loaded module in a process

This is easy. We're going to use cmd.exe as an example. Simply run the following command:

$CmdModules = Get-Process cmd | Get-PEHeader

Note that this will only work if there is only one instance of cmd.exe open. If there is more than one, just give Get-Process a specific process ID.

Once the command completes (it may take ~30-40 seconds) you can start poking around. If you try this yourself, you'll see that it parsed all of the following modules:

$CmdModules | Select-Object Module

Module
------
C:\Windows\system32\cmd.exe
C:\Windows\SYSTEM32\ntdll.dll
C:\Windows\system32\kernel32.dll
C:\Windows\system32\KERNELBASE.dll
C:\Windows\system32\msvcrt.dll
C:\Windows\system32\WINBRAND.dll
C:\Windows\system32\USER32.dll
C:\Windows\system32\GDI32.dll
C:\Windows\system32\LPK.dll
C:\Windows\system32\USP10.dll
C:\Windows\system32\IMM32.DLL
C:\Windows\system32\MSCTF.dll
C:\Windows\system32\nvinitx.dll
C:\Windows\system32\ADVAPI32.dll
C:\Windows\SYSTEM32\sechost.dll
C:\Windows\system32\RPCRT4.dll
C:\Windows\system32\cmd.exe

Parsing PE headers of cmd.exe loaded modules


Interactively poking around the in memory PE header for kernel32.dll

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.

$EvilHiddenDll = Get-PEHeader -ProcessId 4448 -ModuleBaseAddress 0x02560000
$EvilHiddenDll
$EvilHiddenDll.DOSHeader
$EvilHiddenDll.Exports | Sort-Object -Descending VirtualAddress

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.

Pulling apart meterpreter in memory
metsrv.dll optional and file headers. Note correctly displayed TimeDateStamp (in GMT)


Analyzing PE headers of files on disk

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:

- DOS Header
- File Header
- Optional Header
- Data Directories
- Section Headers
- Imports
- Exports

Should I find the time and motivation in the future, I hope to add the following features:

- Resource parsing
- CLR header parsing
- Resolution of addresses of forwarded functions
- Authenticode signature parsing
- etc.

Let me know what you think and please let me know if you have any questions (please no generic PowerShell questions) or bug reports. Enjoy!