Showing posts with label malware analysis. Show all posts
Showing posts with label malware analysis. Show all posts

Monday, August 28, 2017

Application of Authenticode Signatures to Unsigned Code

Attackers have been known to apply legitimate digital certificates to their malware, presumably, to evade basic signature validation utilities. This was the case with the Petya ransomware. As a reverse engineer or red team capability developer, it is important to know the methods in which legitimate signatures can be applied to otherwise unsigned, attacker-supplied code. This blog post will give some background on code signing mechanisms, digital signature binary formats, and finally, techniques describing the application of digital certificates to an unsigned PE file. Soon, you will also see why these techniques are even more relevant in research that I will be releasing next month.

Background


What does it mean for a PE file (exe, dll, sys, etc.) to be signed? The simple answer to many is to open up the file properties on a PE and if a “Digital Signatures” tab is present, it means it was signed. When you see that the “Digital Signatures” tab is present on a file, it actually means that the PE file was Authenticode signed, which means within the file itself there is a binary blob of data consisting of a certificate and a signed hash of the file (more specifically, the Authenticode hash which doesn’t consider certain parts of the PE header in the hash calculation). The format in which an Authenticode signature is stored is documented in the PE Authenticode specification.


Many files that one would expect to be signed, however, (for example, consider notepad.exe) do not have a “Digital Signatures” tab. Does this mean that the file isn’t signed and that Microsoft is actually shipping unsigned code? Well, it depends. While notepad.exe does not have an Authenticode signature embedded within itself, in reality, it was signed via another means - catalog signing. Windows contains a catalog store consisting of many catalog files that are basically just a list of Authenticode hashes. Each catalog file is then signed to attest that any files with matching hashes originated from the signer of the catalog file (which is Microsoft in almost all cases). So while the Explorer UI does not attempt to lookup catalog signatures, pretty much any other signature verification tool will perform catalog lookups - e.g. Get-AuthenticodeSignature in PowerShell and Sysinternals Sigcheck.

Note: The catalog file store is located in %windir%\System32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}



In the above screenshot, the SignatureType property indicates that notepad.exe is catalog signed. What is also worth noting is the IsOSBinary property. While the implementation is not documented, this will show “True” if a signature chains to one of several known, hashed Microsoft root certificates. Those interested in learning more about how this works should reverse the CertVerifyCertificateChainPolicy function.

Sigcheck with the “-i” switch will perform catalog certificate validation and also display the catalog file path that contains the matching Authenticode hash. The “-h” switch will also calculate and display the SHA1 and SHA256 Authenticode hashes of the PE file (PESHA1 and PE256, respectively):

