Я не использую обходные пути (на самом деле я ненавижу это!), Но обход любой функции, не поддерживающей горячее исправление, может быть выполнен в общем виде, например:
Шаг 1:
вставка JMP <your code>
в начале функции, занимает 5 байт, возможно, немного больше для выравнивания с ближайшей инструкцией. как пример
начало функции для подключения:
SUB ESP,3C
PUSH EDI
PUSH ESI
//more code
станет:
JMP MyFunction
//more code
можно было бы сделать это, написав 0xE9
в первом байте, а затем записав значение (function_addr - patch_addr + sizeof(INT_PTR))
в следующем DWORD. запись должна выполняться с помощью WriteProcessMemory
после установки разрешений на чтение / запись / выполнение с помощью VirtualProtectEx
Шаг 2:
Далее мы создаем интерфейс сборки:
void __declspec(naked) MyFunc()
{
__asm
{
call Check ;call out filter func
test eax,eax ; test if we let the call through
je _EXIT
sub esp,3c ; its gone through, so we replicate what we overwrote
push edi
push esi
jmp NextExecutionAddress ; now we jump back to the location just after our jump
_EXIT:
retn ; note, this must have the correct stack cleanup
}
}
NextExecutionAddress необходимо будет заполнить во время выполнения, используя ModuleBase + RVA
.
Если честно, проще и лучше (!) Просто EAT (таблица адресов экспорта) перехватить таблицу экспорта dll, или IAT (таблица адресов импорта) перехватить таблицы импорта того, что вызывает нужные вам функции фильтровать. У обходов должны быть функции для этого типа хуков, если нет, то для этого есть другие свободно доступные библиотеки.
Другим способом будет использование обходного пути для перехвата каждого вызова в приложениях с использованием dll для перенаправления их на прокси-функцию в вашем собственном коде, это дает преимущество, позволяющее фильтровать только определенные вызовы, а не все через двоичный файл (можно сделать то же самое, используя _ReturnAddress
, но это больше работы), однако недостатком является захват местоположений для исправления (я использую ollydbg + пользовательский механизм исправлений), и он не будет работать на нестандартных функции соглашения о вызовах (например, сделанные с помощью #pragma aux
в Watcom или оптимизированные вызовы, генерируемые VC7 +).
Одна важная вещь, на которую следует обратить внимание: если вы подключаете многопоточное приложение, ваши патчи должны быть сделаны с приостановленным приложением, или же они должны быть сделаны с использованием InterlockedExchange
, InterlockExchange64
и InterlockedExchangePointer
(я использую последнее для всех Перехватчики IAT / EAT, особенно при подключении стороннего процесса)
Глядя на пост, на который вы ссылаетесь, метод, на мой взгляд, ужасен, в основном из-за предположения: P, но как вы называете этот указатель, который вы получаете, и как он получается?