The Return of Aggressor
FortyNorth Security recently posted an article detailing the process for leveraging MSBuild to execute unmanaged PowerShell, and automating it in Aggressor script for Cobalt Strike users. Being a native binary in the Windows OS, the use of MSBuild is a common AWL bypass technique, which is handy in relatively well locked down environments.
I’ve previously blogged about how to combine MSBuild and TikiSpawn to execute a Cobalt Strike agent, circumventing AppLocker and Defender on Windows 10 1903. Inspired by Forty North’s Aggressor implemention I thought it would be fun to knock something similar up to leverage TikiSpawn for lateral movement via MSBuild and WMI, and this will hopefully mark the beginning of more Aggressor for common/popular TikiTorch use cases.
tl;dr - code here.
TikiSpawn & TikiLoader Mods
When executing commands remotely via WMI and WinRM, they are done so as children of the
WMI Provider Host and
Host process for WinRM plug-ins respectively.
LAB\Administrator is logged in interactively and has a session ID of
1, as seen by
explorer.exe and other processes. If WMI or WinRM is used remotely with the same credentials, code exec still occurs in session
This has a number of consequences - the most significant of which for this article is the PPID spoofing within TikiLoader. By default, when TikiSpawn runs it looks for the binary specified as the desired parent, checks to see if that process is within the current Session ID and returns its PID. Of course in this situation, we won’t find a process such as Explorer in session 0 which will cause TikiSpawn to exit.
I did experiment with PPID’ing a process in session 0 to a process in a different session, but it didn’t seem to work so well. So instead, I introduced a new function in TikiLoader to create a new process without attempting to PPID.
This creates a new stripped-down version of TikiSpawn like so:
Passing the binary and encoded shellcode in as arguments will allow us to specify them on-the-fly. This is especially useful when we come to the Aggressor, since we can generate shellcode dynamically depending on which listener we choose.
As with my previous post, I’m working from an XML template that has placeholders for the content we want to shove into it at runtime.
Aggressor has the ability to read in data from a file on disk as an array, then remove/add any index in that array. So in the case of shellcode, we:
- generate it based on the specified listener.
- open and read the content of the XML template.
- remove index 22 (which corressponds to
public const string shellcode = "";).
- add the line back in with our encoded shellcode.
This is an approach I personally prefer over embedding the whole template into the Aggressor script.
The rest of the flow is as simple as generating a random filename, uploading it to the target via a UNC path and executing it with MSBuild.