计算trampoline hook的JMP指令地址

问题描述

我正在尝试计算从一条指令到另一条指令的相对地址偏移量。

我了解基本计算,以及为什么我必须-5(为了满足jmp的大小和指令大小)(Calculating JMP instruction's address)

问题是,如果我不想跳转代码的开头而是跳转到它之后的一些特定指令怎么办?

例如:

original function

我想跳转到突出显示的指令 OPENGL32.dll+48195,而我只有 OPENGL32.wglSwapBu 的起始地址。

从我的代码中,我知道我可以做到

uintptr_t gatewayRelativeAddr = src - gateway - 5;

其中src是OPENGL32.wglSwapBu的地址,gateway是我代码的起始地址。

// len is 5

BYTE* gateway = (BYTE*)VirtualAlloc(NULL,len+5,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
memcpy_s(gateway,len,src,len);

// Jump back to original function,but at the highlighted instruction
uintptr_t gatewayRelativeAddr = src - gateway - 5;

// add the jmp opcode to end of gateway

*(gateway + len) = 0xE9;

*(uintptr_t*)(gateway + len + 1) = gatewayRelativeAddr;

到目前为止,我了解代码的作用: 计算从 gateway 的起始地址到 src 的起始地址的相对地址/字节(原始函数)。我也 -5 来满足跳跃的大小。

但是,当我在内存中查看它时,它最终出现在我想要的位置。但是我在代码中没有指定它跳转到突出显示的指令。

解决方法

这是可行的,因为 len 正好等于所需指令之前的指令 (5) 的字节数,我认为这是重点(您想复制将被跳过的指令,也许稍后修改它们?)。

跳转指令从 gateway+len 开始,因此跳转处的 EIP 将为 gateway+len+5。另一方面,您要跳转到的地址是 src+len。所以相对地址是 (src+len)-(gateway+len+5),而 len 抵消了,所以你的公式是正确的。

如果你想跳转到一个不是你复制的指令之后的下一条指令,你需要通过反汇编计算它从 src 的偏移量(称之为 ofs),并且然后将 gatewayRelativeAddr 设置为 (src+ofs)-(gateway+len+5)