API Hooking : Hot Patching
Il y a peu j’écrivais un article dans lequel j’expliquais très brièvement le principe du Hot Patching et en ayant voulu aller trop vite je me suis trompé quant à certains aspects de cette technique. Alors je reprend tout cela et vous propose un article très bref pour vous expliquer le principe.
L’API Hooking consiste à injecter une dll dans un processus qui va modifier quelque peu celui-ci pour rediriger une fonction ou API ciblée vers une fonction contenue dans la dll elle même.En ce qui concerne l’injection de Dll je vous renvois à un article que j’avais sur mon ancien blog ainsi qu’à un article de JoE fort intéressant qui présente plusieurs méthodes : Injection de Dll dans un processus & Inject your DLL.
Il existe différente techniques pour hooker une API à savoir le Hot patching, l’Inline hooking et l’IAT patching. Aujourd’hui je ne vous parlerez que de la première technique mais je ne tarderai pas à vous présenter les deux autres.
.
Hot Patching
.
Des trois techniques évoquées, je pense que c’est la moins efficace du fait qu’elle requiert certaines conditions. En effet prenons par exemple l’API OutputDebugStringA dont voici le disass :
CPU Disasm Address Hex dump Command Comments 762C169D 90 NOP 762C169E 90 NOP 762C169F 90 NOP 762C16A0 90 NOP 762C16A1 90 NOP 762C16A2 8BFF MOV EDI,EDI 762C16A4 55 PUSH EBP 762C16A5 8BEC MOV EBP,ESP 762C16A7 5D POP EBP 762C16A8 ^ EB ED JMP SHORT 762C16AA B8 340000C0 MOV EAX,C0000034 762C16AF E9 B2540000 JMP 762C6B66 762C16B4 68 88020000 PUSH 288 762C16B9 53 PUSH EBX 762C16BA 56 PUSH ESI 762C16BB E8 FDDC0000 CALL ; Jump to ntdll.memset 762C16C0 83C4 0C ADD ESP,0C 762C16C3 E9 A1590000 JMP 762C7069 762C16C8 64:A1 18000000 MOV EAX,DWORD PTR FS:[18] 762C16CE 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30] 762C16D1 68 A8020000 PUSH 2A8 762C16D6 57 PUSH EDI 762C16D7 FF70 18 PUSH DWORD PTR DS:[EAX+18] 762C16DA FFD3 CALL EBX 762C16DC 8985 6CFEFFFF MOV DWORD PTR SS:[EBP-194],EAX 762C16E2 3BC7 CMP EAX,EDI 762C16E4 0F84 15CF0300 JE 762FE5FF 762C16EA 50 PUSH EAX 762C16EB E8 16000000 CALL 762C1706 762C16F0 FFB5 6CFEFFFF PUSH DWORD PTR SS:[EBP-194] 762C16F6 56 PUSH ESI 762C16F7 E8 09540000 CALL 762C6B05 762C16FC E9 30580000 JMP 762C6F31
Bien, j’attire votre attention sur le fait que 5 instructions NOPs précède le code de la fonction qui débute en 0×762C16A2. 5 NOPs c’est-à-dire 5 octets qui n’ont aucune utilité et que nous pourrons donc utiliser comme nous le souhaitons. De plus la fonction débute par l’instruction MOV EDI, EDI, voici encore une opération inutile. Placer le contenu du registre EDI dans EDI lui-même n’a aucun sens ! Maintenant regardons la taille de cette instruction : elle fait précisément 2 octets. Alors c’est maintenant que nous allons agir. Notre but serait de rediriger cette fonction vers une autre qui serait notre. Avec un JMP par exemple. Seulement nous ne pouvons pas réécrire les 2 octets de MOV EDI, EDI avec un JMP FAR car cette instruction requiert 5 octets. Cependant vous l’aurais compris nous pouvons remplacer les 5 NOPs par un saut long (JMP FAR) vers notre fonction. Ainsi en remplaçant MOV EDI, EDI par un simple JMP SHORT (saut court) qui cette fois-ci de requiert que 2 octets nous pourrions rediriger la fonction vers le saut long et ensuite sauter sur notre fonction.
Pour éclaircir mes idées voici un schéma :
Et voici le code qui me permet de faire cette manipulation :
En combinant l’injection de Dll et cette technique vous pouvez désormais hooker bon nombre d’APIs.
Enfin si vous voulez un exemple je vous propose de consulter le code de mon implémentation de la protection SEHOP : Implementing SEHOP
Je détourne les fonctions RtlDispatchException() et CreateThread() via cette technqiue.
Je vous laisse tout de même ma fonction de Hot Patching : HotPatching.c
Je terminerai en évoquant un article rédigé par 0vercl0k à ce sujet, article que nous avions publiés ensemble avec un autre de ma part disponible ici ou ici