# Windows Client-Side Attacks(Windows 客户端 / 桌面端攻击与分析)
# 1_Using Macros (VBA 宏钓鱼攻击)
# 1.1 攻击背景与原理
VBA(Visual Basic for Applications)宏是 Office 文档(如 Word、Excel)中用于自动化任务的脚本语言。攻击者常利用宏进行客户端攻击(Client-Side Attacks),特别是结合钓鱼邮件(Phishing)。
- 攻击载体:包含恶意宏的 Office 文档(如伪装成简历的
.doc或.docm文件),通过邮件附件(如.msg格式)发送。 - 触发条件:受害者打开文档 -> 点击 “启用编辑” -> 点击 “启用内容(宏)”。
- Payload 执行:宏代码被触发后,通常会释放(Drop)第二阶段的 Payload(如 PowerShell 脚本),或直接通过内存执行(Fileless),最终建立反弹 Shell。
# 1.2 攻击载荷执行流程
以样本 Phishing_Email_Resume.msg 为例,典型的宏攻击执行链如下:
- 用户交互:受害者打开 Word 文档并启用宏。
- 宏执行:VBA 宏代码运行,调用
Shell()或WScript.Shell执行 PowerShell。 - Payload 释放 / 执行:PowerShell 下载并执行恶意的
.ps1脚本,或直接在内存中执行混淆的 Base64 编码命令。 - 建立连接:Payload 执行后,向攻击者的 C2(命令与控制)服务器发起网络连接,获取交互式 Shell。
# 1.3 基于 Sysmon 的完整溯源分析 (Event Chaining)
在应急响应中,通过 Sysmon 日志可以完美还原上述无文件 / 少文件攻击的完整生命周期。以下是标准的溯源步骤:
# 步骤 1:发现初始异常进程 (Event ID 1)
首先,在安全告警或系统异常时间点,发现 powershell.exe 被创建。
- 分析点:查看该进程的
ParentImage(父进程)。如果父进程是WINWORD.EXE(Word),则高度怀疑是宏攻击。
Get-SysmonEvent -EventId 1 -Start "..." -End "..." | | |
Where-Object { $_.Properties[4].Value -match "powershell.exe" -and $_.Properties[20].Value -match "WINWORD.EXE" } | | |
Format-List TimeCreated, @{Label="PID";Expression={$_.Properties[3].Value}}, @{Label="ParentImage";Expression={$_.Properties[20].Value}}, @{Label="CommandLine";Expression={$_.Properties[10].Value}} |
# 步骤 2:追踪文件落地 (Event ID 11)
通过上一步获取的 PowerShell 进程的 PID 和时间戳,查询该进程是否创建了临时文件(如释放的 .ps1 脚本)。
- 分析点:
Image为powershell.exe,TargetFilename指向临时目录(如C:\Users\Public\或AppData\Local\Temp\)下的.ps1文件。
Get-SysmonEvent -EventId 11 -Start "..." -End "..." | | |
Where-Object { $_.Properties[3].Value -eq $PowerShellPID -and $_.Properties[5].Value -match "\.ps1$" } | | |
Format-List TimeCreated, @{Label="TargetFile";Expression={$_.Properties[5].Value}} |
# 步骤 3:追踪脚本执行与派生 (Event ID 1)
扩大时间窗口,查找该 .ps1 文件被执行后,派生出的新进程(如 nc.exe , rundll32.exe , 或再次调用 powershell.exe )。
- 分析点:此时
ParentImage将是powershell.exe,CommandLine会暴露真实的恶意载荷或 C2 域名。
# 步骤 4:DNS 解析追踪 (Event ID 22)
如果 Payload 中使用了域名(而非直接 IP)连接 C2,Sysmon 的 DNS 查询日志(Event ID 22)是极佳的追踪点。
- 分析点:查找由恶意进程(PID 匹配)发起的 DNS 查询,获取解析后的 C2 IP 地址。
Get-SysmonEvent -EventId 22 -Start "..." -End "..." | | |
Where-Object { $_.Properties[3].Value -eq $MaliciousPID } | | |
Format-List TimeCreated, @{Label="QueryName";Expression={$_.Properties[5].Value}}, @{Label="QueryResults";Expression={$_.Properties[6].Value}} |
# 步骤 5:网络外联确认 (Event ID 3)
最后,使用上一步获取的 C2 IP 地址,查询网络连接日志(Event ID 3),确认反弹 Shell 是否成功建立。
- 分析点:
Image为恶意进程,DestinationIp为 C2 IP,DestinationPort为监听端口(如 443, 4444)。这标志着攻击链的闭环。
Get-SysmonEvent -EventId 3 -Start "..." -End "..." | | |
Where-Object { $_.Properties[14].Value -eq $C2_IP_Address } | | |
Format-List TimeCreated, @{Label="Image";Expression={$_.Properties[4].Value}}, @{Label="DestinationIP";Expression={$_.Properties[14].Value}}, @{Label="DestinationPort";Expression={$_.Properties[16].Value}} |
# 1.4 防御与缓解建议
- 组策略限制:通过 GPO 阻止 Office 宏从 Internet 区域下载的文档中运行(Attack Surface Reduction 规则)。
- AMSI 集成:确保 Windows Defender 的 AMSI(反恶意软件扫描接口)已启用,可拦截内存中执行的恶意宏和 PowerShell 脚本。
- 用户意识培训:教育员工不要随意启用来自未知发件人的 Office 文档宏。
- 禁用旧版宏:在较新的 Office 版本中,默认阻止来自 Internet 的文档运行 VBA 宏。
# 2_Introduction to PowerShell Logging
# 2.1 基础概念与配置路径
PowerShell 是红队行动和高级持续性威胁 (APT) 中最常用的攻击向量之一。为了有效监控、检测和取证,必须启用 PowerShell 的原生日志记录功能。这些配置可以通过本地组策略编辑器 ( gpedit.msc ) 或域组策略 (GPO) 进行集中管理。
组策略配置路径:Computer Configuration -> Administrative Templates -> Windows Components -> Windows PowerShell
(计算机配置 -> 管理模板 -> Windows 组件 -> Windows PowerShell)
# 2.2 模块日志 (Module Logging)
功能:记录 PowerShell 管道执行时调用的特定模块和 Cmdlet 的详细信息。
记录内容:当启用此功能后,系统会记录执行的 Cmdlet 名称、参数以及所在的模块名称(如 Microsoft.PowerShell.Management )。
安全价值:
- 帮助分析师了解攻击者使用了哪些内置功能或第三方模块(如
Invoke-Mimikatz,Get-Process)。 - 局限性:如果攻击者使用高度混淆的脚本或直接在命令行中执行未封装为模块的碎片化代码,模块日志可能无法捕获完整的恶意意图。
事件 ID:4103(记录在Microsoft-Windows-PowerShell/Operational日志中)。
# 2.3 脚本块日志 (Script Block Logging)
功能:记录 PowerShell 脚本执行时的完整内容,包括所有解混淆(Deobfuscation)后的最终代码。
记录内容:无论脚本是通过文件执行、内存注入(如 IEX )、还是 Base64 编码传入,脚本块日志都会捕获 PowerShell 引擎最终解析并执行的明文代码。
安全价值:
- 对抗混淆的终极武器:攻击者常使用字符串拼接、变量替换或 Base64 来绕过静态检测。脚本块日志能直接展示解密后的真实 Payload,让混淆彻底失效。
- 是分析无文件攻击 (Fileless Attacks) 和内存注入的核心日志。
事件 ID: 4104:创建脚本块(开始执行)。4105:脚本块命令执行中。4106:脚本块执行完成。
# 2.4 转录 / 会话记录 (Transcription)
功能:记录 PowerShell 会话期间的所有输入和输出,类似于传统的命令行历史记录,但更加详尽且结构化。
记录内容:捕获用户在 PowerShell 控制台中键入的每一个命令,以及系统返回的所有标准输出和错误信息。日志通常以 .txt 格式保存在 %USERPROFILE%\Documents 或管理员指定的网络共享路径中。
安全价值:
- 完整还原攻击者视角:提供攻击者在交互式 Shell 中的完整操作上下文,包括他们看到了什么、执行了什么、以及命令的执行结果。
- 对于事后取证、重建攻击时间线和评估数据泄露范围具有不可替代的价值。
配置注意:需要在组策略中启用并指定一个输出目录(OutputDirectory),且该目录需要对写入账户(如SYSTEM或当前用户)具有写权限。
# 2.5 日志协同分析策略
在高级威胁狩猎中,这三种日志应结合使用以形成完整的证据链:
- Script Block Logging (4104):用于发现 “是什么恶意代码被解密并执行了”(获取完整 Payload)。
- Module Logging (4103):用于追踪 “该代码调用了哪些系统级 API 或敏感 Cmdlet”(分析攻击手法)。
- Transcription:用于还原 “攻击者在获得 Shell 后,手动输入了哪些命令并得到了什么反馈”(重建攻击者意图)。
# 3_PowerShell Module Logging
# 3.1 启用与配置模块日志
PowerShell 模块日志(Module Logging)用于记录 PowerShell 管道执行时调用的特定模块和 Cmdlet 的详细信息。
配置路径:
在组策略编辑器 ( gpedit.msc ) 或域组策略 (GPO) 中定位到:Computer Configuration -> Administrative Templates -> Windows Components -> Windows PowerShell
关键设置:
- Turn on Module Logging:将其设置为
Enabled(已启用)。 - Show contents of modules(模块名称列表):在此处输入需要记录的模块名称。
- 技巧:输入通配符
*可以记录所有 PowerShell 模块的活动,确保无死角监控。
- 技巧:输入通配符
# 3.2 日志噪音与清理策略
副作用(日志噪音):
启用模块日志后,使用 PowerShell 本身来查询日志的操作(如执行 Get-WinEvent )也会被记录为模块日志。这会在日志中产生大量与调查相关的 “噪音”,干扰对真实攻击行为的分析。
清理与恢复:
在渗透测试或红队演练中,为了清理痕迹或重置环境,通常会编写 .bat 批处理脚本,利用 wevtutil cl 命令清理相关日志通道。
注意:清理日志后,当前 PowerShell 会话中导入的自定义模块(如之前编写的 Sysmon 查询模块)可能会失效,需要重新执行 Import-Module 导入。
# 3.3 实战示例:触发与查询模块日志
1. 触发模块日志
在目标机器上执行以下命令,调用 WMI 模块获取进程信息并输出当前时间:
Get-WmiObject -Class Win32_Process | Select-Object Name, ParentProcessId; Write-Host (Get-Date) |
2. 查询模块日志 (Event ID 4103)
模块日志记录在 Microsoft-Windows-PowerShell/Operational 通道中,事件 ID 为 4103。使用 Get-WinEvent 结合哈希表进行精准查询:
Get-WinEvent -FilterHashtable @{ | |
LogName = 'Microsoft-Windows-PowerShell/Operational' | |
StartTime = '2/4/2022 14:35:11' | |
EndTime = '2/4/2022 14:35:13' | |
Id = 4103 | |
} |
3. 分析日志详细信息
使用 Format-List 展开日志的完整内容,以获取更深层次的上下文:
Get-WinEvent -FilterHashtable @{ | |
LogName = 'Microsoft-Windows-PowerShell/Operational' | |
StartTime = '2/4/2022 14:35:11' | |
EndTime = '2/4/2022 14:35:13' | |
Id = 4103 | |
} | Format-List TimeCreated, Id, LevelDisplayName, Message |
日志分析要点:
在 Message 字段(XML 视图中的 <EventData> )中,可以提取以下关键信息:
- ContextInfo(上下文信息):包含执行命令的用户名、主机名、进程 ID (PID) 以及 PowerShell 主机版本。
- Severity(严重性):通常为
Information(信息),表示命令成功执行。 - Payload / Command(执行内容):清晰记录了实际执行的 Cmdlet 及其参数(如
Get-WmiObject -Class Win32_Process)。 - Sequence Number(序号):用于对同一会话中的多个模块调用进行排序,还原执行顺序。
# 4_PowerShell Script Block Logging
# 4.1 基础概念与配置
脚本块日志(Script Block Logging)是 PowerShell 最强大的防御和取证功能之一。它能够在 PowerShell 引擎执行代码之前,记录脚本块的完整明文内容,无论这些代码是如何被传入或混淆的。
配置路径:
在本地组策略 ( gpedit.msc ) 或域组策略 (GPO) 中定位到:Computer Configuration -> Administrative Templates -> Windows Components -> Windows PowerShell -> Turn on PowerShell Script Block Logging,将其设置为 Enabled 。
注意:启用此策略后,通常需要重启 PowerShell 会话(或重启计算机)才能使配置生效。
# 4.2 基础测试:明文脚本块记录
执行简单的脚本块,并查询生成的 Event ID 4104(脚本块创建事件)。
1. 触发日志
{ "This is a script block" }; Write-Host (Get-Date) |
2. 查询日志
Get-WinEvent -FilterHashtable @{ | |
LogName = 'Microsoft-Windows-PowerShell/Operational' | |
StartTime = '2/7/2022 12:19:13' | |
EndTime = '2/7/2022 12:19:15' | |
Id = 4104 | |
} | Format-List TimeCreated, Message |
分析:在 Message 字段中,可以清晰地看到完整的脚本执行内容和上下文信息。
# 4.3 核心实战:对抗 Base64 编码 (EncodedCommand)
攻击者经常使用 -EncodedCommand 参数将恶意命令进行 Unicode 编码并转换为 Base64 字符串,以绕过基于命令行的静态安全检测(如 AV 签名或简单的正则匹配)。
1. 生成 Base64 编码载荷
# 定义原始恶意命令(此处以获取时间和系统补丁为例) | |
$Command = 'Write-Host (Get-Date); Get-Hotfix' | |
# 将命令转换为 Unicode 字节数组 | |
$Bytes = [System.Text.Encoding]::Unicode.GetBytes($Command) | |
# 将字节数组转换为 Base64 字符串 | |
$EncodedCommand = [Convert]::ToBase64String($Bytes) | |
# 查看生成的 Base64 字符串 | |
$EncodedCommand | |
# 输出: VwByAGkAdABlAC0ASABvAHMAdAAgACgARwBlAHQALQBEAGEAdABlACkAOwAgAEcAZQB0AC0ASABvAHQAZgBpAHgA |
2. 执行编码后的命令
powershell -EncodedCommand VwByAGkAdABlAC0ASABvAHMAdAAgACgARwBlAHQALQBEAGEAdABlACkAOwAgAEcAZQB0AC0ASABvAHQAZgBpAHgA |
3. 查询日志验证 "解码" 效果
再次查询同一时间段的 4104 事件:
Get-WinEvent -FilterHashtable @{ | |
LogName = 'Microsoft-Windows-PowerShell/Operational' | |
StartTime = '2/7/2022 12:22:50' | |
EndTime = '2/7/2022 12:22:52' | |
Id = 4104 | |
} | Format-List TimeCreated, Message |
关键发现:
查看日志的 Message (或 XML 视图中的 ScriptBlockText ),会发现记录的不是那串长长的 Base64 字符,而是解码后的原始明文:
Write-Host (Get-Date); Get-Hotfix
# 4.4 安全价值总结
Script Block Logging 是对抗 PowerShell 混淆和编码的终极武器。
- 让混淆失效:无论攻击者使用 Base64 编码、字符串拼接、变量替换还是其他复杂的混淆技术,只要代码最终需要被 PowerShell 引擎解析执行,Script Block Logging 就会在解码后、执行前的节点,将其还原为最原始的明文并记录下来。
- 无文件攻击取证:对于通过
IEX(Invoke-Expression) 或内存注入执行的无文件恶意脚本,这是获取完整 Payload 的唯一可靠途径。
# 5_PowerShell Transcription
# 5.1 基础概念与配置
PowerShell 转录(Transcription)功能用于记录 PowerShell 会话期间的所有输入命令和系统输出结果。它相当于一个极其详尽的 “命令行历史记录”,是事后取证和重建攻击者操作时间线的核心工具。
配置路径:
在本地组策略 ( gpedit.msc ) 或域组策略 (GPO) 中定位到:Computer Configuration -> Administrative Templates -> Windows Components -> Windows PowerShell -> Turn on PowerShell Transcription,将其设置为 Enabled 。
关键配置选项:Include invocation headers(包含调用标头)
- 作用:强烈建议勾选此项。启用后,转录文件中的每一次命令执行都会自动附带详细的元数据标头。
- 标头内容:包含精确的时间戳(Time)、执行命令的用户名(User)、主机名(Host)、PowerShell 版本以及进程 ID (PID)。
- 安全价值:没有时间戳的日志在取证时是灾难。此选项确保了即使多个会话并发或日志被合并,分析师也能精确还原命令的执行顺序和上下文。
# 5.2 默认存储路径
如果在组策略中没有强制指定一个集中的网络共享路径(Output Directory),PowerShell 会将转录文件( .txt 格式)默认保存在当前执行用户的 Documents(文档) 目录下。
- 普通用户:
C:\Users\<Username>\Documents\ - SYSTEM 账户:
C:\Windows\System32\config\systemprofile\Documents\ - 文件命名规则:
PowerShell_transcript.<Hostname>.<RandomString>.<Timestamp>.txt
# 5.3 实战演示:触发与查看转录
1. 触发转录
在目标机器上打开 PowerShell(此时后台已自动开始记录),执行以下系统信息收集命令:
Get-CimInstance Win32_ComputerSystem | Select-Object -Property Name, PrimaryOwnerName, Domain, TotalPhysicalMemory, Model, Manufacturer |
2. 查看转录文件
打开当前用户的 Documents 目录,找到最新生成的 PowerShell_transcript_*.txt 文件。使用记事本或 Get-Content 查看其内容:
Get-Content .\PowerShell_transcript.DESKTOP-XXXXXX.YYYYYYYY.20220207123000.txt |
3. 转录文件内容示例
开启 Include invocation headers 后,文件内容结构如下:
********************** | |
Windows PowerShell transcript start | |
Start time: 20220207123000 | |
Username: DESKTOP-XXXXXX\offsec | |
RunAs User: DESKTOP-XXXXXX\offsec | |
Machine: DESKTOP-XXXXXX (Microsoft Windows NT 10.0.19042.0) | |
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe | |
Process ID: 4512 | |
********************** | |
PS C:\Users\offsec\Documents> Get-CimInstance Win32_ComputerSystem | Select-Object -Property Name, PrimaryOwnerName, Domain, TotalPhysicalMemory, Model, Manufacturer | |
Name PrimaryOwnerName Domain TotalPhysicalMemory Model Manufacturer | |
---- ---------------- ------ ------------------- ----- ------------ | |
DESKTOP-XXXXXX offsec WORKGROUP 8589934592 Virtual Machine Microsoft Corporation | |
PS C:\Users\offsec\Documents> | |
********************** | |
Windows PowerShell transcript end | |
End time: 20220207123005 | |
********************** |
# 5.4 安全与取证价值
- 完整还原攻击者视角:与 Script Block Logging(只记录代码本身)不同,Transcription 记录了攻击者在交互式 Shell 中实际键入的每一条命令以及系统返回的所有输出。
- 评估数据泄露范围:通过查看攻击者执行
Get-Content、dir或数据库查询命令后的输出结果,防守方可以准确评估哪些敏感数据已被攻击者窃取。 - 防御规避检测:某些高级攻击者可能会尝试清理 Event Log(如使用
wevtutil cl),但如果 Transcription 被配置为输出到安全的网络共享路径(SMB),攻击者很难在不触发告警的情况下删除远端的.txt转录文件。
# 6_Case Study: PowerShell Logging for Phishing Attacks
# 6.1 场景复现:宏病毒攻击与转录分析
重新触发之前分析的包含恶意宏的钓鱼邮件附件(Phishing Email with Macro)。由于已提前开启 PowerShell 转录(Transcription),系统自动生成了详细的会话记录文件。
分析转录文件:
在生成的 .txt 转录文件中,可以清晰地看到 PowerShell 执行了一个经过 Base64 编码的 Payload。
- 多阶段执行追踪:查看 Script Block Logging(脚本块日志)解码后的内容时,发现第一层解码后的代码依然包含编码调用(例如调用了另一个 Base64 字符串或下载了第二阶段脚本)。
- 逐层剥离:通过查看第二条(下一个)4104 事件记录,成功提取并还原了最终在内存中执行的真实恶意代码,完整还原了攻击者的多阶段混淆手法。
# 6.2 构建健壮的 PowerShell 日志查询函数
为了高效查询 PowerShell 运行日志,编写了一个自定义函数 Get-PSLogEvent 。该函数利用哈希表(FilterHashtable)在底层进行过滤,并通过动态检查参数提升脚本的健壮性。
(注:已全面修正原笔记中因 OCR 识别导致的变量名拼写错误、哈希表键名错误及日志通道名称错误)
function Get-PSLogEvent { | |
param ( | |
[int]$EventId, | |
[datetime]$Start, | |
[datetime]$End | |
) | |
# 初始化哈希表,修正了原笔记中的 "0Operational" 拼写错误 | |
$filters = @{ LogName = "Microsoft-Windows-PowerShell/Operational" } | |
# 动态检查参数,避免传入空值导致查询报错 | |
if ($EventId -ne $null) { $filters.Id = $EventId } | |
if ($Start -ne $null) { $filters.StartTime = $Start } | |
if ($End -ne $null) { $filters.EndTime = $End } | |
# 执行查询,静默处理无结果时的报错 | |
Get-WinEvent -FilterHashtable $filters -ErrorAction SilentlyContinue | |
} |
# 6.3 模块化管理与导入
将上述函数保存为 PowerShell 模块文件(如 Get-PSLog.psm1 ),并在会话中导入,以便像内置 Cmdlet 一样随时调用。
# 导入自定义模块 | |
Import-Module C:\Sysmon\Get-PSLog.psm1 | |
# 验证模块是否成功加载 | |
Get-Module -Name Get-PSLog |
# 6.4 实战溯源:追踪宏攻击调用链
# 1. 查询脚本块日志 (Event ID 4104)
使用自定义函数查询特定时间窗口内的 4104 事件,还原攻击者执行的完整代码逻辑。
# 表格视图快速浏览 | |
Get-PSLogEvent -EventId 4104 -Start "2/7/2022 13:04:00" -End "2/7/2022 13:05:00" | | |
Format-Table TimeCreated, LevelDisplayName, Message | |
# 列表视图深入分析调用链和完整 Payload | |
Get-PSLogEvent -EventId 4104 -Start "2/7/2022 13:04:00" -End "2/7/2022 13:05:00" | | |
Format-List TimeCreated, Message |
# 2. 查询模块日志 (Event ID 4103)
查询同一时间段的 4103 事件,分析攻击者调用了哪些具体的 PowerShell 模块和 Cmdlet(如 Invoke-Expression , DownloadString 等)。
Get-PSLogEvent -EventId 4103 -Start "2/7/2022 13:04:00" -End "2/7/2022 13:05:00" | | |
Format-Table TimeCreated, LevelDisplayName, Message |
# 3. 提取结构化属性 (Properties 数组)
PowerShell 日志的 Message 字段是纯文本,但在底层 XML 中,数据被结构化存储在 Properties 数组中。注意:数组索引从 0 开始。
对于 Event ID 4103 (Module Logging),常见的属性映射如下(注:具体索引可能因 Windows 版本略有差异,建议通过 XML 视图核对):
Properties[0]/Properties[1]:通常为 ContextInfo(上下文信息,包含用户、主机、PID 等)。Properties[1]/Properties[2]:通常为 Payload / CommandData(实际执行的模块和命令数据)。
提取 Payload 示例:
# 使用计算属性 (Calculated Property) 重命名并提取 Properties 数组中的特定值 | |
Get-PSLogEvent -EventId 4103 -Start "2/7/2022 13:04:00" -End "2/7/2022 13:05:00" | | |
Format-List TimeCreated, | |
@{Label = "Payload"; Expression = { $_.Properties[1].Value }}, # 提取 Payload (根据实际版本调整索引) | |
@{Label = "ContextInfo"; Expression = { $_.Properties[2].Value }} # 提取上下文信息 |
# 6.5 分析总结
通过结合 Transcription(宏观行为记录)、Script Block Logging(微观代码还原) 和 Module Logging(API / 模块调用追踪),防守方可以构建出针对 PowerShell 恶意活动的立体监控体系。即使攻击者使用了复杂的编码和多阶段混淆,这种基于日志索引和属性提取的查询方法也能迅速将其 “剥洋葱” 般层层拆解,暴露出真实的攻击意图。
# 7_Obfuscating/Deobfuscating Commands
# 7.1 基础概念:PowerShell 混淆
在红队行动中,为了绕过防病毒软件(AV)、端点检测与响应(EDR)系统以及基于正则表达式的静态检测规则,攻击者必须对 PowerShell 恶意载荷进行混淆(Obfuscation)。混淆的目的是在不改变代码最终执行逻辑的前提下,彻底改变其文本特征(如打乱关键字、改变编码、插入无意义字符等)。
# 7.2 攻击利器:Invoke-Obfuscation
Invoke-Obfuscation 是由 Daniel Bohannon 开发的一款极其强大的 PowerShell 混淆框架。它提供了多种层级的混淆技术,攻击者可以组合使用这些技术来生成高度复杂的载荷。
核心混淆层级(Modes):
在交互式菜单中,攻击者可以选择以下主要混淆模式:
- TOKEN(令牌混淆):打乱 PowerShell 的关键字和变量名(例如将
Get-Process混淆为get-process或使用反向引号)。 - COMMAND(命令混淆):改变命令的执行结构,例如使用调用运算符
&、iex(Invoke-Expression) 或改变管道结构。 - ARGUMENT(参数混淆):对传递给 Cmdlet 的参数进行混淆,如使用子表达式、类型转换或字符串操作。
- STRING(字符串混淆):对字符串进行反转、替换、拆分或使用字符数组(如
[char]103)来重构。 - ENCODING(编码混淆):将代码转换为 Base64、十六进制或压缩格式,并通过
-EncodedCommand执行。 - LAUNCHER(启动器混淆):生成用于在命令行(如
cmd.exe或wmic)中触发混淆代码的完整启动命令。
# 7.3 日志导出与取证准备
在进行离线分析或需要将日志发送给第三方分析时,可以使用 Windows 原生的 wevtutil 工具将 PowerShell 事件日志导出为 .evtx 文件。
导出 PowerShell 运行日志(包含 Script Block Logging):
:: 创建保存目录
mkdir C:\Temp\Logs
:: 导出 Microsoft-Windows-PowerShell/Operational 日志
wevtutil epl Microsoft-Windows-PowerShell/Operational C:\Temp\Logs\PowerShell_Operational.evtx
:: 导出 Security 日志(需要管理员权限)
wevtutil epl Security C:\Temp\Logs\Security.evtx
注:导出的 .evtx 文件可以在另一台 Windows 机器上通过事件查看器(Event Viewer)直接打开和分析。
# 7.4 防御与检测:Revoke-Obfuscation
为了对抗 Invoke-Obfuscation ,同一研究团队(或相关安全研究员 Carlos Perez)开发了配套的检测框架 Revoke-Obfuscation 。它利用启发式分析和统计学特征来识别被混淆的 PowerShell 代码。
检测原理:Revoke-Obfuscation 并不依赖静态签名,而是通过分析 Script Block Logging(Event ID 4104)中的明文代码特征来进行判断。它会计算以下指标:
- 字符串熵值(Entropy):混淆代码通常具有异常高的随机性。
- 特殊字符比例:如反引号(
`)、加号(+)、括号(())的异常密集使用。 - 关键字变形:检测被拆散或替换的 PowerShell 原生关键字。
实战使用:
导入模块:
Import-Module .\Revoke-Obfuscation.psm1
分析本地日志:
使用Get-RvoScriptBlock扫描本地的 4104 事件,自动标记出可疑的混淆代码。# 扫描当前机器的 PowerShell 日志,输出混淆评分Get-RvoScriptBlock -Verbose
分析导出的离线日志:
如果已经使用wevtutil导出了日志,可以指定路径进行分析:Get-RvoScriptBlock -EvtxPath C:\Temp\Logs\PowerShell_Operational.evtx
输出解读:Get-RvoScriptBlock 会返回一个包含 ObfuscationLevel (混淆等级)和 ScriptBlockText (解码后的脚本内容)的对象。如果 ObfuscationLevel 显示为 High 或 Extreme ,则强烈表明该脚本经过了 Invoke-Obfuscation 或类似工具的处理,需立即触发安全告警并进行深度调查。