Ассемблер под Windows №30

Хуки в Windows #3


Доброго времени суток, уважаемые подписчики. Сегодня, как и было обещано, мы рассмотрим возможности Windows-hook процедуры, созданной с типом WH_CBT.


Процедура типа WH_CBT отличается от других типов тем, что может не только предотвратить посылку сообщения, но и полностью аннулировть некоторые изменения в системе. Как и все хук-процедуры она получает три параметра, причём два последних зависят от первого. Первый параметр определяет тип сообщения и может принимать следующие значения:
КодНазваниеЗначение
0HCBT_MOVESIZE*Запрос на перемещение или изменение размера окна
1HCBT_MINMAX*Запрос на минимизацию или максимизацию окна
2HCBT_QSТредом получено сообщение, посылаемое при создании хук-процедуры типа WH_JOURNALPLAYBACK на этот тред
3HCBT_CREATEWND*Запрос на создание окна
4HCBT_DESTROYWND*Запрос на уничтожение окна
5HCBT_ACTIVATE*Запрос на активизацию окна
6HCBT_CLICKSKIPPEDСообщение мышки было убрано из очереди приходящих сообщениий
7HCBT_KEYSKIPPEDСообщение клавиатуры было убрано из очереди приходящих сообщениий
8HCBT_SYSCOMMAND*Запрос на выполнение системной команды
9HCBT_SETFOCUS*Запрос на изменение выделенного окна

* - возвращение ненулевого значения в ответ на такой запрос аннулирует операцию
Последние два параметра, как уже было замечено, зависят от первого параметра.
первый парам.второй парам.третий парам.
HCBT_MOVESIZEhandle окнауказатель на структуру RECT, значения которой можно изменять из хук-процедуры
HCBT_MINMAXhandle окнамладшее слово = значение вида окна (как в ShowWindow)
HCBT_QSнольноль
HCBT_CREATEWNDhandle окнауказател на структуру CBT_CREATEWND
HCBT_DESTROYWNDhandle окнаноль
HCBT_ACTIVATEhandle окнауказатель на структуру CBTACTIVATESTRUCT
HCBT_CLICKSKIPPEDСообщение, убранное из очередиуказатель на сообщение MOUSEHOOKSTRUCT
HCBT_KEYSKIPPEDКод виртуальной клавиши (VK_...)как lParam сообщения WM_KEYDOWN
HCBT_SYSCOMMANDКод системной команды (SC_...)как lParam сообщения WM_SYSCOMMAND
HCBT_SETFOCUShandle выделяемого окнаhandle окна, теряющего выделение
Для лучшего понимания напишем простую программу, после запуска которой попытка изменить размер любого окна приводит к тому, что окно становится 300х200 пикселей. Причём происходит это так, что система думает, что это юзер изменил размер окна! Для этого нам нужно создать динамическую библиотеку (процедуры глобальных хуков должны находиться в динамической библиотеке) и саму программу. Начнём с библиотеки:
cbt_dll.asm:
include kernel32.inc
include user32.inc
include def32.inc
include macros.inc
  .386
  .model flat

  public _InstallHook@4
  public _UninstallHook@0

  .data
hInstance dd 0
hWnd      dd 0
hHook     dd 0
  .code

_InstallHook@4 proc
  mov eax,[esp+04h]
  mov hWnd,eax
  run SetWindowsHookEx, WH_CBT, offset HookProc, hInstance, 0
  mov hHook,eax
  ret 4
_InstallHook@4 endp

HookProc proc
  push ebp
  mov ebp,esp
  mov eax,[ebp+08h]
  test eax,eax
  js no_processing
  test eax,eax    ;cmp eax,HCBT_MOVESIZE
  jnz EndHookProc
  run GetWindowLong, dword ptr [ebp+0ch], GWL_HWNDPARENT
  test eax,eax
  jnz EndHookProc

  mov ecx,[ebp+10h]
  assume ecx:PTR RECT
  mov eax,[ecx].top
  add eax,200
  mov [ecx].bottom,eax
  mov eax,[ecx].left
  add eax,300
  mov [ecx].right,eax
  assume ecx:nothing

EndHookProc:
  leave
  null eax
  ret 12
no_processing:
  leave
  pop eax
  push hHook
  push eax
  jmp CallNextHookEx
HookProc endp

