使用COM将代码注入到受Windows保护的进程中
字数 1744 2025-08-27 12:33:31

通过COM将代码注入受Windows保护的进程(PPL)技术分析

1. Windows保护进程背景

1.1 保护进程模型发展

  • Vista引入Protected Process (PP)

    • 最初为DRM进程设计
    • 严格限制加载的DLL(仅限操作系统安装的代码子集)
    • 可执行文件必须使用特定Microsoft证书签名
  • Windows 8.1引入Protected Process Light (PPL)

    • 放宽DLL加载限制
    • 引入不同签名要求
    • 添加签名级别区分不同类型的受保护进程

1.2 签名级别体系

  • 层级关系
    • 同级或更低级别PPL可完全访问同级或更低级别进程
    • PPL不能完全访问任何级别的PP
    • Anti-Malware PPL是特殊级别,允许第三方通过ELAM证书添加签名密钥

2. 技术原理与绕过方法

2.1 原始脚本注入技术(已修复)

  • 实现方式

    • 通过加载COM对象将JScript代码注入PPL
    • 利用脚本引擎DLL(jscript.dll、scrrun.dll等)
  • 微软修复方案

    • 内核CI.dll中添加黑名单检查(5个脚本相关DLL)
    • 修改DLL资源会导致签名失效

2.2 新攻击目标选择标准

  1. 从普通用户账户运行(非管理员)
  2. 目标是最高签名级别(PPL-WindowsTCB)
  3. 攻击面大的受保护进程

2.3 攻击NGEN进程(MSCORSVW.EXE)

2.3.1 选择原因

  • 不需要管理员权限
  • 加载.NET框架和COM组件
  • 作为PPL运行(CodeGen签名级别)

2.3.2 COM通信分析

  • 进程启动参数

    MSCORSVW -StartupEvent A -InterruptEvent B -NGENProcess C -Pipe D
    
  • 关键函数NGenWorkerEmbedding

    • 通过管道传输封送处理的COM对象(ICorSvcBindToWorker)
    • 使用类型库生成代理/存根

2.3.3 类型混淆攻击

  • 攻击步骤
  1. 修改类型库定义:

    • 将接口指针参数改为整数或其他类型
    • 通过注册表或ROT替换类型库
  2. 代理/存根处理差异:

    • 代理按修改后的类型库封送参数
    • 存根按原始定义解封送
    • 导致类型混淆和任意指针解引用
  3. 构造FakeObject结构:

    struct FakeObject {
        BSTR FakeVTable;
    };
    
    • 通过BSTR控制VTable内容

2.3.4 结合KnownDlls机制

  1. KnownDlls加载原理

    • LdrpFindKnownDll通过LdrpKnownDllDirectoryHandle查找DLL
    • 完全PP禁用KnownDlls,但PPL仍可使用
  2. 攻击实现

    • 继承伪造的KnownDlls目录句柄到PPL进程
    • 使用类型混淆修改LdrpKnownDllDirectoryHandle
    • 通过ICorSvcPooledWorker::CanReuseProcess实现内存写入
  3. DLL注入

    • 放置恶意DLL到伪造的KnownDlls目录
    • 诱导PPL加载System32中已知名称的DLL
    • 执行任意代码(包括DllMain)

2.4 提升到PPL-WindowsTCB

  1. 缓存签名机制

    • 利用NtCreateSection自动缓存签名
    • 需要设置特殊标志(0x40)才能加载到PPL
  2. 实现步骤

    • 伪造缓存签名DLL
    • 通过WERFAULTSECURE.EXE(PPL-WindowsTCB)加载
    • 利用CVE-2018-8449绕过设备保护

3. 防御与缓解

3.1 微软修复措施

  1. 脚本引擎DLL黑名单
  2. 修复缓存签名机制绕过(CVE-2018-8449)
  3. 限制PPL对KnownDlls的访问

3.2 防护建议

  1. 及时安装安全更新
  2. 监控可疑的进程注入行为
  3. 限制普通用户对COM和类型库的修改权限
  4. 使用更高安全机制(如VSM/IUM)替代PPL

4. 影响范围

  • 受影响系统:Windows 10 1803及更早版本
  • 攻击前提:普通用户权限
  • 潜在危害
    • 绕过文件/资源保护(如Windows Store)
    • 管理员权限下可攻击CSRSS、Windows Defender等关键进程

