简体   繁体   English

替换汇编指令会更改其他指令

[英]Replacing assembly instruction changes other instructions

I am trying to place a call instruction at a function to simulate a hook, so i should be replacing 6 bytes in the beginning of the function to place my call which is 2 bytes for the opcode and a dword for the address. 我试图在函数上放置一个调用指令以模拟一个钩子,所以我应该在函数的开头替换6个字节以放置我的调用,这是2个字节的操作码和一个dword的地址。 however here is the disassembly of the function before i hook it 但是这里是我钩上函数之前的反汇编

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)  
}

and strangely here is it after i just replace 6 bytes 奇怪的是我刚替换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)  
}

code for the hook 钩子的代码

#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();
    }
}

I want to understand why this happens, why not just the 6 bytes i replaced are changed ? 我想了解为什么会发生这种情况,为什么不只更改我替换的6个字节?

As you can see, the sub esp,0C0h instruction begins at address 00B533C3, but the next instruction push ebx begins at address 00B533C9. 如您所见, sub esp,0C0h指令从地址00B533C3开始,但是下一条指令push ebx从地址00B533C9开始。 You have overwritten addresses 00B533C0 through 00B533C5, so immediately after your 6 bytes you are in the middle of the sub esp,0C0h instruction. 您已经覆盖了地址00B533C0到00B533C5,因此在6个字节之后,您立即位于sub esp,0C0h指令的中间。

The disassembler has no way of knowing that a certain byte is garbage and not an instruction, so it tries to interpret the bytes as instructions, as best as it can, and what you see is, of course, nonsensical instructions. 反汇编程序无法知道某个字节是垃圾而不是指令,因此它会尽力将字节解释为指令,并且您所看到的当然是无意义的指令。 After a while it just so happens (by coincidence) that the end of a nonsensical instruction coincides with the end of an actual instruction that used to be there, so from that point on the disassembler interprets instructions successfully, that's why the remainder of your function looks okay. 过了一会儿,碰巧的是,一个无意义的指令的结尾与一个曾经存在的实际指令的结尾相吻合,因此从这一点开始,反汇编程序成功地解释了指令,这就是为什么剩下的功能看起来还好

If you look at the actual bytes, and not at the assembly language mnemonic interpretations of these bytes, you will see that nothing funky is going on. 如果您查看实际的字节,而不是这些字节的汇编语言助记符解释,您将发现没有什么时髦的事情。

(Except, perhaps, for the fact that you appear to have replaced 5, not 6 bytes.) (也许除了您似乎替换了5个字节而不是6个字节的事实。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM