Microsoft Detour - 带有汇编器“调用”的钩子函数操作说明
这个板上的第一个问题已经很长了 - 对此我感到很抱歉(并在此感谢大家从这个平台得到的很棒的提示)。
我正在尝试使用 Microsoft Detours 挂钩多个函数(或多或少是插件代码,因此我要挂钩的函数不是我编写的/无法更改的,但可以在同一进程/线程中直接访问)。
每个应挂钩的函数都是由 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
}
}
使用以下trampoline函数:
031F0060 push ebp
031F0061 push ebx
031F0062 push esi
031F0063 push edi
031F0064 call 045A1A8E
031F0069 jmp 045A1A8E
主要问题是trampoline汇编代码中的call指令 1) 将错误的值添加到堆栈(在本例中为 031f0064 而不是 045A1A89) -->使用 eax 进一步处理将收到错误的结果 2)或多或少地破坏了堆栈帧,因为下一个“ret”将跳回“031F0069”==>相同的处理将进行两次; ret 将再次被调用,导致错误的函数。
请理解,不能保证我想要挂钩的每个函数都以上述序言开头。因此我无法重写挂钩函数,并忽略蹦床方法。 ..
所以在所有这篇文章之后的基本问题是: 是否可以使用 Microsoft Detour 挂钩函数,在函数的前 5 个字节中调用调用指令? (如果没有,还有其他选择吗?)
非常感谢您的阅读(并希望得到您的帮助)
The first question on this board and already a pretty long one - i'm sorry for that (and hereby thank you all for the great tips i got from this platform).
I'm trying to hook several functions (it's more or less plugin code, so the function I want to hook is not written/can not be changed by me, but can be directly accessed in the same process/thread) with Microsoft Detours.
Every function which shall be hooked is generated by a c-style compiler and always has the following assembler "startup" code:
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
As you can see some registers are pushed to the stack, and then the call instruction is invoked to the next line (please do not ask to change this, as already said i do not have access to this generated code). The call instruction changes the stack - this stack change is saved in the eax register and used for further processing(!!!)
This method will be hooked to:
045A1A85 jmp hooking_function (528040h)
045A1A8A int 3
045A1A8B int 3
045A1A8C int 3
045A1A8D int 3
045A1A8E pop eax
The hooking function is defined as a naked function which just jumps to the trampoline function.
__inline __declspec(naked) void hooking_function()
{
//more code in future
__asm {
jmp org_func_trampoline
}
}
With the following trampoline function:
031F0060 push ebp
031F0061 push ebx
031F0062 push esi
031F0063 push edi
031F0064 call 045A1A8E
031F0069 jmp 045A1A8E
The main problem is, that the call instruction in the trampoline assembler code
1) adds a wrong value to the stack (in this case to 031f0064 instead of 045A1A89) --> further processing with eax will receive wrong results
2) destroys more or less the stack frame, as the next "ret" will jump back to "031F0069" ==> same processing will be done twice; ret will be called AGAIN, leads to wrong function..
Please understand, that it is NOT guaranteed that every function i want to hook begins with the above stated preamble.. therefore i can not rewrite the hooking function, and ignore the trampoline method...
So the basic question after all this text:
Is it possible to hook a function with Microsoft Detour, where in the first 5 Byte of the function a call instruction is invoked? (if not, are there any alternatives?)
Thank you very much for reading (and hopefully for your help)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
原始代码执行
的只是获取
eip
寄存器内容的简单方法。pop eax
立即从堆栈中删除返回地址 (045A1A8E
) 并将eax
设置为eip
的值在其执行时。Detours 显然无法知道这一点,并将其视为任何子例程,因此它从蹦床执行
call 045A1A8E
,这将导致不同的eax
值(不同的>eip
)。我不完全确定为什么它会返回
031F0069
,通过阅读您发布的代码,它不应该这样做。所以,是的,这是一个非常特殊的情况。 Detours 通常能够完美地挂钩在前几条指令中进行调用的函数。这个只是成功地将这两条指令完美地放置在 Detours 中,以一种不利的方式将它们分开。
The original code performs
which is just an easy way to get the content of the
eip
register. Thepop eax
immediately removes the return address (045A1A8E
) from the stack and setseax
toeip
's value at the point of its execution.Detours obviously has no way of knowing this and treats it like any subroutine, so it performs
call 045A1A8E
from the trampoline which will result in a different value ofeax
(differenteip
).I'm not entirely sure why it would return to
031F0069
, from reading the code you posted it shouldn't be doing that.So, yes, this is a very special case. Detours usually is perfectly capable of hooking functions that have calls among the first few instructions. This one just managed to perfectly place these 2 instructions for Detours to split them in a disadvantageous way.