Написание батутной функции
Мне удалось перезаписать первые несколько байтов функции в памяти и перейти к моей собственной функции. Теперь у меня проблемы с созданием функции батута, чтобы вернуть управление обратно в реальную функцию.
Это вторая часть моего вопроса здесь.
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
это указатель, а не массив.