Написание батутной функции

Мне удалось перезаписать первые несколько байтов функции в памяти и перейти к моей собственной функции. Теперь у меня проблемы с созданием функции батута, чтобы вернуть управление обратно в реальную функцию.

Это вторая часть моего вопроса здесь.

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 ответ

Решение

Таким образом, ваш buf[] содержит 2 вещи:

  • 7 первых байтов оригинальной инструкции
  • JMP

Затем вы передаете управление в buf. Гарантируется ли, что первые 7 байтов содержат только целые инструкции? Если нет, вы можете потерпеть крах во время или после выполнения последней, неполной инструкции, начинающейся в этих 7 байтах.

Гарантируется ли, что инструкции в этих 7 байтах не выполняют каких-либо EIP-относительных вычислений (это включает в себя инструкции с EIP-относительной адресацией, такие как переходы и вызовы в первую очередь)? Если нет, продолжение в исходной функции не будет работать должным образом и, вероятно, приведет к сбою программы.

Принимает ли оригинальная функция какие-либо параметры? Если это так, просто делать ptr(); заставит этот оригинальный код работать с мусором, взятым из регистров и / или стека (зависит от соглашения о вызовах) и может произойти сбой.

РЕДАКТИРОВАТЬ: еще одна вещь. использование buf+12 вместо &buf+12, В вашем коде buf это указатель, а не массив.

Другие вопросы по тегам