-
Notifications
You must be signed in to change notification settings - Fork 72
Controlling AMSI Alerts
A major downside of PSAmsi is that we are submitting potentially malicious scripts directly to the AV engine, not exactly "OpsecSafe". While there is no outright solution to this (submitting strings directly to the AV engine is kind of the point!), PSAmsi offers a few ways to control the noise we make.
The PSAmsiScanner class, described more fully [here], has Delay
and AlertLimit
options that help us.
In the New-PSAmsiScanner
cmdlet, the -Delay
flag allows us to specify how long (in seconds) PSAmsi should wait after it submits a string that AMSI reports as malicious (possibly generating an alert). For maximum stealth, this can be set as long as we are willing to wait.
The -AlertLimit
flag specifies a maximum amount of alerts that will be generated during a PSAmsiScanner's execution. Keep in mind that once the AlertLimit has been reached, the PSAmsiScanner will always return False for PSAmsiScans, even if the script would have been flagged by AMSI as malicious.
Some examples of -Delay
and -AlertLimit
:
PS > $Scanner = New-PSAmsiScanner -Delay 20 -AlertLimit 2
PS > Get-PSAmsiScanResult -ScriptString $malware1 -PSAmsiScanner $Scanner
True
PS > $Scanner.AlertCount
1
PS > $Scanner.AlertLimitReached
False
PS > $Scanner.GetPSAmsiScanResult($malware2)
True
PS > $Scanner.AlertCount
2
PS > $Scanner.AlertLimitReached
True
PS > $Scanner.GetPSAmsiScanResult($malware3)
False
PS > Start-PSAmsiClient -ServerUri 'http://example.com/' -Delay 60 -AlertLimit 30
PS > $null = Invoke-PSAmsiScan -ScriptString $malware4 -Delay 60 -AlertLimit 30
Start-PSAmsiClient
and Invoke-PSAmsiScan
accept the -Delay
and -AlertLimit
parameters for convenience, but other functions within PSAmsi accept a PSAmsiScanner object that should be setup with an AlertLimit
and Delay
value ahead of time.
For example:
PS > $Scanner = New-PSAmsiScanner -Delay 5 -AlertLimit 20
PS > $null = Find-AmsiSignatures -ScriptString $Malware -PSAmsiScanner $Scanner
PS > $null = Find-AmsiAstSignatures -ScriptString $Malware -PSAmsiScanner $Scanner
PS > $null = Find-AmsiPSTokenSignatures -ScriptString $Malware -PSAmsiScanner $Scanner
PS > $null = Get-MinimallyObfuscated -ScriptString $Malware -PSAmsiScanner $Scanner
Keep in mind that some functions, such as Find-AmsiSignatures
and Get-MinimallyObfuscated
may delay many times throughout their execution and the total amount of delay time will depend on the script being scanned.
Using the -AlertLimit
parameter with Start-PSAmsiClient
can allow us to spread alerts across hosts. This is useful in the case that you don't want to generate a large amount of alerts on a single host, but think it will be more stealthy to generate some small amount of alerts on multiple hosts. This may be the case if the target environment is not collecting and correlating event logs across the network.
This is accomplished by starting up multiple PSAmsiClients on different targets with an -AlertLimit
argument. Each PSAmsiClient should point at a single PSAmsiServer.
The server will wait for the first client to run out of alloted alerts, the client will report back ALL of it's cached AmsiScan results, and the server will inform the second client of all these cached results. This allows the second client to pick up where the first client left off. This process will continue until all the requested operations are complete or all clients run out of allotted Alerts.
We first start the server by calling Start-PSAmsiServer
: (Verbose output is very helpful when using multiple PSAmsiClients)
PS > $Results = Start-PSAmsiServer -Port 80 -ScriptPath .\Invoke-Mimikatz.ps1 -Verbose
VERBOSE: [Start-PSAmsiServer] HTTP Listener starting on port 80
VERBOSE: [Start-PSAmsiServer] Waiting for request from a client...
We then start several clients on different hosts by calling Start-PSAmsiClient
with an -AlertLimit
on multiple machines:
PS > Start-PSAmsiClient -ServerUri 'http://example.com/' -AlertLimit 5 -GetMinimallyObfuscated
This results in the following output from Start-PSAmsiServer
after the execution of two PSAmsiClients:
PS > $Results = Start-PSAmsiServer -Port 80 -ScriptPath .\Invoke-Mimikatz.ps1 -Verbose
VERBOSE: [Start-PSAmsiServer] HTTP Listener starting on port 80
VERBOSE: [Start-PSAmsiServer] Waiting for request from a client...
VERBOSE: [Start-PSAmsiServer] Servicing GET request from queue.
VERBOSE: [Start-PSAmsiServer] Received POST request from client. Processing data returned.
VERBOSE: [Start-PSAmsiServer] At least one PSAmsiScanRequest has not been completed.
VERBOSE: [Start-PSAmsiServer] Saving 1 PSAmsiScanRequests to send to the next client
VERBOSE: [Start-PSAmsiServer] Waiting for request from a client...
VERBOSE: [Start-PSAmsiServer] Received GET request from client. Adding it t the queue.
VERBOSE: [Start-PSAmsiServer] Servicing GET request from queue.
VERBOSE: [Start-PSAmsiServer] Waiting for request from a client...
VERBOSE: [Start-PSAmsiServer] Received POST request from client. Processing data returned.
VERBOSE: [Start-PSAmsiServer] At least one PSAmsiScanRequest has not been completed.
VERBOSE: [Start-PSAmsiServer] Saving 1 PSAmsiScanRequests to send to the next client
VERBOSE: [Start-PSAmsiServer] Waiting for request from a client...
The PSAmsiServer will continue to run until all of the PSAmsiScanRequests are completed. We can continue to start PSAmsiClients with the -AlertLimit
parameter until execution completes. We can always start a PSAmsiClient without an -AlertLimit
to guarantee execution will complete.