Игра в прятки Дмитрий Коваленко aka Ingrem Спецвыпуск: Хакер, номер #048, стр. 048-046-4 3. Внедренный код читает номер системного сервиса и в своем теле формирует переходник вида: ; Код переходника mov eax, XXXXXXXX push next_instr ret next_instr - адрес второй инструкции перехватываемой функции (это lea edx, [esp+04]). 4. В первые пять байт перехватываемой функции вписывается jmp на обработчик. Теперь, если процесс вызовет перехваченную Native API, управление сразу попадет на обработчик. Когда обработчику понадобится вызвать ту же Native API, он не будет восстанавливать первые пять байт, а просто сделает call на переходник. Назовем такую технику умным сплайсингом. На практике Давай что-нибудь напишем. Например, попробуем скрыться от менеджера процессов, перехватывая NtQuerySystemInformation. Наш перехватчик будет состоять из двух модулей: инсталлятора installer.exe и библиотеки injectDLL.dll, в которой содержится внедряемый код. Инсталлятор - простенькая программка, которая загружает DLL и вызывает из нее функцию InstallHook. Если все прошло успешно - функция InstallHook возвратила ненулевое значение, инсталлятор выводит message box с сообщением об успешном перехвате. Библиотека устроена посложнее. Функция InstallHook с помощью API SetWindowsHookEx устанавливает глобальный хук на вызов процедуры окна (WH_CALLWNDPROC). Процедура хука HookProc не делает ничего полезного, просто передает вызов дальше по цепочке. В точке входа DLL впишем такой код: _start: ; точка входа ; причина вызова - загрузка ; в новый процесс mov eax, [esp+8] cmp eax, DLL_PROCESS_ATTACH je h_8 ; да ; ... ... ... h_8: ; первая ли это загрузка DLL (если да, ; то hInst=0) cmp hInst, 0 jne SpliceAPI ; нет - сплайсировать API! ; если управление попало сюда, ; DLL загружена впервые ; запомним hInst mov eax, [esp+4] mov hInst, eax h_1: ; выход mov eax, 1 ret 12 DLL при первой загрузке получает сообщение DLL_PROCESS_ATTACH, записывает свой HINST в shared-секцию .data. Каждый раз, получая DLL_PROCESS_ATTACH, DLL проверяет, записан ли уже HINST в .data. Если да, значит, DLL загружается не впервые - хук уже поставлен и DLL попала в чужое адресное пространство. Очутившись в чужом адресном пространстве, код инициализации DLL вызывает функцию сплайсинга SpliceAPI. Функция узнает HINST ntdll.dll, адрес NtQuerySystemInformation. Затем функция проверяет первый байт NtQuerySystemInformation. Если байт правильный, подготавливается переходник. Он находится в секции данных: NtQSI_thunk db 0b8h, 0, 0, 0, 0, \; mov eax, xxxx 068h, 0, 0, 0, 0, \ ; push xxxx 0c3h ; ret Подготовку осуществляет следующий код: mov ebx, dword ptr [eax+1] ; строка ниже - это mov eax, service_nmbr mov dword ptr [NtQSI_thunk+1], ebx mov ebx, eax ; вычисляем адрес ; второй инструкции NtQSI add ebx, 5 ; строка ниже - это push addr NtQSI mov dword ptr [NtQSI_thunk+6], ebx Затем осуществляется замена первых пяти байт NtQuerySystemInformation. Делается это стандартным способом. Для снятия защиты с первых пяти байт перехватываемой функции используется VirtualProtect. Вместо них записывается jmp на обработчик - функцию api_hook_proc: |