c - 编写蹦床函数

标签 c winapi assembly reverse-engineering

我已经成功地覆盖了内存中函数的前几个字节并将其绕到我自己的函数。我现在在创建蹦床函数以将控制权返回到实际函数时遇到问题。

这是我问题的第二部分 here .

BYTE *buf = (BYTE*)VirtualAlloc(buf, 12, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
void (*ptr)(void) = (void (*)(void))buf;

vm_t* VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *), vmInterpret_t interpret )
{
    MessageBox(NULL, L"Oh Snap! VM_Create Hooked!", L"Success!", MB_OK);

    ptr();

    return NULL;//control should never get this far
}

void Hook_VM_Create(void)
{
    DWORD dwBackup;
    VirtualProtect((void*)0x00477C3E, 7, PAGE_EXECUTE_READWRITE, &dwBackup);

    //save the original bytes
    memset(buf, 0x90, sizeof(buf));
    memcpy(buf, (void*)0x00477C3E, 7);

    //finish populating the buffer with the jump instructions to the original functions
    BYTE *jmp2 = (BYTE*)malloc(5);
    int32_t offset2 = ((int32_t)0x00477C3E+7) - ((int32_t)&buf+12);
    memset((void*)jmp2, 0xE9, 1);
    memcpy((void*)(jmp2+1), &offset2, sizeof(offset2));
    memcpy((void*)(buf+7), jmp2, 5);

    VirtualProtect((void*)0x00477C3E, 7, PAGE_EXECUTE_READ, &dwBackup);
}

0x00477C3E是被覆盖的函数地址。在我覆盖它们之前,原始函数的 asm 被保存到 buf。然后我的 5 字节 jmp 指令被添加到 buf 以返回到原始函数的其余部分。

问题出现在调用ptr()时,程序崩溃。在调试它崩溃的站点时,它看起来不像我的 ptr() 函数,但是仔细检查我的偏移量计算看起来是正确的。

注意:省略了多余的代码以使阅读更容易

编辑:这就是 ptr() 函数在 ollydbg 中的样子

0FFB0000   55               PUSH EBP
0FFB0001   57               PUSH EDI
0FFB0002   56               PUSH ESI
0FFB0003   53               PUSH EBX
0FFB0004   83EC 0C          SUB ESP,0C
0FFB0007  -E9 F1484EFD      JMP 0D4948FD

所以看起来好像我的偏移计算是错误的。

最佳答案

所以你的 buf[] 最终包含了两件事:

  • 原始指令的前 7 个字节
  • 跳跃

然后你将控制权转移到buf。是否保证前 7 个字节只包含完整的指令?否则,您可能会在执行从这 7 个字节开始的最后一条不完整指令时或之后崩溃。

是否保证这 7 个字节中的指令不进行任何 EIP 相关计算(这包括具有 EIP 相关寻址的指令,例如主要是跳转和调用)?否则,原始功能的延续将无法正常工作,最终可能会导致程序崩溃。

原始函数是否接受任何参数?如果是这样,只需执行 ptr(); 即可使原始代码处理从寄存器和/或堆栈中获取的垃圾(取决于调用约定)并可能崩溃。

编辑:还有一件事。使用 buf+12 而不是 &buf+12。在您的代码中 buf 是一个指针,而不是数组。

关于c - 编写蹦床函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8099660/

相关文章:

c - 用 C 语言打印位集

c - 在 Unix/Linux 上用 C 动态确定终端高度的最佳方法是什么?

.net - 以编程方式确定 UNC 路径中的可用空间

c++ - 检测窗口是否已完成绘制并显示在屏幕上 (WINAPI)

winapi - 如何在另一个线程的上下文中调用函数?

assembly - 为什么 VMOV.F64 不允许我加载零?

c++ - 空指针强制转换 C++ 和 GTK

C IPC等待 child

performance - 使一个寄存器依赖于另一个寄存器而不改变它的值

c - 试图对一个函数进行逆向工程