Microsoft 绕道 - 带有汇编器"call"指令的钩子功能

Microsoft Detour - Hook Function with an assembler "call" instruction

本文关键字:指令 功能 call Microsoft 汇编器 绕道      更新时间:2023-10-16

第一个问题,这个问题已经很长了,我很抱歉(在此感谢大家从这个平台上得到的伟大建议)。

我正在尝试钩几个函数(它或多或少是插件代码,所以我想要钩的函数不是由我写的/不能改变,但可以直接访问在同一进程/线程)与微软弯路。

每个要被挂钩的函数都是由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将被再次调用,导致错误的函数..

请理解,并不能保证我想要钩子的每个函数都以上述前言开头。因此我不能重写钩子函数,而忽略了蹦床方法…

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

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

原代码执行

045A1A89  call        045A1A8E  
045A1A8E  pop         eax  

是获取eip寄存器内容的一种简单方法。pop eax立即从堆栈中移除返回地址(045A1A8E),并在执行时将eax设置为eip的值。

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

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

所以,是的,这是一个非常特殊的情况。Detours通常能够完美地钩住在前几个指令之间有调用的函数。这一个只是完美地把这两个指令Detours以一种不利的方式分开。