Advanced Registry Tracker : Méthode Dumping par Artex

Ce compte-rendu doit être considéré comme un addendum à l'excellent compte-rendu de Christal&Psyché que vous pouvez trouver sur notre page : http://www.citeweb.net/atpteam
Je vais être assez succint car je pars du principe que vous connaissez la structure du PE (sinon, allez sur le site de Wotsit ou bien attendez que nous mettions à votre disposition le livre de Matt Pietrek en .pdf sur notre page) et que vous avez quelques expériences en cette matière délicate mais passionnante... Vous pourriez par exemple lire le compte-rendu sur Fruityloops 1.4 ;-)
 
 
Outils nécessaires



- Soft-ice
- WDump95 (ou tout autre Dumpper)
- Hview
- UltraEdit
- ProcDump
Tous ces outils sont facilements trouvables sur le Web, et en particulier sur la Page d'Iczelion (cf notre page de liens pour l'URL de ce site).
 
 
Etape 1 : Collecte d'informations sur le programme

On commence par ProcDump qui nous donne les informations suivantes :

1- EntryPoint : 000499B9
2- Image Base : 00400000
3- Size Of Image : 000E1000

Que constate-t-on ? Que l'Image Base est très loin du EntryPoint RVA ce qui confirme ce que l'on subodorait : c'est crypté/packé.

Si nous allons dans la partie "Sections" de ProcDump on remarque une chose intéressante : les sections BSS, .tls et .reloc ont une RawSize de 0 et leur RawOffset est le même que celui de la section qui les suit.
Qu'est ce que cela veut dire ? Tout simplement que ce sont des sections qui n'existent qu'en mémoire (ie purement virtuelles) et pas sur le fichier du disque dur. Cela aura une importance au moment du Dumping.
 
 
Etape 2 : Préparation du Dump


Ensuite il faut faire en sorte que le Loader de SoftIce s'arrête au niveau de l'EntryPoint. Pour cela, j'ai changé les attributs de la section CODE en plaçant C0000020 à la place de C0000040... Pour plus de détails, reporter vous au compte rendu de Psyché. On aurait aussi pu laisser une première fois le programme se charger, revenir dessus pour être dans son contexte de mémoire et mettre manuellement un Breakpoint sur l'EntryPoint.

Maintenant, nous allons utiliser notre Memory-Dumper : j'utilise WDump95 (pour l'obtenir, cf la page de liens pour aller vers le site d'Iczelion). Je crée une Memory Mapped File de 918 KO.

Question : pourquoi 918 KO ?

Cela correspond à la Size Of Image - 1000 ie E1000 - 1000 = E0000 qui en décimal donne 917504 octets donc 918 KO.

Nouvelle question : pourquoi soustrais-je 1000 ?

Tout simplement car je ne vais pas Dumpper le PE Header qui de toutes les manières n'est pas "chargé" en mémoire. Cela explique aussi pourquoi plus loin nous serons obligé de copier le PE Header du programme original...
 
 
Etape 3 : Le Dump en lui même


SoftIce :

Si vous avez bien fait les choses, le Loader devrait s'arrêter tout de suite sur l'EntryPoint, c'est à dire en 4499B9. Ensuite, vous pouvez tracer à la main et constater que l'on voit successivement trois routines qui se ressemblent comme deux gouttes d'eau et qui correspondent aux trois routines servant à décompacter.

Pourquoi trois routines de suite ?

Tout simplement parceque les auteurs de ART on jugé bon de faire passer leur programme trois fois de suite par la moulinette, pensant soit que cela compacterait un peu mieux le programme (je doute que cela marche) ou bien que cela rende plus difficile la démarche des crackers (je doute que cela marche) et des outils de cracking comme les Unpackers (cela peut compliquer la tache avec ProcDump et mettre en échec un simple décompacteur d'ASPack).

Résumé : on a trois routines, trois fois la même et on arrive alors au JUMP EAX crucial, le dernier, qui se trouve en 4DE04F et qui nous renvoie vers le véritable EntryPoint du programme, c'est à dire  485E98.

Maintenant, sachant tout cela, nous pouvons effectuer notre Dump à proprement parler.
Attention : Il faut effectuer le dump juste après le deuxième call (en 4DE034) car le troisième call efface le debut de l'Import Table... Et alors il faudrait la refaire à la main (ce qui n'est pas notre but ici.) On vérifie tout d'abord que les sections sont bien décodées, et pour la section .idata (qui commence en 4BE000.) vous devriez voir apparaitre Kernel32.dll à partir de 4BE800 avec ensuite toutes sortes de fonctions importées dans cette dll. Parfait, tout semble OK.