sigcheck -q -h -i C:\Windows\System32\notepad.exe
c:\windows\system32\notepad.exe:
  Verified:       Signed
  Catalog:        C:\WINDOWS\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Microsoft-Windows-Client-Features-Package-AutoMerged-shell~31bf3856ad364e35~amd64~~10.0.15063.0.cat
  Signers:
    Microsoft Windows
      Status:         Valid
      Valid Usage:    NT5 Crypto, Code Signing
      Serial Number:  33 00 00 01 06 6E C3 25 C4 31 C9 18 0E 00 00 00 00 01 06
      Thumbprint:     AFDD80C4EBF2F61D3943F18BB566D6AA6F6E5033
      Algorithm:      1.2.840.113549.1.1.11
      Valid from:     1:39 PM 10/11/2016
      Valid to:       1:39 PM 1/11/2018
    Microsoft Windows Production PCA 2011
      Status:         Valid
      Valid Usage:    All
      Serial Number:  61 07 76 56 00 00 00 00 00 08
      Thumbprint:     580A6F4CC4E4B669B9EBDC1B2B3E087B80D0678D
      Algorithm:      1.2.840.113549.1.1.11
      Valid from:     11:41 AM 10/19/2011
      Valid to:       11:51 AM 10/19/2026
    Microsoft Root Certificate Authority 2010
                Status:         Valid
                Valid Usage:    All
                Serial Number:  28 CC 3A 25 BF BA 44 AC 44 9A
                                9B 58 6B 43 39 AA
                Thumbprint:     3B1EFD3A66EA28B16697394703A72CA340A05BD5
                Algorithm:      1.2.840.113549.1.1.11
                Valid from:     2:57 PM 6/23/2010
                Valid to:       3:04 PM 6/23/2035
    Signing date:   1:02 PM 3/18/2017
    Counter Signers:
      Microsoft Time-Stamp Service
        Status:         Valid
        Valid Usage:    Timestamp Signing
        Serial Number:  33 00 00 00 B3 39 BB D4 12 93 15 A9 FE 00 00 00 00 00 B3
        Thumbprint:     BEF9C1F4DA0F153FF0900303BE78A59ADA8ADCB9
        Algorithm:      1.2.840.113549.1.1.11
        Valid from:     10:56 AM 9/7/2016
        Valid to:       10:56 AM 9/7/2018
      Microsoft Time-Stamp PCA 2010
        Status:         Valid
        Valid Usage:    All
        Serial Number:  61 09 81 2A 00 00 00 00 00 02
        Thumbprint:     2AA752FE64C49ABE82913C463529CF10FF2F04EE
        Algorithm:      1.2.840.113549.1.1.11
        Valid from:     2:36 PM 7/1/2010
        Valid to:       2:46 PM 7/1/2025
      Microsoft Root Certificate Authority 2010
        Status:         Valid
        Valid Usage:    All
        Serial Number:  28 CC 3A 25 BF BA 44 AC 44 9A 9B 58 6B 43 39 AA
        Thumbprint:     3B1EFD3A66EA28B16697394703A72CA340A05BD5
        Algorithm:      1.2.840.113549.1.1.11
        Valid from:     2:57 PM 6/23/2010
        Valid to:       3:04 PM 6/23/2035
    Publisher:      Microsoft Windows
    Description:    Notepad
    Product:        Microsoft« Windows« Operating System
    Prod version:   10.0.15063.0
    File version:   10.0.15063.0 (WinBuild.160101.0800)
    MachineType:    64-bit
    MD5:    F60A9D3A9461F68DE0FCCEBB0C6CB31A
    SHA1:   2302BA58181F3C4E1E44A47A7D214EE9397CF2BA
    PESHA1: ACCE8ADCE9DDDE507EAE295DBB37683CA272DB9E
    PE256:  0C67E3923EDA8154A89ADCA8A6BF47DF7C07D40BB41963DEB16ACBCF2E54803E
    SHA256: C84C361B7F5DBAEAC93828E60D2B54704D3E7CA84148BAFDA632F9AD6CDC96FA
    IMP:    645E8D8B0AEA808FF16DAA70D6EE720E

Knowing the Authenticode hash allows you to look up the respective entry in the catalog file. You can double-click a catalog file to view its entries. I also wrote the CatalogTools PowerShell module to parse catalog files. The “hint” metadata field gives away that notepad.exe is indeed the corresponding entry:


Digital Signature Binary Format


Now that you have an understanding of the methods in which a PE file can be signed (Authenticode and catalog), it is useful to have some background on the binary format of signatures. Whether Authenticode signed or catalog signed, both signatures are stored as PKCS #7 signed data which is ASN.1 formatted binary data. ASN.1 is simply a standard that states how binary data of different data types should be stored. Before observing/parsing the bytes of a digital signature, you must first know how it is stored in the file. Catalog files are straightforward as the file itself consists of raw PKCS #7 data. There are online ASN.1 decoders that parse out ASN.1 data and present it in an intuitive fashion. For example, try loading the catalog file containing the hash for notepad.exe into the decoder and you will get a sense of the layout of the data. Here’s a snippet of the parsed output:


Each property within the ASN.1 encoded data begins with an object identifier (OID) - a unique numeric sequence that identifies the type of data that follows. The OIDs worth noting in the above snippet are the following:
  1. 1.2.840.113549.1.7.2 - This indicates that what follows is PKCS #7 signed data - the format expected for Authenticode and catalog-signed code.
  2. 1.3.6.1.4.1.311.12.1.1 - This indicates that what follows is catalog file hash data
It is worth spending time exploring all of the fields contained within a digital signature. All fields present are outside of the scope of this blog post, however. Additional crypto/signature-related OIDs are listed here.

Embedded PE Authenticode Signature Retrieval


The digital signature data in a PE file with an embedded Authenticode signature is appended to the end of the file (in a well-formatted PE file). The OS obviously needs a little bit more information than that though in order to retrieve the exact offset and size of the embedded signature. Let’s look at kernel32.dll in one of my favorite PE parsing/editing utilities: CFF Explorer.


The offset and size of the embedded digital signature is stored in the “security directory” offset within the “data directories” array within the optional header. The data directory contains offsets and size of various structures within the PE file - exports, imports, relocations, etc. All offsets within the data directory are relative virtual offsets (RVA) meaning they are the offset to the respective portion of the PE when loaded in memory. There is one exception though - the security directory which stores its offset as a file offset. The reason for this is because the Windows loader doesn’t actually load the content of the security directory in memory.

The binary data in the at the security directory file offset is a WIN_CERTIFICATE structure. Here’s what the structure for kernel32.dll looks like parsed out in 010 Editor (file offset 0x000A9600):


