[译]使用 COOP 绕过 CFI 保护
字数 2013 2025-08-18 11:35:40
使用 COOP 绕过 CFI 保护技术详解
1. 引言
控制流完整性(CFI)已成为漏洞利用缓解的重要标准,有多种实现方式如Microsoft CFG、Microsoft RFG、PaX Team的RAP和Clang的CFI。本文介绍一种高级代码重用技术——伪造面向对象编程(COOP),用于绕过现代CFI保护。
2. 漏洞背景
CVE-2015-5122是Hacking Team利用的Adobe Flash Player(<=18.0.0.203)的UAF漏洞。该漏洞提供进程内存的完整读写原语,通过覆盖vector对象的length成员实现。
3. 传统利用方法分析
传统利用方法通过以下步骤实现:
- 覆盖vector对象的length成员
- 使用ExploitByteArray类提供读写原语
- 定义伪造的"magic"方法并覆盖虚函数指针
- 调用VirtualProtect修改内存页保护标志
- 执行ROP链
这种方法能绕过ASLR和DEP,但无法绕过CFI保护,因为:
- 函数返回地址与原始调用不匹配
- 栈迁移和ROP链执行会被基于Shadow Stack的CFI检测
4. CFI约束条件
为绕过现代CFI实现,必须遵循以下约束:
- 间接调用/跳转到非已知地址
- 返回不符合规定的调用堆栈
- 避免过度使用间接分支
- 避免堆栈指针迁移(即使是暂时的)
- 不注入新代码指针或滥用现有代码指针
- 避免间接调用/跳转/返回到"关键函数"
5. COOP技术原理
伪造面向对象编程(COOP)是一种针对C++应用程序的代码重用技术,基于以下假设:
- CFI实现不考虑C++语义
- 不验证虚函数调用与调用者对象类的关系
5.1 技术组成要素
- vfgadgets:执行特定操作的虚函数
- Main Loop Gadget(ML-G):特殊的vfgadget,包含遍历对象列表并调用每个对象虚函数的循环
5.2 技术实现步骤
- 伪造vtable对象并选择vptr
- 找到合适的vfgadgets
- 组合vfgadgets实现所需功能
- 通过伪造对象列表控制执行流程
6. 实际案例演示
6.1 案例1:获取可执行内存页
组合两个vfgadgets:
ATL::CComControl::CreateControlWindowCLibrariesFolderBase::v_AreAllLibraries
6.1.1 ATL::CComControl::CreateControlWindow分析
关键特性:
- 调用
ATL::_stdcallthunk::Init分配EXECUTE_READWRITE内存页 - 创建thunk将Windows回调转换为虚函数调用
- thunk数据格式:
c7 44 24 04 [thisPointer] e9 [WndProc]
绕过检查:
- 仅验证对象的一个成员为NULL,完全可控
6.1.2 CLibrariesFolderBase::v_AreAllLibraries分析
作为Main Loop Gadget的特性:
- 每次迭代调用相同虚函数(vtable偏移0x4c)
- 仅在函数返回0时停止迭代
- 接收3个参数,传递2个参数
6.1.3 组合实现
伪造对象结构:
- magic方法指针指向ML-ARG-G(vtable+0x18)
- ML-ARG-G内部调用CreateControlWindow(vtable+0x4c)
执行流程:
- 保存原始this指针
- 设置伪造vptr
- 配置vtable中的vfgadget指针
- 调用magic方法启动COOP流程
- 读取分配的EXECUTE_READWRITE内存页地址(存储在this+0x5c)
- 写入shellcode并执行
6.2 案例2:文件操作链
发现的5个vfgadgets可实现:
- 创建指定路径的子目录
- 写入文件"digest.s"
- 调用MoveFileEx重命名文件为"atl.dll"
- 调用SetCurrentDirectory设置进程当前目录
- 调用LoadLibrary加载"atl.dll"
7. 技术优势分析
COOP技术成功绕过CFI的原因:
- Microsoft CFG无法检测合法函数的重定向
- 不违反后端CFI策略(无返回地址覆盖)
- 不使用ROP链
- 不更改堆栈指针
- 仅操作对象指针,不操作代码指针
- VirtualAlloc从合法偏移调用,绕过EMET关键函数保护
8. 防御建议
有效防御COOP攻击需要:
- CFI实现考虑语言语义和上下文状态
- 实施细粒度策略验证虚函数调用与对象类的关系
- 监控异常的对象创建和虚函数调用模式
- 加强关键函数保护机制
9. 总结
COOP技术通过巧妙利用C++虚函数机制和CFI实现的局限性,成功绕过了现代CFI保护。防御此类攻击需要更深入的语义分析和细粒度的控制流验证,标志着软件安全进入了一个需要更复杂防御策略的新阶段。