2015-02-05 4 views
-3

При отладке моего кода я вижу, что он перескакивает в неопределенную часть RAM, кажется, что malloc не работает. Вот код, который предназначен для создания батута и привязка realFunction к fakeFunction.malloc не выделяет память

void patch() 
{ 
    PINT trampoline = (PINT)malloc(15); 
    DWORD oldProtect; 
    *((PBYTE)trampoline) = 0xE8; 
    *((PDWORD)trampoline + 1) = ((DWORD)fakeFunction - (DWORD)trampoline -5); 
    memcpy(trampoline, realFunction, 6); 
    *((PDWORD)trampoline + 7) = 0xE9; 
    *((PDWORD)trampoline + 8) = ((DWORD)fakeFunction - (DWORD)realFunction - 5); 
    VirtualProtect((LPVOID)realFunction, 6, PAGE_EXECUTE_READWRITE, &oldProtect); 
    *((PBYTE)realFunction) = 0xE9; 
    *((PDWORD)realFunction + 1) = ((DWORD)trampoline - (DWORD)realFunction - 5); 
    VirtualProtect((LPVOID)realFunction, 6, oldProtect, NULL); 
} 

Update: я решил эту проблему, и вот код объяснил:

#include <iostream> 
#include <windows.h> 

using namespace std; 

void realFunction() 
{ 
    MessageBox(NULL, "realFunction()", "Trace", MB_OK); 
} 

void fakeFunction() 
{ 
    MessageBox(NULL, "fakeFunction()", "Trace", MB_OK); 
} 

//I wrote this generic function (although not using it below) to ease the writing to memory process 
template<typename T> 
void writeMemory(DWORD address, T value) 
{ 
    *((T*)address) = value; 
} 

void main() 
{ 
    BYTE originalPrologue[sizeof(DWORD[2])]; //Why DWORD[2]... meh it is just 2*4 = bytes not a big deal. 
    DWORD oldProtection; 
    DWORD addr = (DWORD)realFunction; 

    for (int i = 0; i < sizeof(DWORD[2]); i++) { 
     originalPrologue[i] = (*(PBYTE)(addr + i)); 
    } 

    //(DWORD)((DWORD)fakeFunction - (DWORD)realFunction - 5) note that we do target - source - 5, why - 5 ? because the size of jump instruction is 5, and the destination of jump is relative to it's address. 
    //Implement Hook 
    VirtualProtect(realFunction, sizeof(DWORD[3]), PAGE_EXECUTE_READWRITE, &oldProtection); 
    *((PBYTE)addr) = 0xE9; E9 is JMP instruction 
    *((PDWORD)(addr + 1)) = (DWORD)((DWORD)fakeFunction - (DWORD)realFunction - 5); 
    VirtualProtect(realFunction, sizeof(DWORD[3]), oldProtection, NULL); 

    realFunction(); //Boom, we now jump to our fake function instead of the original one. 

    //Unimplement hook by restoring the original prologue 
    VirtualProtect(realFunction, sizeof(DWORD[3]), PAGE_EXECUTE_READWRITE, &oldProtection); 
    memcpy(realFunction, originalPrologue, sizeof(DWORD[2])); 
    VirtualProtect(realFunction, sizeof(DWORD[3]), oldProtection, NULL); 

    realFunction(); //Test it and we have the original function back! 

    while (true){ 
     cin.get(); 
    } 
} 
+2

Ваш код неуклонный с неопределенным поведением. Предполагая, что DWORD имеет 4 байта (большинство из них находятся на WIN32, но оно только ухудшается, если оно больше), вы можете подумать о том, что на самом деле означает '(PDWORD) батут + 7' *. Математика-указатель говорит: «Возьмите адрес 15-байтового выделения, сметете 28 байтов от указанного адреса, а затем используйте это для * записи * DWORD в неопределенной памяти.Я предполагаю, что 15 должно быть сопряжено с 'sizeof()' кратным некоторого вида. Проверьте, на каком месте вы его обманули, скорее всего, они не допустили ошибок. 'malloc' в порядке, его * ваш код *, который был закрыт. – WhozCraig

