更换装配说明会更改其他说明

  • 本文关键字:其他 说明 说明会 c++
  • 更新时间 :
  • 英文 :


我正试图在函数中放置一条调用指令来模拟钩子,所以我应该替换函数开头的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个字节被更改?

如您所见,sub esp,0C0h指令从地址00B533C3开始,但下一条指令push ebx从地址00B533C9开始。您已经覆盖了地址00B533C0到00B533C5,因此在您的6个字节之后,您立即处于sub esp,0C0h指令的中间。

反汇编程序无法知道某个字节是垃圾,而不是指令,所以它试图尽可能地将字节解释为指令,当然,你看到的是荒谬的指令。过了一段时间,(巧合的是)一条荒谬指令的结尾与过去的实际指令的结尾重合,所以从那时起,反汇编程序成功地解释了指令,这就是为什么你的函数的其余部分看起来还可以。

如果你观察实际的字节,而不是这些字节的汇编语言助记符解释,你会发现没有什么奇怪的事情发生

(也许,除了您似乎替换了5个字节,而不是6个字节。)

最新更新