Hot Patching to mechanizm wprowadzony już nie pamiętam, chyba w Windows XP, skorygujcie mnie jeśli błędnie strzeliłem, w każdym razie powstał on to po, aby uprościć stawianie hooków w funkcjach bibliotek systemowych.
Normalnie hookowanie funkcji w bibliotekach DLL polega na tym, aby pobrać adres funkcji i w miejscu pierwszych instrukcji wstawić trampolinę do kodu hooka, wiąże się to z użyciem deasemblera, przepisywaniem instrukcji i jest mówiąc krótko problematyczne.
Microsoft wyszedł naprzeciw takiemu zapotrzebowaniu na hookowanie i stworzył mechanizm hotpatching, funkcje bibliotek systemowych posiadają specjalny prolog, który ułatwia szybkie ustawianie i usuwanie hooków bez potrzeby grzebania się w przepisywanie instrukcji.
Zauważcie, że pierwsze bajty funkcji stanowi instrukcja mov edi,edi (która sama w sobie nic nie robi), a przed nią znajduje się okno z 5 instrukcjami nop.
Wstawienia hooka do takiej funkcji polega na tym, aby w miejscu instrukcji mov edi,edi wstawić krótki skok jmp short (zakodowany jako EB xx) do tego okna nop-ów, a w miejscu nop-ów ustawić instrukcję call (E8 xx xx xx xx), która wywoła właściwy kod hooka.
Całość jest banalnie prosta i pozwala w szybkim tempie wstawiać hooki bez potrzeby korzystania z bibliotek typu Detours.
Poniżej prezentuję kod dla MASM-a, przedstawiający przykładowe ustawienie hooka na funkcję SetWindowTextA z wykorzystaniem mechanizmu hotpatching.
.data
; biblioteka, ktora hookujemy
szLibUser db 'USER32.dll',0
; nazwa hookowanej funkcji
szSetWindowTextA db 'SetWindowTextA',0
; adres oryginalnej funkcji (po prologu mov edi,edi)
lpOrgSetWindowTextA dd 0
; domyslny skok do okna NOP-ow
cHotPatchJmps db 0EBh,0F9h
; instrukcja call _hook (E9 xx xx xx xx)
cHotPatchCall db 0E9h
dwHotPatchRel dd 0
szHookTest db 'secnews.pl',0
.code
align 4
_hook_SetWindowTextA proc uses esi edi ebx, hWnd:dword, lpString:dword
; podmien parametr lpString na szHookTest i wykonaj
; oryginalna funkcje
; push lpString
push offset szHookTest
push hWnd
call lpOrgSetWindowTextA
ret
_hook_SetWindowTextA endp
align 4
_make_hook proc uses esi edi ebx, hProcess:dword, lpszLib:dword, lpszProc:dword, lpOrgPtr:dword, lpNewProc:dword
; sprawdz czy podana biblioteka jest dostepna
push lpszLib
call GetModuleHandleA
test eax,eax
je _make_hook_exit
; pobierz adres procedury, na ktora chcemy zalozyc hooka
push lpszProc
push eax
call GetProcAddress
test eax,eax
je _make_hook_exit
; czy pierwsze 2 bajty odpowiadaja instrukcji mov edi,edi
cmp word ptr[eax],0FF8Bh
jne _make_hook_exit
; zapisz wskaznik do kodu procedury (po prologu hotpatcha)
add eax,2
mov edx,lpOrgPtr
mov dword ptr[edx],eax
; wstaw krotki skok do serii nop-ow
push offset dwWritten
push 2
push offset cHotPatchJmps
push edi
push hProcess
call WriteProcessMemory
; procka docelowa
mov edx,lpNewProc
; budujemy instrukcje call _hook
; zrodlo, gdzie bedzie instrukcja call = okno nopow
lea eax,[edi-5]
; relatywny adres calla
; = cel - zrodlo - 5 (rozmiar instrukcji call)
sub edx,eax
sub edx,5
mov dwHotPatchRel,edx
; zapisz instrukcje call wskazujaca na naszego hooka
push offset dwWritten
push 5
push offset cHotPatchCall
push eax
push hProcess
call WriteProcessMemory
_make_hook_exit:
ret
_make_hook endp
align 4
_test_hooks proc uses esi edi ebx
; id naszego procesu
call GetCurrentProcessId
; otworz nasz wlasny proces
push eax
push 1
push PROCESS_ALL_ACCESS
call OpenProcess
test eax,eax
je _exit
mov ebx,eax
; ustaw hooki
mov edi,offset _make_hook
push offset _hook_SetWindowTextA ; hook proc
push offset lpOrgSetWindowTextA ; &lpOrgProc
push offset szSetWindowTextA ; szApiName
push offset szLibUser ; szLibName
push ebx ; hProcess
call edi ;_make_hook
_exit:
ret
_test_hooks endp
Update
Raymond Chen rzucił nieco informacji na temat hot patchingu:
http://blogs.msdn.com/b/oldnewthing/archive/2013/01/02/10381672.aspx