_UninstallHook@0 proc
  run UnhookWindowsHookEx, hHook
  ret
_UninstallHook@0 endp

_start@12:
  mov eax,[esp+04h]
  mov hInstance,eax
  null eax
  inc eax
  ret 12
  end _start@12
Думаю, здесь нет ничего сложного, функции Install/UninstallHook инсталируют/деинсталируют хук, а HookProc, после убеждения в том, что текущее сообщение стоит обрабатывать, изменяет размеры передаваемые системе. Для компиляции также понадобится файл линковки(cbt_dll.lnk):
/dll
/entry:start
/subsystem:windows
/section:.data,SRW
/export:InstallHook
/export:UninstallHook
И батник(cbt_dll.bat):
ml /c /coff /Fl /D_MASM_ cbt_dll.asm
link32 cbt_dll.obj @cbt_dll.lnk
Для лёгкости написания программы используем диалог, который поместим в cbt.rc:
#define DIALOG_1   1
#define WS_VISIBLE 0x10000000L
#define WS_POPUP   0x80000000L
#define WS_CAPTION 0x00C00000L

DIALOG_1 DIALOG 182, 107, 161, 127
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Hooker ;)"
FONT 8, "MS Sans Serif"
{
   PUSHBUTTON "", 100, 50, 49, 62, 31
}
Вот код самой программы(cbt.asm):
include kernel32.inc
include user32.inc
include macros.inc
include def32.inc
include cbt_dll.inc
  .386
  .model flat
  .data
HookFlag     dd ?
ButtonHook   db 'Hook it!',0
ButtonUnhook db 'Unhook',0
  .code
_start:
  null ebx
  run GetModuleHandle, ebx
  run DialogBoxParam, eax, 1, ebx, offset WndProc, ebx
  run ExitProcess, ebx

WndProc proc
  push ebp
  mov ebp,esp
  pusha
  mov edi,[ebp+08h]
  null ebx
  mov eax,[ebp+0Ch]
  cmp eax,WM_COMMAND
  je command_proc
  cmp eax,WM_INITDIALOG
  je init_proc
  cmp eax,WM_CLOSE
  je close_proc
  popa
  null eax
  leave
  ret 16
close_proc:
  run EndDialog, edi, ebx
EndWndProc:
  popa
  null eax
  inc eax
  leave
  ret 16
init_proc:
  run SetDlgItemText, edi, 100, offset ButtonHook
  jmp short EndWndProc
command_proc:
  cmp word ptr [ebp+10h], 100
  jne EndWndProc
  cmp HookFlag,ebx
  jz hook_proc
  run UninstallHook
  run SetDlgItemText, edi, 100, offset ButtonHook
  dec HookFlag
  jmp EndWndProc
hook_proc:
  run InstallHook, edi
  run SetDlgItemText, edi, 100, offset ButtonUnhook
  inc HookFlag
  jmp EndWndProc
WndProc endp
  end _start
Я считаю, что ничего нового здесь нет, единственное, что следует отметить это то, что нужно создать .inc файл для использования нашей библиотеки (cbt_dll.inc):
includelib cbt_dll.lib
  extrn __imp__InstallHook@4:dword
  extrn __imp__UninstallHook@0:dword
InstallHook   equ __imp__InstallHook@4
UninstallHook equ __imp__UninstallHook@0
Компилировать саму программу следует лишь после успешной компиляции библиотеки, так как указанный в cbt_dll.inc файл cbt_dll.lib будет создан лишь в процессе успешной комниляции динамической библиотеки! Компиляцию программы можно произвести следующим батником(cbt.bat):
ml /c /coff /Fl /D_MASM_ cbt.asm
rc cbt.rc
link32 cbt.obj cbt.res /entry:start /subsystem:windows
Если компилятор выдаст ошибку в связи с незаданными константами, то скачайте .inc файлы из дополнения к выпуску.

Дополнения к выпуску:
0030asm - набранный вариант примеров, приведённых в выпуске
0030inc - файлы дополнения kernel32.inc, user32.inc, def32.inc и cbt_dll.inc
0030exe - скомпилированные примеры выпуска


На сегодня это всё. В следующем уроке рассмотрим хук-процедуру WH_CBT. Если есть какие вопросы, пишите. Пишите на Dark_Lord@RusFAQ.ru или Dark_Lord@land.ru.

Сайт управляется системой uCoz