Zero-configuration protection with PowerShell Protect

Protect Security AMSI Endpoint Security

August 31, 2020

Version 1.3 of PowerShell Protect introduces several new, zero-configuration rules to detect, audit and block common exploitation techniques. PowerShell Protect is a configurable antimalware scan interface provider for PowerShell.

Zero-Configuration.

The new version of PowerShell Protect, now automatically enables ten built in rules without having to edit any XML. By default, the rules will write an error to the event log when the issue is detected as well as block the rule using the AMSI provider.

Default Rules

AMSI Bypass Protection

The AMSI bypass protection will be enabled by default. You can learn more about AMSI bypass by reading our previous post.

Module and Script Block Logging Bypass Protection

Module and script block logging was outlined in our blog post last week but is now enabled by default without configuration.

Assembly Load from Memory

One common technique for loading malicious assemblies in a fileless attack is to store the assembly as a base64 encoded string within the script. The System.Reflection.Assembly.Load method will be used to load the byte array directly in memory without accessing the file system. PowerShell Protect will now detect the use of this method and block the script.

Here is a blog post about an AMSI bypass loaded with this method.

An example of this in action from the blog post is listed below.

function Bypass-AMSI
{
    if(-not ([System.Management.Automation.PSTypeName]"Bypass.AMSI").Type) {
        [Reflection.Assembly]::Load([Convert]::FromBase64String("truncated")) | Out-Null
        Write-Output "DLL has been reflected";
    }
    [Bypass.AMSI]::Disable()
}

Disabling Defender

Windows comes with cmdlets for managing the local Windows Defender instance. The Set-MpPreference cmdlet can be used to disable Windows Defender by using the DisableRealtimeMonitoring parameter. Although you will need administrative permissions to perform this action, you will be able to see if users are attempting to execute this command and further investigate the behavior.

An example of the command that is blocked is listed below.

Set-MpPreference -DisableRealtimeMonitoring $true

Use of the System.Reflection.Emit Namespace

One common technique used by fileless attacks is the ability to define .NET assemblies and types in memory. This can be done with the System.Reflection.Emit namespace. Rather than invoking the C# compiler, like with Add-Type, you won’t see any file system activity when this type of attack is taking place. PowerShell Protect will now watch for these types of method calls, audit and block them.

You can see an example of this in PowerSploit’s Invoke-ReflectivePEInjection command for loading binaries into memory without file system access.

This is one way of loading a binary, like Mimikatz, into memory from a script-based payload.

An example of the script that would be blocked.

$Domain = [AppDomain]::CurrentDomain
$DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false)
$ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]

PowerSploit

Windows Defender already blocks a bunch of the PowerSploit commands. You won’t be able to use Invoke-Mimikatz or Invoke-ReflectivePEInjection as-is on a default Windows environment because Defender is checking for these commands. PowerShell Protect now checks for all functions defined in PowerSploit to ensure that no one is poking around your environment with any of the tools.

Marshal Class

The use of the System.RuntimeServices.Interop.Marshal class may be an indication that someone is attempting to manipulate memory within the PowerShell process. This class provides methods for allocating unmanaged memory segments, copying bytes around and determining memory sizes, among other things.

The use of the Marshal class is rare in the C# and the .NET world and should be even more rare in the PowerShell world. Although it may not be an actual attack, it’s a strange thing to be doing for most sysadmins.

An example of the script that would be blocked.

[System.RuntimeServices.Interop.Marshal]::SizeOf($MyVariable)

Persistent WMI Event Subscription

Attackers may use WMI to create a persistent WMI event subscription to run a command during system start up or user logon. This is a difficult attack to detect. It’s also a less common use of PowerShell. We’ve decided to block it by default in PowerShell Protect.

An example of the script that would be blocked.

 $ElevatedTrigger = "`"```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```"root\subscription```" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```"WQL```";Query=```"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325```"};```$Consumer=Set-WmiInstance -Namespace ```"root\subscription```" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```"```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```";RunInteractively='false'};Set-WmiInstance -Namespace ```"root\subscription```" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`""

BloudHound Injestor Execution

BloudHound is an Active Directory tool for enumerating and visualizing relationships in a domain or forest. It uses an injestor, SharpHound, to execute the enumeration of objects and discover their relationships. There are some signs of SharpHound usage that we have identified and blocked to prevent people from executing SharpHound. Other rules, like Assembly Loading for Memory, will also prevent this type of script execution.

An example of the script that would be blocked.

$EncodedCompressedFile = 'truncated'
$DeflatedStream = New-Object IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String($EncodedCompressedFile),[IO.Compression.CompressionMode]::Decompress)
$UncompressedFileBytes = New-Object Byte[](833536)
$DeflatedStream.Read($UncompressedFileBytes, 0, 833536) | Out-Null
$Assembly = [Reflection.Assembly]::Load($UncompressedFileBytes)
$BindingFlags = [Reflection.BindingFlags] "Public,Static"
$a = @()
$Assembly.GetType("Costura.AssemblyLoader", $false).GetMethod("Attach", $BindingFlags).Invoke($Null, @())
$Assembly.GetType("SharpHound3.SharpHound").GetMethod("InvokeSharpHound").Invoke($Null, @(,$passed))

Kerberoasting

Kerberoasting is a lateral movement technique that abuses the Kerberos Ticket Granting Service (TGS). Using tools like Mimikatz, tickets can be dumped from memory, brute forced offline and then used to exfiltrate passwords which can be used to move laterally across an environment.

PowerShell Protect looks for signs of this type of attack being performed based on signatures found in scripts like Invoke-Kerberoasting.ps1.

An example of the script that would be blocked.

elseif ( ($_ -eq 'lastlogon') -or ($_ -eq 'lastlogontimestamp') -or ($_ -eq 'pwdlastset') -or ($_ -eq 'lastlogoff') -or ($_ -eq 'badPasswordTime') ) {
    # convert timestamps
    if ($Properties[$_][0] -is [System.MarshalByRefObject]) {
        # if we have a System.__ComObject
        $Temp = $Properties[$_][0]
        [Int32]$High = $Temp.GetType().InvokeMember('HighPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null)
        [Int32]$Low  = $Temp.GetType().InvokeMember('LowPart',  [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null)
        $ObjectProperties[$_] = ([datetime]::FromFileTime([Int64]("0x{0:x8}{1:x8}" -f $High, $Low)))
    }
    else {
        # otherwise just a string
        $ObjectProperties[$_] = ([datetime]::FromFileTime(($Properties[$_][0])))
    }
}

Auditing

In addition to blocking the activities listed above, PowerShell Protect will also write events to the event log whenever a built-in rule is broken. You can search for the PowerShell Protect source in the application log to see if any of the offending scripts have been run.

Disclaimer

No security solution is a silver bullet. PowerShell Protect adds another layer of security to allow you to detect and block certain behavior that may be malicious. The best security solution is a good understanding of your environment and the right education for the people using it.

These new zero-configuration audit and blocking features should be see as another line of defense.