嗨,我想了解一个函数,它是关于Windows API挂钩的。我试图钩住LoadLibraryA,看看是否有作弊器试图注入我的游戏。为此我试图拦截任何对LoadLibraryA的调用。
我试着写评论来解释我认为发生了什么,但我对后面的部分不确定。
// src = address of LoadLibraryA in kernel32.dll,
// dst = my function prototype of LoadLibraryA
// len = 5, as we allocate a JMP instruction (0xE9)
PVOID Detour(BYTE* src, const BYTE* dst, const int len)
{
BYTE* jmp = (BYTE*)malloc(len + 5); // allocate 10 bytes
DWORD oldProtection; // change protection of 5 bytes starting from LoadLibraryA in kernel32.dll
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &oldProtection); // Changes the protection on a region of committed pages in the virtual address space of the calling process.
memcpy(jmp, src, len); // save 5 first bytes of the start of LoadLibraryA in kernel32.dll from src to jmp
jmp += len; // start from byte 6
jmp[0] = 0xE9; // insert jump from byte 6 - 10:
// jmp looks like this currently: [8BFF] = 2 bytes [55] = 1 byte [8BEC] = 2 bytes [0xE9] = 5 bytes
// ??
*(DWORD*)(jmp + 1) = (DWORD)(src + len - jmp) - 5; // ?
// ??
src[0] = 0xE9;
*(DWORD*)(src + 1) = (DWORD)(dst - src) - 5; // ?
// Set the same memory protection as before.
VirtualProtect(src, len, oldProtection, &oldProtection);
// ??
return (jmp - len);
}
以下是勾当前和勾当后的表示。
该函数工作正常,只是需要帮助理解该函数的后面部分>发生了什么。我不确定从这里开始jmp += len会发生什么。
我注意到的第一件事是你的代码是一次完成了绕行和jmp返回,这和我通常看到的人们的做法不同。
memcpy(jmp, src, len)。
你把偷来的字节复制到你的shellcode的位置上
jmp是你要跳转到的地址。
jmp += len;
length是被盗的字节数,或者说是你覆盖的字节数,这些字节被复制到你jmp的区域,因为你必须仍然执行它们。 所以你的推进到了你的shellcode中相对jmp之后的直接字节
jmp[0] = 0xE9。
你正在写相对跳转指令
(DWORD)(jmp + 1)=(DWORD)(src + len - jmp)- 5;
jmp + 1 = jmp指令后需要放置相对地址的地址。
(src + len - jmp) - 5
是获取相对地址所需的公式。
src[0] = 0xE9; (DWORD)(src + 1) = (DWORD)(dst - src) - 5。
你做的事情和你在shellcode里面做的一样,只不过在这种情况下,你只是创建了迂回到它的路径。
return (jmp - len)。
你正在返回shellcode的地址(这有点奇怪,但你必须这样做,因为你的代码已经做了) jmp +=len
)