我试图在一个函数上放置一个调用指令来模拟一个钩子,所以我应该在函数的开头替换6个字节来放置我的调用,对于操作码是2个字节,对于地址是dword。但是在我挂钩之前这是函数的反汇编
void realFunction()
{
00B533C0 push ebp
00B533C1 mov ebp,esp
00B533C3 sub esp,0C0h
00B533C9 push ebx
00B533CA push esi
00B533CB push edi
00B533CC lea edi,[ebp-0C0h]
00B533D2 mov ecx,30h
00B533D7 mov eax,0CCCCCCCCh
00B533DC rep stos dword ptr es:[edi]
MessageBox(NULL, "realFunction()", "Trace", MB_OK);
00B533DE mov esi,esp
00B533E0 push 0
00B533E2 push 0B56488h
00B533E7 push 0B56490h
00B533EC push 0
00B533EE call dword ptr ds:[0B5613Ch]
00B533F4 cmp esi,esp
00B533F6 call _RTC_CheckEsp (0B53A10h)
}
奇怪的是,我只需要替换6个字节
void realFunction()
{
00B533C0 call fakeFunction (0B52EF0h)
00B533C5 rol byte ptr [eax],0 <--
00B533C8 add byte ptr [ebx+56h],dl <--
00B533CB push edi <--
00B533CC lea edi,[ebp-0C0h] <--
00B533D2 mov ecx,30h
00B533D7 mov eax,0CCCCCCCCh
00B533DC rep stos dword ptr es:[edi]
MessageBox(NULL, "realFunction()", "Trace", MB_OK);
00B533DE mov esi,esp
00B533E0 push 0
00B533E2 push 0B56488h
00B533E7 push 0B56490h
00B533EC push 0
00B533EE call dword ptr ds:[0B5613Ch]
00B533F4 cmp esi,esp
00B533F6 call _RTC_CheckEsp (0B53A10h)
}
钩子的代码
#include <iostream>
#include <windows.h>
using namespace std;
void realFunction()
{
MessageBox(NULL, "realFunction()", "Trace", MB_OK);
}
__declspec(naked) void fakeFunction()
{
__asm {
pushad;
pushfd;
}
MessageBox(NULL, "fakeFunction()", "Trace", MB_OK);
__asm{
popfd;
popad;
ret; //This should return back and resumes the execution of the original function;
}
}
void main()
{
DWORD size = sizeof(double);
DWORD oldProtection;
DWORD realFunctionAddr = (DWORD)realFunction;
DWORD fakeFunctionAddr = (DWORD)fakeFunction;
VirtualProtect((LPVOID)realFunctionAddr, size, PAGE_EXECUTE_READWRITE, &oldProtection);
*((PBYTE)(realFunctionAddr)) = 0xE8;
*((PDWORD)(realFunctionAddr + 1)) = fakeFunctionAddr - realFunctionAddr - 5;
VirtualProtect((LPVOID)fakeFunctionAddr, size, oldProtection, &oldProtection);
realFunction();
while (true){
cin.get();
}
}
我想了解为什么会发生这种情况,为什么不更改我更换的6个字节?
答案 0 :(得分:2)
如您所见,sub esp,0C0h
指令从地址00B533C3开始,但下一条指令push ebx
从地址00B533C9开始。您已经覆盖了地址00B533C0到00B533C5,因此在您的6个字节之后立即处于sub esp,0C0h
指令的中间位置。
反汇编程序无法知道某个字节是垃圾而不是指令,因此它会尝试尽可能地将字节解释为指令,当然,您看到的是无意义的指令。过了一段时间(巧合)恰好发生了一个荒谬的指令的结束与过去的实际指令的结束一致,所以从反汇编程序的那一点开始成功地解释了指令,这就是为什么你的函数的其余部分看起来还不错。
如果你查看实际的字节,而不是汇编语言对这些字节的助记符解释,你会看到没有任何时髦的事情发生。
(或许,除非您似乎已经替换了5而不是6个字节。)