Microsoft Detour - 带有汇编程序“调用”指令的挂钩函数
Posted
技术标签:
【中文标题】Microsoft Detour - 带有汇编程序“调用”指令的挂钩函数【英文标题】:Microsoft Detour - Hook Function with an assembler "call" instruction 【发布时间】:2011-08-15 01:43:02 【问题描述】:这个板上的第一个问题已经很长了 - 对此我深表歉意(在此感谢大家从这个平台获得的重要提示)。
我正在尝试hook几个函数(它或多或少是插件代码,所以我要hook的函数不是我写的/不能由我更改,但可以在同一个进程/线程中直接访问)微软绕道。
每个需要挂钩的函数都是由 c 风格的编译器生成的,并且总是有以下汇编“启动”代码:
045A1A85 push ebp
045A1A86 push ebx
045A1A87 push esi
045A1A88 push edi
045A1A89 call 045A1A8E
045A1A8E pop eax
045A1A8F mov ebx,eax
//go on with a little bit more assembler code
正如你所看到的,一些寄存器被压入堆栈,然后调用指令被调用到下一行(请不要要求更改它,因为我已经说过我无权访问这个生成的代码)。 call 指令更改堆栈 - 此堆栈更改保存在 eax 寄存器中并用于进一步处理(!!!)
此方法将被挂钩:
045A1A85 jmp hooking_function (528040h)
045A1A8A int 3
045A1A8B int 3
045A1A8C int 3
045A1A8D int 3
045A1A8E pop eax
钩子函数被定义为一个裸函数,它只是跳转到蹦床函数。
__inline __declspec(naked) void hooking_function()
//more code in future
__asm
jmp org_func_trampoline
具有以下蹦床功能:
031F0060 push ebp
031F0061 push ebx
031F0062 push esi
031F0063 push edi
031F0064 call 045A1A8E
031F0069 jmp 045A1A8E
主要问题是,蹦床汇编代码中的调用指令 1) 向堆栈添加错误值(在本例中为 031f0064 而不是 045A1A89)--> 使用 eax 进一步处理将收到错误结果 2) 或多或少地破坏堆栈帧,因为下一个“ret”将跳回“031F0069” ==> 相同的处理将执行两次; ret 将被再次调用,导致错误的功能..
请理解,不保证我要挂钩的每个函数都以上述序言开头..因此我无法重写挂钩函数,并忽略蹦床方法...
所以在所有这些文本之后的基本问题: 是否可以将函数与 Microsoft Detour 挂钩,在函数的前 5 个字节中调用调用指令? (如果没有,还有其他选择吗?)
非常感谢您的阅读(希望您的帮助)
【问题讨论】:
地址和一切都相对正确吗?为什么您尝试挂钩的函数会调用下一条指令(call 045A1A8E
)?
哦,是的,Detours 可以挂钩一个函数,其中前 5 个字节中有一个调用,只要你正确调用了蹦床。
@Seth Carnegie 感谢您的回答。据我所知,该函数尝试访问寄存器 eip,这可以通过调用下一行并读取堆栈(不是直接)来实现。
哦,地址并不总是相同的(相对跳转)——或者你的意思是什么地址? PS:打电话怎么可能绕道?据我了解(虽然我的汇编知识很基础,如果我错了请纠正我),调用指令会影响堆栈帧,下一个“ret”指令==>下一个“ret”指令总是会跳回到蹦床函数,如果蹦床函数包含一个“调用”,这可能不正确?
当 Detours 绕过某些东西时,它会复制前 5 个(左右)字节(确保不会将指令切成两半)并将它们保存在缓冲区中,然后放在缓冲区的末尾, jmp
回到它绕过它的地方,但加上它从函数中获取的字节数。那是它给你的“原始”函数的地址,所以当你调用它时,执行会转到缓冲区,然后执行前 5 个字节,然后跳回到原始函数 + 5 个字节,然后继续它是快乐的方式。堆栈没有混乱。原代码调用函数时,(更多来)
【参考方案1】:
原代码执行
045A1A89 call 045A1A8E
045A1A8E pop eax
这只是获取eip
寄存器内容的简单方法。 pop eax
立即从堆栈中删除返回地址 (045A1A8E
),并在其执行时将 eax
设置为 eip
的值。
Detours 显然无法知道这一点并将其视为任何子程序,因此它从蹦床执行call 045A1A8E
,这将导致eax
的不同值(不同eip
)。
我不完全确定为什么它会返回031F0069
,从阅读您发布的代码来看它不应该这样做。
所以,是的,这是一个非常特殊的情况。 Detours 通常完全能够挂钩在前几条指令中调用的函数。这个只是设法完美地放置了这两条指令,以便 Detours 以不利的方式将它们分开。
【讨论】:
以上是关于Microsoft Detour - 带有汇编程序“调用”指令的挂钩函数的主要内容,如果未能解决你的问题,请参考以下文章
带有 ASP.NET MVC 5 应用程序的 Microsoft 身份验证循环
带有RabbitMQ.Client.dll异常的Microsoft.Diagnostics.Tracing.EventSource