|
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 ;-)
|
|
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.
|
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...
|
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 modifierOn remet l'EIP à sa valeur originale et on laisse (F5) le proggie tourner tout seul. Ensuite, on clique sur Dump dans WDump95.
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.
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.
|
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...)
|
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