Le Dump :

Comme toujours, je vous conseille de faire la recopie à la main car toutes les pages ne sont pas nécessairement chargées en mémoire (ie la commande m ne fonctionnera pas car Soft-ice n'est pas capable de forcer les pages en mémoire). On doit pour cela trouver un endroit pour écrire notre petite routine qui effectuera la sale besogne. Prenons pas exemple 488D00 en prenant bien soins de noter quelque part l'EIP pour que nous puissions revenir au programme une fois notre routine terminée.
- r eip 488D00 ; on pointe sur le début de notre routine
- a eip ; on écrit notre routine

pushad ; on sauvegarde tous les registres car on va les modifier
mov esi, 00401000 ; on va copier les octets qui commencent ici
mov edi, ******** ; adresse que vous donne votre Memory Dumper
mov ecx, E0000 ; on veut dumpper cette longeur
repe movsb ; on recopie
popad ; on restaure les registres.
On remet l'EIP à sa valeur originale et on laisse (F5) le proggie tourner tout seul. Ensuite, on clique sur Dump dans WDump95.

Qu'avons nous fait ?

Nous avons un fichier qui contient ce que contenait la mémoire auparavant et qui correspond à l'ensemble du programme, sauf son PE Header.
 
 
Etape 4 : Rendre executable notre Dump


C'est la partie la plus difficile et la plus pénible car il y a pas mal de manipulations.

UltraEdit :

De la même manière vous pourrez trouver cet excellent outil sur la page D'Iczelion (cf Page de liens).

Que nous reste-t-il à faire pour que cela fonctionne ?

1- Il faut que l'on colle un PE Header à notre programme car pour le moment il n'en a pas.
2- Il faut que l'on s'occupe de faire en sorte que le programme puisse tourner : il va falloir s'occuper de la section .idata et des section BSS, .tls et .reloc (vous vous souvenez, celles qui avaient un RawSize de 0)

1- Ajout d'un PE Header au fichier Dump :
On utilise donc UltraEdit pour cela : on ouvre ART.exe (le programme original) et aussi notre fichier Dump. On va ensuite sélectionner dans l'original le PE Header et en faire un copie : on prend donc tout depuis le début jusqu'à l'Offset 400h non compris. On le colle à notre fichier Dump. A ce stade, si vous essayez d'exécuter le programme, cela ne fonctionnera pas, à juste titre car il faut

2- Modifier les sections :
5 choses à faire :

2.1- Modifier la taile des sections :
Il faut tout d'abord faire en sorte que PhySize = VirtSize. On modifie donc, section par section, la taille physique pour que celle ci soit égale à la taille virtuelle.

Pourquoi ?

Tout simplement car on aura sur le disque exactement ce que l'on avait en mémoire donc les tailles physiques (sur le disque) et virtuelles (en mémoire) sont les mêmes.

Attention : on ne fera pas cette modification pour toutes les sections : les section BSS, .tls et .reloc sont des sections purements virtuelles et donc, on se permettra de mettre leur RawOffset et leur RawSize à 0. Avant de faire cela, prendre note de la valeur des Offsets et des Sizes car on va en avoir besoins.

2.2- Modifier les Offsets :
Pour la même raison qu'auparavant, les RVA sont bonnes (car elles correspondent à la mémoire) mais il faudra changer les Offsets des sections (car elles correspondent au fichier sur le disque dur.)
Je ne vais pas détailler comment faire pour toutes les sections, cela serait trop fastidieux mais je dirais quand même qu'il faut ajouter la taille du segment 1 à l'Offset du segment 1 pour trouver l'Offset du segment 2. Exceptions : les sections BSS, .tls et .reloc auront un RawOffset et un RawSize de 0 (car elles sont purement virtuelles.)

Vous devriez obtenir quelquechose du style :
 
 

Section RawSize RawOffset
CODE 00085000 00000400
DATA 00003000 00085400
BSS 00000000 00000000
.idata 00003000 00088400
.tls 00000000 00000000
.rdata 00001000 0008B400
.reloc 00000000 00000000
.rsc 00011000 0008C400
.data 00001000 0009D400
.data 00001000 0009E400
.data 00001000 0009F400

 

2.3- Les sections BSS, .tls et .reloc :
Nous avons dumppé en mémoire ce qui veut dire que l'on a dumppé aussi les sections BSS, .tls et .reloc et je vous rappelle qu'elles sont purement virtuelles. Il va donc falloir les éliminer de l'exécutable (ici notre dump auquel on a "collé" un PE Header) si l'on veut que le programme ait eu chance de fonctionner correctement.

La section BSS :
nous irons donc à l'Offset 88400 et nous couperons sur une longueur de 35000 soit jusqu'à 88400 + 35000 = BD400.

La section .tls :
nous irons à l'Offset 8B400 et nous couperons d'une longueur de 1000 soit jusqu'à 8B400 + 1000 = 8C400.

La section .reloc :
On supprimera entre 8C400 et 96400 (8C400 + A000.)

2.4- L'Import Table :
Si vous utilisez Hview pour voir un peu ce que cela donne, vous verrez bien qu'il y a encore un problème au niveau de l'import table. Il faut en effet modifier celle-ci, toujours via ProcDump (bouton Directory) :
Nous aurons :
RVA : 000BE000
Size : 00000140

La RVA est celle de la section... rien de bien compliqué la-dessous. En ce qui concerne la taille, il faut savoir que l'Import Table est constitué d'une suite "d'enregistrements" qui sont chacun une suite de 20 octets (14 en hexa.) Cette suite se termine par un "enregistrement" dont toutes les valeurs sont nulles... Avec un peu d'entrainement, on reconnait tout de suite (on dirait un peu des escalators sous Hview...) Cela nous donne une taille de 140 en hexa (qui est bien divisible par 14 en hexa.)

2.5- L'EntryPoint :
On se rappelle que celui-ci est donné par la valeur du dernier jump eax de la routine d'ASPack... On a donc un EntryPoint de 00085E98.
 

Voilà, ART 1.0 est maintenant dépacké et fonctionne correctement. Il est donc maintenant déassemblable par Wdasm... Il ne vous reste plus qu'à le cracker de manière habituelle (ce qui ne sera pas trop difficile ici...)
 
 
Notes Finales

Voila, c'est la fin du compte-rendu... Je me rends compte qu'il est loin d'être aussi long que celui de Psyché...
J'espère que vous aurez pu apprendre quelquechose... La méthode Dumping est assez complexe au début (et fastidieuse aussi) mais elle a plusieurs avantages dont notamment de permettre de bien comprendre ce que font des utilitaires comme ProcDump et aussi de vous permettre de vous en sortir le jour où vous ne réussissez pas à écrire un script avec ProcDump...

Autre chose : on pourrait, si on le désirait, rendre le programme un peu plus propre en mettant à leur vraie valeur les tailles des sections (c'est assez pénible car il faut recalculer tous les Offsets... et en fait pas vraiment nécessaire sauf si vraiment on veut gagner quelques KO.) On pourrait aussi se débarasser de diverses sections, comme les .data à la fin. Attention, ASPack fait des modifications au niveau des ressources... notamment en changeant les adresses de certaines d'entre-elles... il faut donc bien faire attention avant de se débarrasser de la dernière des sections .data... Enfin, ici on touche le domaine des puristes...

Comme toujours, si vous avez des questions, commentaires ou même des propositions de logiciels ayant une protection sympa... envoyez moi un petit email.

Octobre 99
artex@nighton.com
ou
artex@caramail.com