Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #48, НОЯБРЬ 2004 г.

Игра в прятки

Дмитрий Коваленко 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:

Назад на стр. 048-046-3  Содержание  Вперед на стр. 048-046-5