写蹦床功能

时间:2011-11-11 20:38:27

标签: 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

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

1 个答案:

答案 0 :(得分:3)

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

  • 原始指令的第7个字节
  • JMP

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

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

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

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