PE Authenticode signatures should always have a wRevision of WIN_CERT_TYPE_PKCS_SIGNED_DATA. The byte array that follows is the same PKCS #7, ASN.1 encoded signed data as was seen in the contents of a catalog file. The only difference is that you shouldn’t find the 1.3.6.1.4.1.311.12.1.1 OID, indicating the presence of catalog hashes.

Parsing out the raw bCertificate data in the online ASN.1 decoder confirms we’re dealing with proper PKCS #7 data:

Application of Digital Signatures to Unsigned PEs


Now that you have a basic idea of the binary format and storage locations of digital signatures, you can start applying existing signatures to your unsigned code.

Application of Embedded Authenticode Signatures


Applying an embedded Authenticode signature from a signed file to an unsigned PE file is quite straightforward. While the process can obviously be automated, I’m going to explain how to do it manually with a hex editor and CFF Explorer.

Step #1: Identify the Authenticode signature that you want to steal. In this example, I will use the one in kernel32.dll

Step #2: Identify the offset and size of the WIN_CERTIFICATE structure in the “security directory”


So the file offset in the above screenshot is 0x000A9600 and the size is 0x00003A68.

Step #3: Open kernel32.dll in a hex editor, select 0x3A68 bytes starting at offset 0xA9600, and then copy the bytes.


Step #4: Open your unsigned PE (HelloWorld.exe in this example) in a hex editor, scroll to the end, and paste the bytes copied from kernel32.dll. Take note of the file offset of the beginning of the signature (0x00000E00 in my case). Save the file after pasting in the signature.


Step #5: Open HelloWorld.exe in CFF Explorer and update the security directory to point to the digital signature that was applied: offset - 0x00000E00, size - 0x00003A68. Save the file after making the modifications. Ignore the “Invalid” warning. CFF Explorer doesn’t treat the security directory as a file offset and gets confused when it tries to reference what section the data resides in.


That’s it! Now, signature validation utilities will parse and display the signature properly. The only caveat is that they will report that the signature is invalid because the calculated Authenticode of the file does not match that of the signed hash stored in the certificate.

Now, if you were wondering why the SignerCertificate thumbprint values don’t match, then you are an astute reader. Considering we applied the identical signature, why doesn’t the certificate thumbprint match? That’s because Get-AuthenticodeSignature first attempts a catalog file lookup of kernel32.dll. In this case, it found a catalog entry for kernel32.dll and is displaying the signature information for the signer of the catalog file. kernel32.dll is also Authenticode signed though. To validate that the thumbprint values for the Authenticode hashes are identical, temporarily stop the CryptSvc service - the service responsible for performing catalog hash lookups. Now you will see that the thumbprint values match. This indicates that the catalog hash was signed with a different code signing certificate from the certificate used to sign kernel32.dll itself.

Application of a Catalog Signature to a PE File


Realistically, CryptSvc will always be running and catalog lookups will be performed. Suppose you want to be mindful of OPSEC and match the identical certificate used to sign your target binary. It turns out, you can actually apply the contents of a catalog file to an embedded PE signature by swapping out the contents of bCertificate in the WIN_CERTIFICATE structure and updating dwLength accordingly. Feel free to follow along as this is done. Note that our goal (in this case) is to apply an Authenticode signature to our unsigned binary that is identical to the one used to sign the containing catalog file: Certificate thumbprint AFDD80C4EBF2F61D3943F18BB566D6AA6F6E5033 in this case.

Step #1: Identify the catalog file containing the Authenticode hash of the target binary - kernel32.dll in this case. If a file is Authenticode signed, sigcheck will actually fail to resolve the catalog file. Signtool (included in the Windows SDK) will, however.


Step #2: Open the catalog file in in a hex editor and annotate the file size - 0x000137C7


Step #3: We’re going to manually craft a WIN_CERTIFICATE structure in a hex editor. Let’s go through each field we’ll supply:
  1. dwLength: This is the total length of the WIN_CERTIFICATE structure - i.e. bCertificate bytes plus the size of the other fields = 4 (size of DWORD) + 2 (size of WORD) + 2 (size of WORD) + 0x000137C7 (bCertificate - the file size of the .cat file) = 0x000137CF.
  2. wRevision: This will be 0x0200 to indicate WIN_CERT_REVISION_2_0.
  3. wCertificateType: This will be 0x0002 to indicate WIN_CERT_TYPE_PKCS_SIGNED_DATA.
  4. bCertificate: This will consist of the raw bytes of the catalog file.
When crafting the bytes in the hex editor, be mindful that the fields are stored in little-endian format.


