windows10的cfg,windows10cf兼容性最佳设置( 二 )


我定位的可用的API是RtlCaptureContext , 由kernel32.dll、kernelbase.dll和ntdll.dll导出 , 这个API有一个指向CONTEXT结构的参数:

windows10的cfg,windows10cf兼容性最佳设置

文章插图
CONTEXT结构储存了转储的所有的寄存器(包括ESP) , 而且输入值仅仅是一个缓冲区的指针 。看一下TypedArray对象的内存布局:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
第一个DWORD值是虚函数表指针 , 能够被覆盖创建一个假的虚函数表 , 在偏移0x7c处存储API RtlCaptureContext的地址 , 同时偏移0x20是TypedArray指向的真实数据的指针:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
因为泄漏这个缓冲区的地址也是可能的 , 它能提供RtlCaptureContext的参数 。为了完成夹的虚函数表 , 不得不创建一个指针指向偏移0x7c处的ntdll!RtlCaptureContext , 这意味着泄露了RtlCaptureContext的地址 , 继而意味这泄露了ntdll.dll的地址 。执行此操作的默认路径是使用vtable的地址 , 它是一个指向jscript9.dll的指针:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
从这个指针往回0x1000个字节 , 搜索MZ头 , 继而查找到指向kernelbase.dll的导入表 。做同样的操作能偶获得kernelbase.dll的基址 , 然后再获得ntdll.dll的导入表指针并再次获得其基址 , 然后从导出函数中找到RtlCaptureContext 。尽管这个方法是可靠的但是有个缺陷 , 如果在系统中装了EMET , 将触发来自jscript9.dll的代码的崩溃 , 因为从PE头或导出表读取数据不被允许 , 为了绕过EMET我使用了一个不同的技术 。记住每一个非直接调用都被CFG保护 , 因为jscript9.dll的函数被CFG保护了 , 所以不能调用直接指向ntdll的函数 。一个在虚表中偏移0x10的函数如下:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
用原始读操作 , 指向ntdll.dll的指针能通过以下函数找到:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
通过ntdll.dll的指针得到RtlCaptureContext的地址 , 不通过读取导出表而是使用搜索特征和哈希找到并读取 。RtlCaptureContext看起来如下:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
前0x30字节总是相同的并且很特殊 , 因此可以用哈希碰撞找到函数地址:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
函数可以使用指向ntdll.dll的指针作为参数 。
把上面的都整合到一起:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
从这偏移0x200包含了RtlCaptureContext的结果 , 看起来如下:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
从上面可以清楚地看出堆栈指针已经泄漏 , 现在找到一个能控制执行的地址是个问题 。看下栈顶显示:
windows10的cfg,windows10cf兼容性最佳设置

文章插图
那就是当前函数的返回地址 , 这个地址位于与RtlCaptureContext信息中的偏移0x9C处的泄漏指针相距0x40字节的偏移处 。运气好 , 这个偏移对于其他简单函数将是相同的 , 所以应该可以写入并使其覆盖其自己的返回地址 , 从而绕过CFG 。
利用补充如下:

推荐阅读