5. 技术总结

本技术通过组合利用以下漏洞实现PPL注入:

  1. COM类型库类型混淆
  2. KnownDlls机制缺陷
  3. 缓存签名验证逻辑问题

这种攻击方式展示了即使在高强度保护机制下,通过巧妙组合多个"非安全边界"问题,仍可能实现权限提升和代码执行。

通过COM将代码注入受Windows保护的进程(PPL)技术分析 1. Windows保护进程背景 1.1 保护进程模型发展 Vista引入Protected Process (PP) : 最初为DRM进程设计 严格限制加载的DLL(仅限操作系统安装的代码子集) 可执行文件必须使用特定Microsoft证书签名 Windows 8.1引入Protected Process Light (PPL) : 放宽DLL加载限制 引入不同签名要求 添加签名级别区分不同类型的受保护进程 1.2 签名级别体系 层级关系 : 同级或更低级别PPL可完全访问同级或更低级别进程 PPL不能完全访问任何级别的PP Anti-Malware PPL是特殊级别,允许第三方通过ELAM证书添加签名密钥 2. 技术原理与绕过方法 2.1 原始脚本注入技术(已修复) 实现方式 : 通过加载COM对象将JScript代码注入PPL 利用脚本引擎DLL(jscript.dll、scrrun.dll等) 微软修复方案 : 内核CI.dll中添加黑名单检查(5个脚本相关DLL) 修改DLL资源会导致签名失效 2.2 新攻击目标选择标准 从普通用户账户运行(非管理员) 目标是最高签名级别(PPL-WindowsTCB) 攻击面大的受保护进程 2.3 攻击NGEN进程(MSCORSVW.EXE) 2.3.1 选择原因 不需要管理员权限 加载.NET框架和COM组件 作为PPL运行(CodeGen签名级别) 2.3.2 COM通信分析 进程启动参数 : 关键函数 : NGenWorkerEmbedding 通过管道传输封送处理的COM对象(ICorSvcBindToWorker) 使用类型库生成代理/存根 2.3.3 类型混淆攻击 攻击步骤 : 修改类型库定义: 将接口指针参数改为整数或其他类型 通过注册表或ROT替换类型库 代理/存根处理差异: 代理按修改后的类型库封送参数 存根按原始定义解封送 导致类型混淆和任意指针解引用 构造FakeObject结构: 通过BSTR控制VTable内容 2.3.4 结合KnownDlls机制 KnownDlls加载原理 : LdrpFindKnownDll 通过 LdrpKnownDllDirectoryHandle 查找DLL 完全PP禁用KnownDlls,但PPL仍可使用 攻击实现 : 继承伪造的KnownDlls目录句柄到PPL进程 使用类型混淆修改 LdrpKnownDllDirectoryHandle 值 通过 ICorSvcPooledWorker::CanReuseProcess 实现内存写入 DLL注入 : 放置恶意DLL到伪造的KnownDlls目录 诱导PPL加载System32中已知名称的DLL 执行任意代码(包括DllMain) 2.4 提升到PPL-WindowsTCB 缓存签名机制 : 利用 NtCreateSection 自动缓存签名 需要设置特殊标志(0x40)才能加载到PPL 实现步骤 : 伪造缓存签名DLL 通过WERFAULTSECURE.EXE(PPL-WindowsTCB)加载 利用CVE-2018-8449绕过设备保护 3. 防御与缓解 3.1 微软修复措施 脚本引擎DLL黑名单 修复缓存签名机制绕过(CVE-2018-8449) 限制PPL对KnownDlls的访问 3.2 防护建议 及时安装安全更新 监控可疑的进程注入行为 限制普通用户对COM和类型库的修改权限 使用更高安全机制(如VSM/IUM)替代PPL 4. 影响范围 受影响系统 :Windows 10 1803及更早版本 攻击前提 :普通用户权限 潜在危害 : 绕过文件/资源保护(如Windows Store) 管理员权限下可攻击CSRSS、Windows Defender等关键进程 5. 技术总结 本技术通过组合利用以下漏洞实现PPL注入: COM类型库类型混淆 KnownDlls机制缺陷 缓存签名验证逻辑问题 这种攻击方式展示了即使在高强度保护机制下,通过巧妙组合多个"非安全边界"问题,仍可能实现权限提升和代码执行。