+0

Я должен согласиться с @WhozCraig. Это один из самых страшных кодов, которые я видел в своей жизни. Серьезно ... –

+0

Я все еще учась, ребята, пожалуйста, несите меня, @WhozCraig, так зачем смещать 28 байтов с указанного адреса?, Malloc создает пространство в exe для нас, чтобы написать какой-то пользовательский код? –

ответ

2

Этот код полна ошибок. Как указано в комментариях, вы вообще не принимаете указатель arithmetic, поэтому вы записываете значения по неправильным адресам памяти. Вы также не выполняете обработку ошибок, и вы даже не настраиваете функции объезда и трамплина правильно. Вы явно не читали документацию о том, как объезд фактически реализуется:

Detours: Binary Interception of Win32 Functions

В частности:

Для объезда целевой функции, Detours первого выделяет память для динамической функции батута (если статический трамплин не предоставляется), а затем разрешает доступ к записи как для цели, так и для батута. Начиная с первой команды, Detours копирует инструкции с цели на батут, пока не будет скопировано не менее 5 байтов (достаточно для инструкции безусловного перехода). Если целевая функция меньше 5 байт, прерывания прерываются, а возвращает код ошибки. Чтобы скопировать инструкции, Detours использует простой дизассемблер с табличным управлением. Объемы добавляет команду перехода от конца батут к первой не скопированной команде целевой функции. Detours записывает инструкцию безусловного перехода в функцию обхода в качестве первой инструкции целевой функции . Чтобы закончить, Detours восстанавливает исходные разрешения страницы как для функций цели, так и для батутов и сбрасывает кэш команд процессора вызовом FlushInstructionCache.

Инструкции по процессору являются переменной длиной. Различные инструкции имеют разные длины байтов. Возможно, вам придется скопировать более 5 байт в ваш батут, чтобы учесть полные инструкции. Вы не можете предположить, что в каждой функции используется ровно 6 байтов, так как вы можете копировать часть многобайтовой инструкции. Таким образом, вам необходимо проанализировать инструкции исходной функции, которая откладывается, и скопировать правильное количество байтов по мере необходимости, чтобы батут всегда содержал полные инструкции, а затем вам нужно вставить инструкцию JMP с правильным смещением внутри батута, и заставить его перейти к правильному смещению исходной функции.

Хуже того, ваш батут прыгает в вашу функцию объезда вместо оригинальной функции, и вы исправляете исходную функцию, чтобы прыгать в свой батут вместо вашей функции обхода.

Короче говоря, почти каждая строка этого кода просто делает неправильную вещь на каждом шагу. Если вы собираетесь заняться такой передовой техникой, то, по крайней мере, достаточно умны, чтобы использовать предварительно подготовленную библиотеку, которая избавит вас от совершения всех этих ошибок. Ваш плохой код рискует серьезными повреждениями памяти и ошибками времени выполнения.

+0

Этот код не будет выполнен в белом доме: D, я просто учился, и кстати я пойму вещи лучше. Вот почему я спрашиваю вас, ребята, о переполнении стека всякий раз, когда я сталкиваюсь с проблемой ... и да, я много читал о перехвате функций и адресах памяти, а сборка и пример, который я привел здесь, - это просто грубая попытка сделать что-то я уточню его. –

+0

Это не тот код, из которого вы должны изучать программирование. Это тот код, который вы можете написать, как только вы уже знаете, что делаете (чего у вас нет). Есть лучшие и безопасные способы научиться программированию. –

+0

Я не учусь, как программировать: D, как я уже упоминал, прежде чем я программировал в течение 6 лет на C#, и я в значительной степени знаю, как работает язык программирования. Однако C++ все еще немного странно для меня, поскольку вы знаете, что GC Collector делал все связанные с записью персональные данные для нас на C# и Java. –

Смежные вопросы