时间:2015-02-12 | 来源:互联网 | 阅读:122
话题:
以win10 preview 9926中IE11的Spartan html解析模块为例,看一下CFG的具体情况:
这里就是被编译器插入的CFG校验函数
但是静态情况下默认的检测函数是一个直接return的空函数,是微软在和我们开玩笑吗?
通过动态调试看一下
从上图我们可以看出,实际运行时的地址和我们通过IDA静态看到的地址是不一样的,这里就涉及到CFG和操作系统相关的那部分。支持CFG版本的操作系统加载器在加载支持CFG的模块时,会把这个地址替换成ntdll中的一个函数地址。不支持CFG版本的操作系统不用理会这个检测,程序执行时直接retn。
这是ntdll中的检测函数
原理是在进入检测函数之前,把即将call的寄存器值(或者是带偏移的寄存器间接寻址)赋值给ecx,在检测函数中通过编译期间记录的数据,来校验这个值是否有效。
检测过程如下:
首先从LdrSystemDllInitBlock+0x60处读取一个位图(bitmap),这个位图表明了哪些函数地址是有效的,通过间接调用的函数地址的高3个字节作为一个索引,获取该函数地址所在的位图的一个DWORD值,一共32位,证明1位代表了8个字节,但一般来说间接调用的函数地址都是0x10对齐的,因此一般奇数位是不使用的。
通过函数地址的高3个字节作为索引拿到了一个所在的位图的DWORD值,然后检查低1字节的0-3位是否为0,如果为0,证明函数是0x10对齐的,则用3-7bit共5个bit就作为这个DWORD值的索引,这样通过一个函数地址就能找到位图中所对应的位了。如果置位了,表明函数地址有效,反之则会触发异常。
这里有个有趣的东西,虽然使用test cl,0Fh检测是否0x10对齐,如果对齐的话实际上用3-7位作为索引,也就是说第3位一定是0。但如果函数地址不是0x10对齐的话,则会对3-7位 or 1,然后再作为索引。这样就有一个弊端,如果一个有效的间接调用的函数地址是8字节对齐的,那么其实是允许一个8字节的一个错位调用的,这样可能导致的结果就是可能造成虽然通过了校验,但是实际调用的地址并不是原始记录的函数地址。
湘ICP备2022002427号-10 湘公网安备:43070202000427号
© 2013~2024 haote.com 好特网