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


Calendar

octobre 2021
L Ma Me J V S D
« fév    
 123
45678910
11121314151617
18192021222324
25262728293031

Most Recent Posts