Microsoft Detour - Hook函数与汇编程序“调用”指令

时间:2011-08-15 01:43:02

标签: c++ hook call detours

关于这个主板上的第一个问题并且已经很长了 - 我很抱歉(特此感谢大家从这个平台获得的很棒的技巧)。

我正在尝试挂钩几个函数(它或多或少的插件代码,所以我想挂钩的函数不是我写的/不能改变的,但可以在同一个进程/线程中直接访问)微软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

正如您所看到的,一些寄存器被推送到堆栈,然后调用指令被调用到下一行(请不要求更改它,因为已经说过我无法访问此生成的代码)。调用指令更改堆栈 - 此堆栈更改保存在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将被称为AGAIN,导致错误的功能..

请理解,我不能保证我想挂钩的每个功能都是从上面提到的序言开始的。因此我无法重写挂钩功能,而忽略了蹦床方法......

所有这些文字之后的基本问题: 是否可以使用Microsoft Detour挂钩函数,在函数的前5个字节中调用调用指令? (如果没有,有没有其他选择?)

非常感谢你阅读(并希望得到你的帮助)

1 个答案:

答案 0 :(得分:1)

原始代码执行

045A1A89  call        045A1A8E  
045A1A8E  pop         eax  

这是获取eip注册表内容的简单方法。 pop eax会立即从堆栈中删除返回地址(045A1A8E),并在执行时将eax设置为eip的值。

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

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

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