Step #4: Copy all the bytes from the crafted WIN_CERTIFICATE, append them your unsigned PE, and update the security directory offset and size accordingly.


Now, assuming your calculations and alignments were proper, behold a thumbprint match with that of the catalog file!


Anomaly Detection Ideas


The techniques presented in this blog post have hopefully got some people thinking about how one might go about detecting the abuse of digital signatures. While I have not investigated signature heuristics thoroughly, let me just pose a series of questions that might motivate others to start investigating and writing detections for potential signature anomalies:
  • For a legitimately signed Microsoft PE, is there any correlation between the PE timestamp and the certificate validity period? Would the PE timestamp for attacker-supplied code deviate from the aforementioned correlation?
  • After reading this article, what is your level of trust in a “signed” file that has a hash mismatch?
  • How would you go about detecting a PE file that has an embedded Authenticode signature consisting of a catalog file? Hint: A specific OID mentioned earlier might be useful.
  • How might you go about validating the signature of a catalog-signed file on a different system?
  • What effect might a stopped/disabled CryptSvc service have on security products performing local signature validation? If that was to occur, then most system files, for all intents and purposes will cease to be signed.
  • Every legitimate PE I’ve seen is padded on a 0x10 byte boundary. The example I showed where I applied the catalog contents to an Authenticode signature is not 0x10 byte aligned.
  • How might you differentiate between a legitimate Microsoft digital signature and one where all the certificate attributes are applied to a self-signed certificate?
  • What if there is data appended beyond the digital signature? This has been abused in the past.
  • Threat intel professionals should find the Authenticode hash to be an interesting data point when investigating identical code with different certificates applied. VirusTotal supplies this as the "Authentihash" value: i.e. the hash value that was calculated with "sigcheck -h". If I were investigating variants of a sample that had more than one hit on a single Authentihash in VirusTotal, I would find that to be very interesting.

Saturday, April 5, 2014

Analyzing the "Power Worm" PowerShell-based Malware

On March 27, 2014, Trend Micro revealed the so called “Power Worm” PowerShell-based malware that is actively being used in the wild. With so few publicly reported instances of PowerShell malware in existence, I was excited to get my hands on this most recent strain of PowerShell-based malware. Unable to track it down on my own, I reached out to the security and PowerShell communities. It was with great relief that my friend Lee Holmes – PowerShell developer extraordinaire and author of the Windows PowerShell Cookbook kindly provided me with all of the samples described in the Trend Micro post.

While the Trend Micro post was thorough in its coverage of the broader capabilities of the malware, they did not provide an analysis of its implementation which, as a PowerShell enthusiast and malware analyst, I was very interested in. That said, what follows is my analysis of the mechanics of the Office document infecting malware. Since there were multiple payloads associated with “Power Worm.” I decided to focus on the X97M_CRIGENT.A payload – a malicious Excel spreadsheet.

The targeted Excel macro used in the "Power Worm" campaign

The spreadsheet contains the following macro:

Private Sub Workbook_Open()
b = "JwBDAEkREDACTEDREDACTED" _
& "QA7ACcAcgREDACTEDREDACTED" _
& "BzACgAKQAREDACTEDREDACTED" _
& "jAGUAIAAtREDACTEDREDACTED" _
& "ACAAUwB5AREDACTEDREDACTED" _
& "GcALgBpAGREDACTEDREDACTED" _
& "4AIAAtAGEREDACTEDREDACTED" _
& "AdAAuAHAAREDACTEDREDACTED"
Set a = CreateObject("WScript.Shell")
a.Run "powershell.exe" & " -noexit -encodedcommand " & b, 0, False
End Sub

People have asked, “Wouldn’t the PowerShell execution policy potentially mitigate this attack?” No. First of all, the execution policy should not be viewed as a security mitigation considering PowerShell itself provides the mechanism to bypass it. Second, the execution policy is not honored when a Base64 encoded command is provided to the ‘-EncodedCommand’ parameter. Malware authors know this and will never run into a situation where the execution policy is the reason their malicious PowerShell code was prevented from executing. Having macros disabled by default prevents the initial infection, but all it takes is a naïve victim to click a single button to enable macros.

The ‘Workbook_Open’ function will execute automatically upon opening an Excel spreadsheet (assuming macros are allowed to execute). After decoding the Base64-encoded PowerShell command, you will be presented with an obfuscated mess consisting of the following:

  1. The payload is a single line of semicolon delimited PowerShell commands.
  2. Junk strings that have no impact on the script are inserted between each command.
  3. All variables and function names are randomly generated and have no logical meaning.
  4. Lastly, some functions used in the script are not implemented until a subsequent payload is downloaded from the command and control (C2) server.

