老伙计,别太相信返回地址

有些朋友曾经问过这么个问题

“通过Microsoft编译器扩展指令ReturnAddress,我可以轻易的知道代码执行流返回到调用者后的下一条指令的地址。那么,我怎样才能通过返回地址来确定它属于哪个DLL呢?”

要小心了

即使你知道这个返回地址属于哪个DLL(使用GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS),那也不一定是那个实际调用的DLL。

我可以想到的一个小技巧是:在一个”可信的”DLL里对某些特定的字节进行搜索,根据搜索到的结果,你(攻击者)就可以决定是否执行它。我们可以简单的使用”retd”这条指令实现这个功能点。然后攻击者可以创建如下图所示的一个栈帧(Stack Frame),例如,一个带有两个参数的函数:

构建完上述的栈帧之后,攻击者可以通过指令跳转到那个被攻击的函数上。

这个被攻击的函数查看了返回地址并观察到了一个指向可信DLL的地址trusted_retd,然后它就信任了调用者并使用攻击者构造的2个参数进行了不安全的操作。
紧接着,被攻击函数执行了一条”retd 8″来返回并清理参数。这个操作将导致控制流转移到trusted_retd,这条指令只是简单的一条retd指令,这将会把控制权转移到hacker_code_addr这个位置,然后攻击者就可以使用这个结果进行后续的攻击流程。

这就是为什么当你听到有人说”我的代码对调用者进行了身份验证,确保调用者是可信的”时需要保持警惕的原因。
因为,他们怎么知道调用者是谁呢?

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Don’t trust the return address》

猜你喜欢

转载自blog.csdn.net/mmxida/article/details/108610746