当前位置: 首页 > 科技观察

对CFG漏洞缓解机制的分析研究

时间:2023-03-15 21:46:36 科技观察

ControlFlowGuard(CFG)是Windows的一种安全机制,其目的是通过检查间接调用的目标地址是否为有效函数来缓解执行流的重定向,我们可以用这个例子来分析。0x01CFG是如何工作的通过这个例子,我们用MSVC编译器编译一个exe文件,看看在调用main()之前生成并执行了哪些代码:scrt_get_dyn_tls_init_callback获取指向TLS回调表的指针以调用第一个条目。回调的函数受CFG保护,所以编译器在执行ESI中的目标地址之前添加代码检查函数地址是否有效。然后执行:__guard_check_icall_fptrddoffset_guard_check_icall_nop_guard_check_icall_nopprocnearretn_guard_check_icall_nopendpretn就可以绕过,为什么?这样程序可以在不支持CFG的旧操作系统版本上运行。在支持它的系统上,_guard_check_icall_nop地址被NTDLL中的LdrpValidateUserCallTarget替换:ntdll!LdrpValidateUserCallTarget:movedx,[ntdll!LdrSystemDllInitBlock+0xb0(76fb82e8)]moveax,ecxshreax,8ntdll!LdrpValidateUserCallTargetBitx,ed+movedax,movedx*4]moveax,ecxshreax,30x02Bitmap的介绍对于CFG,他们在LoadConfig目录下给PE增加了一堆新字段:GuardCFCheckfunctionpointer,指向guard_check_icall_ptr,也就是要被调用的函数的地址replacedandGuard加载PE时创建的Bitmap中包含了所有要设置为有效目标的函数的RVAs的CF函数表。验证调用目标的用户的Ldrp是否从第一条指令中的LdrSystemDllInitblock+0xb0获取到Bitmap的地址。Bitmap包含整个过程中每16个字节的“状态”。加载PE时,表中的RVA将转换为偏移量,然后相应地设置该偏移量处的状态。0x03TransferBitmap我的想法是使用GuardCFFunction表将选定状态填充到Bitmap中,我们在其中重新生成代码,然后将其复制到入口点的Bitmap中并执行。感谢AlexIonescu在WindowsInternals的研究,我得以找到一些以前的文档:假设我们代码中的第一个字节是0x10(010000b),我们从Bitmap传输代码的区域从0x402000(RVA:0x2000)开始,为了清楚起见,我们将对假RVA使用相同的区域。要生成0x10,我们只需要表中的1个条目:0x2020,它跳过前32个字节,使状态设置为0000b,0x2020将下一个状态设置为01b,Bitmap变为010000b。现在要获得状态11b,假设我们想要字节0x1D(011101b),我们使用未对齐的RVA,表将变为:0x2000(设置为01b)、0x2012(设置为11b)、0x2020(设置为01b)。要得到10b,我们需要使用一种带有元数据的特殊类型的RVA,但很简单,我们将一个字节附加到用于生成10b的RVA。元数据是一个标志:IMAGE_GUARD_FLAG_FID_SUPPRESSED(1)或IMAGE_GUARD_FLAG_EXPORT_SUPPRESSED(2)。所以我们说要生成0x86(10000110b),使用:0x2000和0x2(设置为10b),0x2010(设置为01b),0x2030和0x2(设置为10b)。0x04位图转换movesi,0DEADh;GuardCFCheckFunctionPointerpointsheremovesi,[esi+2];getLdrSystemDllInitBlock+0xb0addressmovesi,[esi];gettheBitmapaddressmoveax,[ebx+8];ebx=fs:[30h]atstarttimeleaedi,[eax+xxxxxxxx];imagebase+bufferrvaaddah,20h;imagebase+0x2000shreax,8;shift-right8bitstomaketheoffsetleaesi,[esi+eax*4];esi=ourcodeintheBitmapmovecx,xxxxxxxx;sizeofcoderepmovsb我们让loader把0DEADH替换成LDRP验证用户调用目标的地址,从中我们可以得到位图的地址,我们计算该区域在位图中的偏移量(0x402000)并从中复制再生代码。0x05分析总结那么,当检测到无效地址时会发生什么?该计划被终止。因为大多数更改PE文件的工具或代码不支持CFG:任何更改为在别处执行代码的地址都必须在表中。这会消除许多病毒更改入口点地址或使用入口点模糊(EPO)技术的影响。但是,如果你在PE中禁用CFG,你可以用你自己的地址替换GuardCFCheck函数指针来获取EPO。本文翻译自:https://github.com/86hh/PagedOut2/blob/master/CFGTeleport.pdf如有转载请注明原文地址: