1

这个板上的第一个问题,已经是一个很长的问题了——我很抱歉(在此感谢大家为我从这个平台获得的重要提示)。

我正在尝试使用 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  

hooking 函数被定义为一个裸函数,它只是跳转到 trampoline 函数。

__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 个字节中调用一个调用指令?(如果没有,还有其他选择吗?)

非常感谢您的阅读(希望对您有所帮助)

4

1 回答 1

1

原始代码执行

045A1A89  call        045A1A8E  
045A1A8E  pop         eax  

这只是获取eip寄存器内容的简单方法。立即从堆栈中删除返回地址 ( ) 并在其执行点设置为pop eax'值。 045A1A8Eeaxeip

Detours 显然无法知道这一点并将其视为任何子程序,因此它call 045A1A8E从蹦床执行,这将导致eax(不同eip) 的不同值。

我不完全确定它为什么会返回031F0069,从阅读您发布的代码来看,它不应该这样做。

所以,的,这是一个非常特殊的情况。Detours 通常完全能够挂钩在前几条指令中调用的函数。这个刚刚设法完美地放置了这两条指令,以便 Detours 以不利的方式将它们分开。

于 2011-08-16T01:41:22.703 回答