关于这个主板上的第一个问题并且已经很长了 - 我很抱歉(特此感谢大家从这个平台获得的很棒的技巧)。
我正在尝试挂钩几个函数(它或多或少的插件代码,所以我想挂钩的函数不是我写的/不能改变的,但可以在同一个进程/线程中直接访问)微软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个字节中调用调用指令? (如果没有,有没有其他选择?)
非常感谢你阅读(并希望得到你的帮助)
答案 0 :(得分:1)
原始代码执行
045A1A89 call 045A1A8E
045A1A8E pop eax
这是获取eip
注册表内容的简单方法。 pop eax
会立即从堆栈中删除返回地址(045A1A8E
),并在执行时将eax
设置为eip
的值。
Detours显然无法知道这一点并将其视为任何子例程,因此它会从蹦床中执行call 045A1A8E
,这将导致eax
的不同值(不同eip
)
我不完全确定为什么它会返回031F0069
,因为阅读你发布的代码不应该这样做。
所以,是,这是一个非常特殊的情况。 Detours通常完全能够挂钩在前几条指令中调用的函数。这个只是设法完美地将这两条说明放在Detours上,以便以不利的方式将它们分开。