Inline Hook
février 10th, 2007 at 04:47 admin
Yop, après une semaine d’idlage larvaire intensif je me décide à poster quelque chose. Une chose qu’on aime faire lorsque qu’on veut faire mumuse avec le système est de détourner le fonctionnement normal de ses fonctions, pour cela on utilise un « hook », le principe est simple on modifie légèrement le programme pour qu’il appel notre fonction au lieu d’appeler la fonction original. Le plus souvent on détourne une fonction afin de modifier ses résultats, ainsi il est possible de faire croire ce qu’on veut au programme :}
Il existe en gros 2 méthodes pour hooker, la première consiste à modifier la table des imports qui contient les adresses des différentes fonctions importées des DLL. Par exemple si l’on désire détourner la fonction GetModuleHandle(), on modifie dans l’IAT (Import Address Table) le pointeur sur cette fonction par l’adresse de la notre. Evidemment niveau discrétion c’est pas trop ca, il suffit de scanner les entrées de l’IAT et de les comparer aux adresses des vrai fonctions pour détecter se type de hook.
D’ou l’invention d’une seconde méthode, l’inline hook, cette fois plus question de toucher à l’IAT, on va directement modifier le prologue de la fonction. En fait l’on place au début de la fonction un jump sur la notre, le problème c’est qu’on écrase ses premiers bytes et si l’on veut la réutiliser ca pose problème :p
Pour ne pas déteriorer la fonction de départ on sauvegarde ses premieres instructions suivit d’un petit jump, je m’explique, voulant exécuter toutes les instructions de la fonction hooké on doit commencer par appeler ses premiers bytes puis le reste qui n’a pas bougé on l’appel en jumpant dessus, on obtient donc le schéma suivant:
{//buffer en mémoire [premiers bytes sauvegardés] [jump @begin] } {//fonction hookée [jump sur notre fonction] [@begin, instructions inchangées de la fonction hookée] }
On commence par call sur les premiers bytes saved, on les exécute, puis on jump sur la suite.
Reste encore un petit soucis, la taille d’un jmp en assembleur est des 5 octects, or sauvegarder les 5 premiers bytes de l’API hooké serait une erreur, en effet si par exemple on se retrouve avec 2 instrutions, 1 de 3 bytes et l’autre de 4 bytes, la seconde sera tronqué et lors du jump on exécutera n’importe quoi. La solution est d’utiliser un moteur qui calcul la taille des instructions oO, on calcul la taille des instructions jusqu’à trouver un bloc de taille supérieure ou égale à 5 octets. Si on doit copier 7 bytes alors les 5 premiers seront pour les jump et les 2 autres contiendront des nop (0×90).
Le mieux est évidemment de voir ce que ca donne, dans l’exemple suivant je hook l’api native NtOpenFile :
Avant le hook: 7C91DCFD > B8 74000000 MOV EAX,74 7C91DD02 BA 0003FE7F MOV EDX,7FFE0300 7C91DD07 FF12 CALL NEAR DWORD PTR DS:[EDX] 7C91DD09 C2 1800 RET 18 Après la hook : 7C91DCFD >- E9 374C6E93 JMP 10002939 7C91DD02 BA 0003FE7F MOV EDX,7FFE0300 7C91DD07 FF12 CALL NEAR DWORD PTR DS:[EDX] 7C91DD09 C2 1800 RET 18 A noter que le hasard veut que la première instruction fasse 5 octets ... On la retrouve sauvegardé ici, suivit du jump vers les suite des instructions 000A9518 B8 74000000 MOV EAX,74 000A951D - E9 E047877C JMP ntdll.7C91DD02
Now reste plus qu’a lancé cela dans la mémoire d’un process, pour cela on utilise une dll qui lors du DLL_PROCESS_ATTACH place le hook, et l’enlève lors du DLL_PROCESS_DETACH. Je ne reviens sur la méthode pour injecter une DLL, il y à assez de doc sur le net pour apprendre ça.
La fonction qui place le hook s’appelle, InstallInlineHook() elle prend 3 arguments :
-L’adresse de l’API à hooker
-L’adresse de notre fonction de substitution
-Un pointeur sur la zone mémoire qui contiendra les instructions sauvegardées.
Pour l’enlever on utilise RemoveInlineHook() avec comme paramètres:
-L’addresse de l’API hooké
-L’adresse des premières instructions sauvegardées
-La taille des instruction sauvegardées
Vous touverez dans les sources:
InlineHook.cpp : le moteur d’inline hook
ZDisasm.h et ZDisasm.C la moteur codé par Z0MBiE qui calcul la taille des instructions.
NtOpenFile_spy.cpp : la dll qui hook l’api native NtOpenFile et qui écrit dans c:\logfile.txt les noms des fichiers passés en paramètre.
Pour l’utiliser il faut d’abord injecter la dll dans le process choisit :
C:\\ProgHack\\c\\InlineHook>inject_dll notepad.exe c:\\proghack\\c\\InlineHook\\NtOpenFile_spy.dll [*]Ownage du processus: notepad.exe [*]Handle: 0x7f4 [*]CodeSize: 44 [*]Emplacement memoire: 0x3c0000 [*]Target injected
Après vous pouvez voir dans le fichier c:\logfile.txt les noms des fichers ouverts par le notepad.
Puis pour enlever le hook :
C:\ProgHack\c\InlineHook>unload_dll notepad.exe NtOpenFile_spy.dll
[*]Ownage du processus: notepad.exe [*]Handle: 0x7f4 [*]Target injected
Voilà j’espère que j’ai été clair, sinon n’hésitez pas à mes poser de questions
Tout est dispo ici:
http://ivanlef0u.fr/repo/InlineHook.rar
Enjoy :}
Entry Filed under: Non classé
2 Comments
1. Null | juillet 19th, 2010 at 18:39
Iop, super ta source, elle m’a été très utile!
Néanmoins, si je peux me permettre une amélioration, le cas où tu copierais un JMP n’est pas couvert. Vu que les adresses de destination sont relatives, ben ça merde tout :p.
Sinon, tu peux aussi simplifier sans utiliser de trampoline si tu tombes sur le cas d’une API qui a un prologue type 5 NOP/INT3 suivis d’un MOV EDI, EDI, en foutant un JMP SHORT -EBF9- sur le MOV EDI, EDI, et en mettant ton CALL à la place des 5 bytes au dessus.
J’ai fait un p’tit article là dessus, bien basé sur le tien, d’ailleurs
Du reste, super ton blog, vraiment intéressant! T’chaw!
2. API hooking sous Windows &hellip | avril 25th, 2012 at 17:14
[...] 1- Hooks inline : http://www.ivanlef0u.tuxfamily.org/?p=24 [...]
Trackback this post