在汇编和c ++中混淆堆栈

use*_*100 6 assembly hook

我想做以下事情:

我有一个不是我的功能(这里真的没关系,只是说我无法控制它)而且我想修补它以便它调用我的函数,保留参数列表(跳跃不是一种选择).

我正在尝试做的是,在调用该函数之前将堆栈指针放在原来的状态,然后调用我的(就像回去再做同样的事情,但是使用不同的函数).这不起作用,因为堆栈变得混乱.我相信当我进行呼叫时它会替换返回地址.所以,我做了一个步骤来保存返回地址,将它保存在一个全局变量中它可以工作,但这不行,因为我希望它抵制recursitivy,你知道我的意思.无论如何,我是集会的新手,这就是我在这里的原因.

请不要告诉我有关已经制作软件的事情,因为我想以自己的方式做事.

当然,这段代码必须独立于编译器和优化.

我的代码(如果它比可接受的大,请告诉我如何发布):

// A function that is not mine but to which I have access and want to patch so that it calls a function of mine with its original arguments
void real(int a,int b,int c,int d)
{

}

// A function that I want to be called, receiving the original arguments
void receiver(int a,int b,int c,int d)
{
 printf("Arguments %d %d %d %d\n",a,b,c,d);
}

long helper;

// A patch to apply in the "real" function and on which I will call "receiver" with the same arguments that "real" received.
__declspec( naked ) void patch()
{
 _asm
 {
  // This first two instructions save the return address in a global variable
  // If I don't save and restore, the program won't work correctly.
  // I want to do this without having to use a global variable
  mov eax, [ebp+4]
  mov helper,eax

  push ebp
  mov ebp, esp

  // Make that the stack becomes as it were before the real function was called
  add esp, 8

  // Calls our receiver 
  call receiver

  mov esp, ebp
  pop ebp

  // Restores the return address previously saved
  mov eax, helper
  mov [ebp+4],eax

  ret
 }
}

int _tmain(int argc, _TCHAR* argv[])
{
 FlushInstructionCache(GetCurrentProcess(),&real,5);

 DWORD oldProtection;
 VirtualProtect(&real,5,PAGE_EXECUTE_READWRITE,&oldProtection);

 // Patching the real function to go to my patch
 ((unsigned char*)real)[0] = 0xE9;
 *((long*)((long)(real) + sizeof(unsigned char))) = (char*)patch - (char*)real - 5;

 // calling real function (I'm just calling it with inline assembly because otherwise it seems to works as if it were un patched
 // that is strange but irrelevant for this
 _asm
 {
  push 666
  push 1337
  push 69
  push 100
  call real
  add esp, 16
 }

 return 0;
}
Run Code Online (Sandbox Code Playgroud)

打印(并且必须):

参数100 69 1337 666

编辑:

代码我正在测试Vlad建议(仍然不工作)

// A patch to apply in the real function and on which I will call receiver with the same arguments that "real" received.
__declspec( naked ) void patch()
{
    _asm
    {
        jmp start

        mem:

        nop
        nop
        nop
        nop

        start :

        // This first two instructions save the return address in a global variable
        // If I don't save and restore the program won't work correctly.
        // I want to do this without having to use a global variable
        mov eax, [ebp+4]
        mov mem, eax

        push ebp
        mov ebp, esp

        // Make that the stack becomes as it were before the real function was called
        add esp, 8

        // Calls our receiver 
        call receiver

        mov esp, ebp
        pop ebp

        // Restores the return address previously saved
        mov eax, mem
        mov [ebp+4],eax

        ret
    }
} 
Run Code Online (Sandbox Code Playgroud)

Vla*_*lad 0

你曾经有过add esp, 8一次add esp, 16。其中一定有一个是错误的。

编辑:
哦,我明白了,add esp, 8你必须从堆栈中删除ebp之前推送的 2 条指令和返回地址。

在 [ebp+4] 处必须有调用的返回地址_tmain

Edit2:
您可以通过类似的方式分配“内部”变量:

  call next
  dd 0
next:
  pop eax
  mov [eax], yourinfo
Run Code Online (Sandbox Code Playgroud)

但仍然不清楚为什么我们需要保存该值。

Edit3:(已删除,错误)

编辑4:
另一个想法:

__declspec( naked ) void patch()
{
 _asm
 {
  call next
  // here we temporarily save the arguments
  dd   0
  dd   0
  dd   0
  dd   0
next:
  pop eax
  // eax points to the first dd

  // now store the args
  pop edx
  mov [eax], edx
  pop edx
  mov [eax+4], edx
  pop edx
  mov [eax+8], edx
  pop edx
  mov [eax+12], edx

  // now we can push the value
  mov edx, [ebp+4]
  push edx

  // now, push the args again
  mov edx, [eax+12]
  push edx
  mov edx, [eax+8]
  push edx
  mov edx, [eax+4]
  push edx
  mov edx, [eax]
  push edx

  // now continue with the old code
  // --------------------------------
  // restore the arguments    
  push ebp
  mov ebp, esp

  // Make that the stack becomes as it were before the real function was called
  add esp, 8

  // Calls our receiver 
  call receiver

  mov esp, ebp
  pop ebp

  // ----------------------------
  pop edx
  mov [ebp+4], edx

  ret
 }
}
Run Code Online (Sandbox Code Playgroud)

该解决方案可以在递归中幸存,但不能从两个不同的线程同时执行。