Last update: 29/05/2007


EtatStoppé
Versionbeta
Mise à jour01/08/2004

Projet Process Explorer
"PROCESS EXPLORER" est un outil permettant d'avoir un premier aperçu sur le fonctionnement d'un programme et affichant pour chaque appel de fonction dans une dll : le nom de la fonction, l'adresse de retour et la valeur des paramètres.
Ce projet a été (temporairement ?) arrêté au stade de beta.

Origine du projet
L'utilité du reverse engineering n'est plus à prouver. Les derniers sceptiques pourront se reporter au numéro 14 de MISC, consacré en grande partie à ce sujet. Pour étudier le fonctionnement précis d'une partie d'un exécutable, par exemple l'implémentation d’un algorithme de cryptage, il est évident que vous allez devoir plonger au coeur du code assembleur. Il existe alors de nombreux outils, soit des désassembleurs (notamment IDA), soit des débuggeurs.
Cependant, il se peut que vous n'ayez pas besoin de ce niveau de détail, ou que vous souhaitiez commencer par avoir une vue générale du fonctionnement d'un exécutable. Par exemple, il serait utile de savoir quelles fonctions exportées par les DLL sont utilisées et avec quels paramètres. C'est là qu'intervient Process Explorer.
Principe
Process Explorer n'est pas un nouveau débugger ou un nouveau désasembleur. C'est plutôt un nouveau type d'outil. Le principe est simple : Il "hook" toutes les fonctions que vous désirez dans un processus, puis logge dans un fichier la valeur des paramètres avant et après l'appel, ainsi que l'adresse de retour et le code de retour.
Fonctionnement
Les différentes méthodes de hooking
Le hooking consiste à modifier en mémoire des portions de code/données afin de détourner le flot d'exécution lors de l'appel de fonctions vers un code qui aura alors l'opportunité d'effectuer un certain nombre d'action avant de retransmettre le contrôle à la fonction appelée à l'origine.
Plusieurs techniques permettent de réaliser cela. En voici une liste non exhaustive :
Modification de l'import table
Cette technique consiste à modifier l'IAT pour que les pointeurs de fonctions redirigent l'exécution vers le code désiré.
Elle présente l'avantage d'être très stable, cependant elle ne fournie pas des résultats exhaustifs: en effet, elle n'intercepte pas les fonctions des Dlls chargées dynamiquement. Par exemple IE charge quasiment toutes ses librairies via LoadLibrary.
Patch du header de fonction avec restauration
Une autre technique consiste à patcher le header des fonctions avec un jmp vers notre code. A la fin de ce code, le header est restauré, puis l'exécution saute au début de la fonction. A la fin de la fonction, l'exécution doit de nouveau être détournée pour remettre le jmp au début de la fonction.
Cette technique présente l'avantage d'être relativement stable et surtout de pouvoir traiter toutes les fonctions. Par contre les opérations de copies risquent de provoquer des instabilités dans un environnement multi-threadé. De plus durant l'exécution de la fonction, le header n'est plus patché, donc des appels peuvent ne pas être tracés.
Patch du header de fonction sans restauration
Encore une autre technique consiste à patcher le header des fonctions avec un jmp vers notre code, mais cette fois le header ne sera jamais restauré: A la fin du code de hook, il faut alors exécuter une copie du header, puis sauter après le jump.
Cette technique est également relativement stable, surtout si vous patchez les headers lorsque le processus est suspendu. Après cela, il n'y a plus de modifications d'instructions, donc cette méthode est bien adaptée aux environnements multi-threadé.
Mais le gros inconvénient est que la taille de header à sauver n'est maintenant plus 5 octets (taille du jmp), mais un alignement d'instruction supérieur à 5 octets. Il faut donc commencer par déterminer les tailles des instructions du header. Le schéma plus bas résume ce principe: En copiant juste 5 octets, vous ne sauverez qu'une partie de l'instruction 2 et l'exécution plantera.
Voici les étapes à effectuer:
  • Déterminer la taille de l'instruction 1, la comparer la celle du JMP: Elle est inférieur, on continue
  • Déterminer la taille de l'instruction 2 additionnée à celle de l'instruction 1, la comparer la celle du JMP: Elle supérieure, on sauve donc ce nombre d'octets.
+------------+            +------------+          +------------+
|            |            |            |          |            |
|   Inst1    |            |            |          |            |
|            |      |     |    JMP     |          |    JMP     |
+------------+    --+--   |            |   ----   |            |
|            |      |     |            |   ----   |            |
|   Inst2    |            +------------+          +------------+
|            |                                    |    ???     |
+------------+                                    +------------+ <- adresse de retour du saut
|   Inst3    |                                    |   Inst3    |
+------------+                                    +------------+
		
Le hooking dans Process Explorer
Process Explorer utilise cette troisième technique pour le hooking. Le principal problème est donc d'avoir un code déterminant la taille des instructions. Le "moteur" utilisé actuellement pour ce calcul est une version modifiée de "detours" et permet de déterminer la taille de 90% des instructions. Il peut donc patcher la grande majorité des fonctions, mais pas toutes, ce qui limite considérablement sa portée. J'ai découvert depuis le moteur LDE32 développé par z0mbie qui est d'une efficacité assez impressionnante.
Bilan sur Process Explorer
Process Explorer est actuellement capable de hooker 90% de fonctions. Il faut noter qu'il est relativement stable si la configuration à hooker reste raisonnable: Dans le cas de ZoneAlarm (voir doc), le hook de toutes les fonctions de advapi32.dll ou crypt32.dll ne pose pas de problème. Celui de kernel32.dll ou user32.dll risque planter l'application. Il vous faut alors choisir les fonctions que vous souhaiter analyser dans ces librairies.

Contrairement aux apparences, Process Explorer est un projet assez délicat: il ne faut pas oublier qu'il patche à la volée du code de manière automatique. Il est donc assez difficile d'obtenir un outil qui ne plante pas les applications. De plus le debuggage se fait systématiquement sur de l'assembleur généré puisque le code est injecté dans un processus distant. C'est donc un projet d'envergure qu’il est difficile de mener seul.

Au delà de l'outil, l'objectif de cette beta est donc de montrer l'intérêt que peut avoir ce type d'outil: Il permet d’avoir facilement et rapidement une idée du fonctionnement d'un programme, sans se plonger dans des milliers de lignes d'assembleur. Il permet également d'apprendre facilement de nouvelles méthodes de programmation en analysant des programmes existants
Un tel outil, plus stable, développé et maintenu par une réelle équipe permettrait une analyse et une exploration de Windows et ses applications extrêmement intéressantes.
Ressources
L'archive contenant les exécutables et la doc : PROCESS EXPLORER
La documentation en ligne: PROCESS EXPLORER DOCUMENTATION
Screenshots (cliquer pour élargir)
Les screenshots suivants ont été faits pendant l'analyse de ZoneAlarm:
Une remarque/un bug ?
Pour l'instant, ce projet est arrêté. Suite à de recentes recherches, il est cependant possible que je reprenne son développement. N'hésitez donc pas à me contacter si vous avez des questions/remarques: Benjamin CAILLAT