I rewrote all of the “Power Worm” malware (redacting key portions) that I was able to obtain so that those interested don’t have to be bogged down with difficult to understand obfuscated code. I also created a PowerWorm GitHub repo where you will find the following code:

  1. The rewritten X97M_CRIGENT.A PowerShell payloads (5 parts in total)
  2. Test-PowerWormInfection – Detects and removes a “Power Worm” infection
  3. Get-ExcelMacro – Outputs and removes Excel spreadsheet macros
  4. Get-WordMacro – Outputs and removes Word document macros

As soon as the macro executes and launches PowerShell, the following code is executed:


  1. Suppress error messages.
  2. Obtain the machine GUID with WMI. This unique value specific to your system is used throughout the malware as a directory name to store downloaded files, registry key names where additional payload are persisted, and as a unique identifier for the C2 server.
  3. Next, If the malware is already persistent in the registry, don’t bother running the payload again. It will execute again at next reboot.
  4. Define a function to resolve DNS TXT records and download and decompress a zip file located at the URI in the resolved TXT record. Both Tor and Polipo are downloaded via this function.
  5. Mark the downloaded file directory as hidden.

The next portion of the payload executes tor and polipo, a requirement for communicating with the C2 server and downloads and executes the next stage of the attack:


For those unfamiliar with common malware techniques, what should be worrisome about the fact that additional PowerShell code is downloaded and executed is that the malware authors have complete control over the downloaded content. The analysis that follows describes the instance of the malware that I downloaded. The malware authors could very well change the payload at any time.

The downloaded payload starts by persisting three additional Base64-encoded payloads to the registry.


The Trend Micro article neglected to mention the two payloads saved in the registry at the following locations:

HKCU:\Software\Microsoft -> {Machine GUID}0
HKCU:\Software\Microsoft -> {Machine GUID}1

$EncodedPayload1 and $EncodedPayload2 are essentially equivalent to the initial payload included in the Excel macro – they serve to reinfect the system and download/execute any additional payloads. $EncodedPayload3 contains all the logic to infect Office documents.

The malware then collects information about the compromised system and uploads it to the C2 server. 


Finally, the Office document infection functions are called and if an additional payload is available, it is executed. I was unable to retrieve the additional payload during my analysis.


The Office document infection payload implements the following functions:

  1. Start-NewDriveInfection – Registers a WMI event that detects when a new drive is added (e.g. USB thumb drive) and infects all Office documents present on the drive
  2. Invoke-OfficeDocInfection – Infects all Office documents on the drive letter specified
  3. Start-ExistingDriveInfection – Registers a FileSystemWatcher event to detect and infect newly created Office documents
  4. Set-OfficeDocPayload – Adds a macro to the specified Office document
  5. New-MaliciousMacroPayload – Generates a macro based upon one of the payloads present in the registry
  6. Set-ExcelDocumentMacroPayload – Infects an Excel spreadsheet
  7. Set-WordDocumentMacroPayload – Infects a Word document

In order to programmatically create/modify/remove Excel and Word macros, macro security must be disabled in the registry with these commands:

Set-ItemProperty HKCU:\Software\Microsoft\Office\*\*\Security -Name AccessVBOM -Type DWORD -Value 1
Set-ItemProperty HKCU:\Software\Microsoft\Office\*\*\Security -Name VBAWarnings -Type DWORD -Value 1 

After the registry values are set, you will no longer be prompted to enable macros. They will execute automatically without your knowledge. Also, be mindful that if a macro is present in an Office document and you attempt to analyze it with the Word.Application and Excel.Application COM objects, the macro security settings are not honored and the macro will execute without your permission. Before opening an Office document with the COM objects, you must explicitly disallow the execution of macros by setting the ‘AutomationSecurity’ property to ‘msoAutomationSecurityForceDisable’.

The Word document infector is implemented as follows:


What’s interesting is that once the macro is written to the Word document, it is downgraded to a ‘macro-enabled’ .doc file.

Once a document or spreadsheet is infected, it will download and execute another PowerShell payload. I was unable to successfully download any additional payloads during my analysis. Either I was not emulating C2 communication properly or the payload was not made available at the time.

So in the end, I was rather impressed by the effectiveness of which the PowerShell payloads infected Office documents. It has yet to be seen though the true power of this malware until additional malicious payloads can be downloaded from the C2 server.

Should you become the victim of a “Power Worm” infection or any malicious Office document for that matter, I’ve provided tools to detect and remove “Power Worm” and Word/Excel macros. You can download these tools from my Github repo.

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!