Background (What is AMSI?)
Over the last decade, powershell has proven to be a very accessible vector for pentesters and hackers alike to run malicious code in memory without writing to disk. This provided some stealth at first when used against many poorly built antivirus solutions, but things eventually changed a bit. Microsoft released a scan interface called AMSI that allows any antivirus installed on the system to monitor and block powershell scripts in memory. Below is an image of how a default Windows 10 installation blocks BloodHound’s powershell ingestor in memory:
How do we bypass it?
With an “AMSI Bypass” of course! Googling this will provide some decent results, and you may even come across amsi.fail, a website by @Flangvik that will automatically generate bypasses for you. These bypasses are designed to disable AMSI in the powershell process they are run in. This allows an attacker to then load and execute their malicious scripts without needing to worry about detection by AMSI. Seems SUPER easy! Let’s see what happens when we try to run one of the AMSI bypasses generated by amsi.fail:
Ah man, that almost worked. A few months ago it actually did work! However, we can see from the screenshot that our AMSI bypass was detected by AMSI itself. This happened because the bypass we got from amsi.fail is relatively old now and Microsoft has already created a signature for it. It seems like we actually might have to do some work ourselves. ;)
As you might have noticed from the screenshot, all of the bypasses from amsi.fail are obfuscated in order defeat AMSI’s signature based detection. IMO, this is the best way to create working AMSI bypasses. However, manual obfuscation can be pretty time consuming, and bypasses can get detected over time as demonstrated previously. Sure, coming up with an automated way of obfuscating bypasses would work too, but we’re trying to do this with ZERO effort!
HELP!!! I DON’T WANT TO WORK!
No worries! There’s an easier way to execute AMSI bypasses without the need for any obfuscation. Let’s try taking the same AMSI Bypass we tried before, but this time we’re going to simply copy and paste it directly into a powershell terminal:
WOAH! That worked! And we were able to download and execute BloodHound’s ingestor from memory right after! The reason for this is simple: AMSI can’t detect our bypass with a signature if we run it line-by-line. Every time powershell is invoked to execute a command/script, AMSI is called to see if it’s is malicious. By running the script line-by-line, we are effectively splitting the bypass into 14 different scripts, none of which AMSI has a signature for.
I have tested this with multiple bypasses and scripts with good success. I’ve found the best AMSI bypass to use with this method (and in general) is the AmsiScanBuffer patch created by rasta-mouse. It can be executed using this method with no need for ANY obfuscation.
So that’s it? It’s really that easy?
Yep. Pretty much. The flaw is simple and so is the concept: split a detected script into multiple blocks that are executed in order to prevent it from being detected. The only limitation perhaps is that it takes an interactive session to be able to copy and paste a powershell script line-by-line. This is fine for many pentesting scenarios, but becomes an issue if we were trying execute commands in a non-interactive setting, such as exploiting a RCE vulnerability in a web application. For cases like that, a new tool was developed:
Bl1ng bl1ng, new tool drop!
Meet PowerChunker, a tool designed to automate the process described in this post for use in non-interactive environments. PowerChunker will take a given powershell script, split it up line-by-line, and create a stager that will download and execute each line in order. This allows the attacker to bypass AMSI using the method outlined in this post, all by invoking one single ps1 file.
I hope you enjoyed reading, and check back for more hacking related content!