伪造ASM回邮地址?

时间:2016-03-05 21:53:19

标签: visual-c++ assembly dll reverse-engineering

是否有可能在ebp + 4处伪造返回地址。

我正在编写一个你会注入游戏的DLL,它会调用游戏函数来做事情,但是我调用的函数会检查程序本身的返回地址,如果它在它的基础之外它检测到它。

所以基本上有没有办法以任何方式伪造回复地址?

它的工作原理如下:

if ( (_BYTE *)retaddr - (_BYTE *)unusedPadding >= (unsigned int)&byte_A6132A )
  {
    dword_11E59F8 |= 0x200000u;
    dword_162D06C = 0;
    result = (void (*)())sub_51FEE0(dword_11E59FC, v5, (_BYTE *)retaddr - (_BYTE *)unusedPadding, ebx0, edi0, a1);
  }

2 个答案:

答案 0 :(得分:5)

更好的方式:

    push returnshere
    push your_second_argument
    push your_first_argument
    push address_of_fragment_in_exe
    jmp  function_you_want_to_call
returnshere:
    ; more code

其中address_of_ret_in_exe是此片段的地址:

    add esp, 8 ;4 * number of arguments pushed
    ret

这具有不编辑游戏二进制文件的优点。我已经看过不止一个游戏校验自己,所以如果你编辑它,即使在松弛的空间,你也有麻烦。如果他们经历了如此多的麻烦来验证来自游戏二进制文件的调用,那么他们可能会对编辑的游戏二进制文件进行防御。很高兴他们不跟踪调用图。

答案 1 :(得分:1)

你的意思是在进入被叫函数时,[esp]的返回地址不是实际的呼叫站点?

你可以通过推动你想要的任何东西然后跳跃来模仿call。当然,您以这种方式调用的函数将返回到您提供的返回地址。对于不匹配的call / ret,也会有明显的性能损失,因为您将打破CPU的返回地址预测器堆栈。

您可以将一些蹦床功能放在可接受的地址范围内,并通过它们进行呼叫吗?虽然这在32位ABI中非常不方便,它可以在堆栈中传递args。我想你必须将一个额外的arg传递给它可以用来存储返回地址的trampoline函数,而不是复制所有的args。

所以蹦床可能是这样的:

mov   [esp+20], esi      ; save esi in a dummy arg slot
mov   esi, [esp]         ; save the orig return address in a call-preserved reg
add   esp, 4             ; call with the original args
call  lib_function
push  esi                ; restore the orig return address
mov   esi, [esp+20]      ; and restore esi
ret                      ; return to orig return address

这并不精彩,并且需要为每个库函数复制需要大量代码的代码。 (并且它不会构成堆栈帧,因此可能会影响调试/异常处理?)对于没有很多args的函数,执行类似

的操作可能会更短
push   [esp+8]         ; 2nd arg
push   [esp+8]         ; 1st arg
call  lib_function
add    esp, 8
ret

使用间接调用可以让你使用相同的蹦床来实现多种功能,但如果没有简单的短模式,则会以分支误预测为代价。

当然,这些蹦床都不会起作用,除非您可以将它们粘贴在库中接受来电的地址的内存中。