The PowerShell Capabilities Matrix
I think the offensive usage of PowerShell can be bucketed into the following, non-mutually exclusive categories:
- 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.
- 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.
- 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:
- 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.
- 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.
- Because we’ll be dealing with sensitive data, we need to encrypt the Mimikatz results.
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:
Invoke-Command - for WinRM payload deployment
Invoke-WmiCommand - for WMI payload deployment
Optional communications functionality
In-memory PE loader used to load Mimikatz or any other PE
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:
- 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.
- 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.
- 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.
- Take a list of PowerSploit functions and generate a script that includes all of them with their required dependencies merged
- Generate a script that includes all functions and merged dependencies from a specified submodule – e.g. the Recon submodule which includes PowerView
- Takes a script or scriptblock as input, parses it and prepends any dependencies to a resulting output script
- 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.
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.