我试图在某个win32 api函数中编写一个trampoline挂钩,当我将JMP指令写入原始函数的开头时,我希望它跳转到编解码而不是调用函数。
原始函数start在OllyDBG中如下所示:
PUSH 14
MOV EAX, 12345678
...
我将其修补为:
JMP 87654321
NOP
NOP
以下功能的地址:
int HookFunc(int param)
{
DoStuff(param);
return ExecuteOriginal(param);
}
ExceuteOriginal看起来像这样:
unsigned long address = AddressOfOriginalFunction + 7;
int ExceuteOriginal(int param)
{
__asm
{
PUSH 0x14
MOV EAX, 0x12345678
JMP address
}
}
执行被覆盖的代码并在修补后的代码后立即跳转到原始函数。问题在于,由于它是一个函数,它会使堆栈陷入困境,因为调用者应该清理它并且函数而不是返回,跳转到另一个函数的代码。我猜这就是程序崩溃的原因。
有没有办法使用Visual C ++编译器将汇编代码放在程序的代码部分而不将其放在函数中?这样我就可以跳到那里,执行任何操作,然后返回,而不会有弄乱堆栈的风险。
答案 0 :(得分:6)
解决方案:__declspec(naked)
对于使用naked属性声明的函数,编译器生成没有prolog和epilog代码的代码。您可以使用此功能使用内联汇编程序代码编写自己的prolog / epilog代码序列。
示例:
__declspec( naked ) int ExceuteOriginal(int param)
{
__asm
{
PUSH 14
MOV EAX, 0x12345678
JMP address
}
}