【发布时间】:2014-12-30 15:52:53
【问题描述】:
我试图创建一种我玩的游戏的叠加层,以便实时显示我的 ping,因为存在很多问题并且人们指责 ping,所以我只想要一个简单的解决方案并添加实时 ping 显示在游戏中:)
无论如何,钩子一直是我一直在努力解决的问题,我知道它是如何工作的,但它对我来说从来没有奏效,这是我在无数地方看到的代码,但在经历了蹦床之后崩溃:
void* detour::Hook(BYTE* src, BYTE* dst, int len) {
BYTE *jmp = (BYTE*)malloc(len+5);
DWORD dwback;
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &dwback);
memcpy(jmp, src, len);
jmp += len;
jmp[0] = 0xE9;
*(DWORD*)(jmp + 1) = (DWORD)(src + len - jmp) - 5;
src[0] = 0xE9;
*(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
VirtualProtect(src, len, dwback, &dwback);
return (src + 6);
}
我可以看到它真的很混乱,它使用 malloc 而不是 VirtualAlloc 等。但由于某种原因,它工作了一半:S 无论如何,这只是我用来尝试和获得更好理解的东西钩子,与此同时,我正在编写自己的一些代码:
DWORD detour::SetHook(DWORD src, DWORD dst, int len) {
BYTE* backup;
DWORD oldProtection;
DWORD trampolineAddr;
VirtualProtectEx(GetModuleHandle(NULL), (void*) dst, 5, PAGE_READWRITE, &oldProtection);
//Create trampoline backup
trampolineAddr = (DWORD) VirtualAllocEx(GetModuleHandle(NULL), NULL, 10, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy((void*) trampolineAddr, (void*) dst, 5);
memcpy((void*)(trampolineAddr + 5), (void*) 0xE9, 1);
memcpy((void*)(trampolineAddr + 6), (void*) dst, 4);
//set API hook
memcpy((void*)dst, (void*) 0xE9, 1);
memcpy((void*)(dst + 1), (void*)src, 4);
VirtualProtectEx(GetModuleHandle(NULL), (void*) dst, 5, oldProtection, &oldProtection);
return trampolineAddr;
}
它的作用是返回创建蹦床的地址,我只是在调用了替换挂钩函数的函数后跳转到该地址,所有这些都不起作用:/
所以我的问题本质上是真的,为什么第一个钩子只能在中途工作?我的钩子有什么问题?它创建了到地址的跳转,备份了被覆盖的字节并将它们保存在一个蹦床上,我在我的自定义函数之后跳转到它,但它都不起作用:(
非常感谢一些建设性的反馈,因为这是我已经想掌握了很长时间的东西 :) 提前致谢!
【问题讨论】:
-
这两段代码都将代码的保护更改为
read_write_execute,然后又变回原来的样子。malloc几乎 100% 肯定不会为您提供可执行内存,并且您没有显示第二个函数用于内存分配的内容,所以不能说,但对于它为什么会崩溃似乎是一个合理的解释。你试过拆解蹦床吗? -
memcpy(..., (void*)0xE9, 1)语句应该做什么?0xE9肯定不是有效地址吗? -
是的,正如我所说的第一个代码不是我的,它是我用来更好地理解它的东西,它在编译时确实有效,尽管它在蹦床后崩溃了,并且用于内存分配第二个我使用VirtualAlloc,它在代码中哈哈,一旦我对它进行修改,我只是恢复旧的保护。我确实给它附加了一个调试器并且钩子被成功放置,它运行我的跳转以正常运行但是当它应该返回到原始函数时它以某种方式崩溃,因为地址只包含垃圾。
-
0xE9 表示汇编中的跳转,所以我在函数的第一个字节中放置了一个跳转,然后是 4 个字节,即新函数的地址。
-
@Paze:啊哈,我明白了意图是什么——你想将
0xE9(操作码)写入缓冲区,而不是使用例如设置它。trampolineAddr[5] = 0xE9,你正在使用memcpy。但是memcpy从你给它的地址读取字节,而不是地址本身的值——所以它不会在任何地方复制0xE9,而是试图读取地址@处的一个字节 987654332@,里面有垃圾。原始代码没有这样做。
标签: c++ hook reverse-engineering