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.
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 0
.
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:
public const string shellcode = "";
with public const string shellcode = "THE GENERATED SHELLCODE HERE";
.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 uploading it to the target and executing it with MSBuild. To handle the actual WMI execution, I’m using WMI.exe
from my MiscTools repo.