C++ C++;midfunction钩子覆盖原始局部变量

C++ C++;midfunction钩子覆盖原始局部变量,c++,x86,inline-assembly,C++,X86,Inline Assembly,我编写了一个中间函数钩子,我注意到函数的原始局部变量被我在函数中声明的变量覆盖 这是我的密码: DWORD jbPlantTrap = 0x48ED53 + 7; DWORD jbPlantTrapSkip = 0x48EDD6; __declspec(naked) void hkPlantTrap() { __asm { PUSHAD PUSHFD } // this variable is overwriting the or

我编写了一个中间函数钩子,我注意到函数的原始局部变量被我在函数中声明的变量覆盖

这是我的密码:

DWORD jbPlantTrap = 0x48ED53 + 7;
DWORD jbPlantTrapSkip = 0x48EDD6;
__declspec(naked) void hkPlantTrap()
{
    __asm
    {
        PUSHAD
        PUSHFD
    }

    // this variable is overwriting the original [EBP-4]
    unsigned char* player;
    unsigned char* packet;

    __asm
    {
        MOV ECX, DWORD PTR SS : [EBP + 0x8]
        MOV player, ECX
        MOV EDX, DWORD PTR SS : [EBP + 0x0C]
        MOV packet, EDX
    }

    if (*(WORD*)(packet + 2) == 114 && sub_46261E(player, 104))
    {
        __asm
        {
            POPFD
            POPAD

            JMP[jbPlantTrapSkip]
        }
    }
    else
    {
        // go back to original jump
        __asm
        {
            POPFD
            POPAD

            MOV DWORD PTR SS : [EBP - 0x34] , 0x0

            JMP[jbPlantTrap]
        }
    }
}
我怎样才能防止它这样做,这样我在迂回中声明的任何变量都不会影响原始函数

就像
player
是如何覆盖
[EBP-4]
并弄乱原始函数上的变量,从而导致奇怪的行为

我的挂钩功能供参考:

void __cdecl PlaceJMP(BYTE *pAddress, DWORD dwJumpTo, DWORD dwLen) 
{
    DWORD dwOldProtect, dwBkup, dwRelAddr;
    VirtualProtect(pAddress, dwLen, PAGE_EXECUTE_READWRITE, &dwOldProtect);
    dwRelAddr = (DWORD)(dwJumpTo - (DWORD)pAddress) - 5;
    *pAddress = 0xE9;
    *((DWORD *)(pAddress + 0x1)) = dwRelAddr;
    for (DWORD x = 0x5; x < dwLen; x++)
        *(pAddress + x) = 0x90;
    VirtualProtect(pAddress, dwLen, dwOldProtect, &dwBkup);
}

更新

将变量声明移到函数外部可以使其按预期工作,但我希望避免这种情况。我还有其他选择吗

DWORD jbPlantTrap = 0x48ED53 + 7;
DWORD jbPlantTrapSkip = 0x48EDD6;
unsigned char* player1; // moved outside function
unsigned char* packet1; // moved outside function
__declspec(naked) void hkPlantTrap() {
...

当使用mid函数钩子和declspec裸函数时,必须在汇编中编写所有函数。您应该声明裸函数之外的任何变量,然后在程序集中引用这些变量,这样就不会损坏堆栈


或者,您可以增加堆栈大小,完成自己的工作,然后在返回之前展开堆栈,但老实说,这会更烦人。

当使用mid函数挂钩和declspec裸函数时,您必须在汇编中编写所有内容。您应该声明裸函数之外的任何变量,然后在程序集中引用这些变量,这样就不会损坏堆栈


或者,您可以增加堆栈大小,完成自己的工作,然后在返回之前展开堆栈,但老实说,这会更烦人。

IIRC,裸函数的整个主体都必须用asm编写。使用C变量和语句将导致编译器生成代码,而没有进行任何正确的设置。此外,您自己的asm使用
[EBP+0x8]
表示某些内容,但您从未将EBP设置为指向任何内容。@PeterCordes打印出
player
packet
实际上表明它指向正确的变量,因此我相信
[EBP]
设置正确。我还有其他类似的函数,可以用,但它仍然替换了原来的函数变量。幸运的是,这些被覆盖的变量并不重要,因此不会影响行为。不幸的是,这个函数覆盖了一个重要的变量。IIRC,一个裸函数的整个函数体必须用asm编写。使用C变量和语句将导致编译器生成代码,而没有进行任何正确的设置。此外,您自己的asm使用
[EBP+0x8]
表示某些内容,但您从未将EBP设置为指向任何内容。@PeterCordes打印出
player
packet
实际上表明它指向正确的变量,因此我相信
[EBP]
设置正确。我还有其他类似的函数,可以用,但它仍然替换了原来的函数变量。幸运的是,这些被覆盖的变量并不重要,因此不会影响行为。不幸的是,这个函数覆盖了一个重要的变量。我确实尝试过通过保存esp和sub'ng它来执行
prolog
epilog
,希望能为变量获得额外的空间。在我的2个int指针中有8个字节,但它似乎根本不起作用。只在函数外使用变量是可行的,但我有点担心多线程访问全局变量。@majidarif我这么做已经很长时间了,而且在多线程处理方面从来没有遇到过任何问题,但将来可能会出现问题。当你到达那里时,我会穿过那座桥,我确实试着做了一个
prolog
epilog
,通过保存esp和sub'ng它,希望能为变量获得额外的空间。在我的2个int指针中有8个字节,但它似乎根本不起作用。只在函数外使用变量是可行的,但我有点担心多线程访问全局变量。@majidarif我这么做已经很长时间了,而且在多线程处理方面从来没有遇到过任何问题,但将来可能会出现问题。我想,你到了那里我会过桥的
DWORD jbPlantTrap = 0x48ED53 + 7;
DWORD jbPlantTrapSkip = 0x48EDD6;
unsigned char* player1; // moved outside function
unsigned char* packet1; // moved outside function
__declspec(naked) void hkPlantTrap() {
...