Là encore on utilisera LordPE.
Mais avant toute chose, il faut faire en sorte que le dump se fasse à l'OEP et non à partir de n'importe quel endroit du code (ce qui en soit est très important, sinon certaines fonctions seront déjà initialisées au moment de la création du dump et elles se protégeront en écriture).
Tout d'abord, un petit cours sur la manière dont se présente la compression par UPX dans le code :
Ouvrez UPXUnpackme dans olly. Vous pouvez voir :

Et plus bas :

Un programme compressé par upx comportera toujours une partie de code similaire à ce que vous voyez ci-dessus, et si vous regardez bien, en 0041AB4F il y a un jump, juste en dessous du popad.
Ce jmp en l'occurrence nous amène directement sur l'OEP d'origine... rien de plus simple. (C'est pour cette raison que je vous disais tout à l'heure que l'étape de recherche de l'OEP au préalable aurait très bien pu être omise :)).
Maintenant voici ma méthode pour faire le dump :
Posez un breakpoint (F2) sur le fameux JMP OEP en 0041AB4F puis faites F9 pour lancer le processus.
Refaites F2 sur cette même ligne pour enlever le breakpoint puis F8, ce qui aura pour effet de vous jumper directement sur l'OEP.
Il va falloir faire tourner le prog en boucle si on veut pouvoir avoir le temps de dumper la copie en mémoire.
Pour se faire, on va lui dire d'executer une boucle infinie sur l'OEP : Faites Clique-Droit -> Binary -> Edit (ou ctrl+E pour les adeptes des raccourcis clavier) sur la ligne de l'OEP et vous aurez une fenêtre similaire à celle ci :
(Decochez "Keep size" s'il ne l'est pas chez vous.)
Il va falloir changer les bytes d'origine (55 et 8B de la ligne du dessous) par un jmp eip (EBFE en hexadecimal), et vous devriez voir dans ollydbg :

Si c'est le cas, appuyez sur F9 afin de poursuivre le processus et à partir de là n'attendez pas trop si vous ne voulez pas vous retrouver saturé en mémoire :p (je vous rappelle que là unpackme1.exe jump de manière infinie sur l'OEP ;)).
Ouvrez LordPE, cliquez-droit dans la fenêtre des processus actifs (Task) puis cliquez sur Refresh (si LordPE était déjà ouvert avant).
Cherchez alors votre unpackme dans cette même fenêtre.
Une fois que vous l'avez, cliquez-droit sur son chemin de destination et sélectionnez Dump full en vous étant assurés que dans Options "Full Dump : paste header from disk" et "Full Dump : fix header" étaient bien cochés.
Enregistrez le dump.
Faites clique-droit de nouveau sur le chemin de destination d'unpackme1.exe puis Burn process, afin de le "killer" pour qu'il ne tourne plus en boucle.
Si on veut pouvoir voir du code et des String Data References, ainsi que pouvoir écrire dans la section qui contient l'OEP, il va falloir changer la valeur de flags attribuée à cette section en E00000E0 (Characteristics Flags = CODE, INITIALIZED_DATA, UNINITIALIZED_DATA, MEM_EXECUTE, MEM_READ et MEM_WRITE).
Mais quelle est cette section qui contient l'OEP ?
Et bien c'est tout simple, c'est celle qui commence avant l'entrypoint et qui est le plus proche de celui-ci. Notre OEP = 00008998, UPX0 a pour Voffset 1000 et UPX1 10000, ça sera donc UPX0.
Donc cliquez sur Sections après avoir sélectionné PE Editor, cliquez-droit sur UPX0 puis "Edit Section Header".
Vous obtiendrez :
Dans Flags, à la place de E0000080, mettez E00000E0, puis OK.
Profitez-en aussi pour changer l'ancien OEP par le bon, autrement dit dans PE Editor, dans le champ EntryPoint changez le 0001AA00 par 00008998 puis validez.
A ce niveau là, votre dump n'est pas encore fonctionnel et si vous l'ouvrez sous windasm vous .
D'ailleurs, ouvrons-le sous windasm :
On remarque que le dump a été fait avec les fameux bytes qui font jumper en boucle sur l'OEP. Il va donc falloir changer ça aussi, remettre les bytes d'origine (558B) à la place de EBFE sinon vous aurez un dump fonctionnel tout à l'heure mais qui tournera en rond, qui ne s'executera pas :p
Je passe volontairement l'explication de la modification de ces bytes sous éditeur hexadecimal, j'estime que si vous lisez ce tutorial, vous êtes en mesure d'utiliser un editeur hexadecimal sans trop de difficultés (en cas de soucis, vous pourrez toujours me mailer).
Ceci dit un autre problème se pose :
- Nous n'avons pas de String Data References (!!)
- Au desassemblage on ne break pas sur l'entrypoint
Et celà bien qu'on ait fait nos modifications !
Et c'est là que nous allons parler du détail important que j'avais énoncé en introduction de ce tutorial :).
En fait, le problème vient de la valeur de la BaseOfCode.
En effet, nous avions vu plus haut qu'elle était égale à 00010000. Littéralement, BaseOfCode signifie "la base du code" donc on en déduit qu'il doit s'agir du virtual offset à partir duquel le code est considéré comme s'initiant.
Après packing l'entrypoint était égal à 0001AA00 ( > à 10000 ) donc il est bien reconnu comme étant présent dans le code.
Or, après unpacking notre OEP prend pour valeur 00008998 ( < 10000 ) et là si on ne modifie pas la valeur de BaseOfCode, notre OEP est considéré comme étant en dehors du code.
Mais attention, on peut être tenté de se dire que si on modifie la BaseofCode en lui attribuant 8000 comme valeur tout rentrera dans l'ordre, mais là encore on se tromperait : notre OEP serait bien reconnu comme faisant partie du code cette fois, mais notre section UPX0 serait toujours considérée comme étant compressée.
Nos seules possibilités de modification de la BaseOfCode sont de lui donner pour valeur le Voffset d'une des sections. UPX0 ayant pour Virtual Offset 1000, on va donc faire passer avec LordPe la valeur de BaseOfCode de 10000 à 1000 (merci SeVeN pour avoir pris la peine de m'aider sur ce point ;)).
Vous reouvrez UPXUnpackme.exe (fichier original) si vous l'avez fermé, et vous executez Imprec.
Vous attachez l'exe, et vous pouvez constater que les modules sont chargés comme en demontre la fenêtre de logs.
Dans IAT Info Need, maintenant que vous avez le veritable OEP (cf ci-dessus) = 00408998 - ImageBase = 00008998, vous allez renseigner le champ adéquat puis cliquer sur "IAT AutoSearch" :
Apparemment ImpRec a l'air d'avoir trouvé quelque chose, ce qui signifie que notre OEP est correct, mais aussi notre RVA et sa taille (size).
Si c'est le cas aussi chez vous, cliquez sur "Get Imports", ce qui aura pour fonction d'aller chercher tous les imports (dll) du prog packé :
Dans Imported Functions Found, apparemment il n'y a pas d'erreur (vous avez toujours la possibilité de vérifier dans la fenêtre de logs) : en effet, à coté de chaque fonction importée un "Yes" apparaît.
Il est alors temps de faire un fix de notre dump préalablement préparé : il suffit pour celà de cliquer sur "Fix Dump" et d'aller chercher votre dump :
Dans la fenêtre de logs, vous voyez que tout s'est bien passé, il ne reste plus qu'à tester.
Pour se faire, executez simplement
votre dump. Il doit être fonctionnel et s'executer sans aucune erreur :
Apparemment tout s'est très bien passé :)
On vérifie que les Data String Reference ainsi que les Imports sont bien présents dans Ollydbg pour finir, et apparemment tout est correct.
Encore une fois j'espère avoir été suffisamment claire :)
GREETZ :
A toute la team FFF, ainsi qu'à la ShmeitCorp,
Special greetz à SeVeN, jB, Darus, Kephren, Le_MaLaDe, Netix, The_Analyst et Presage pour l'aide et la motivation qu'ils m'apportent et les nuits qu'on tue ensemble pour certains.
A tous les auteurs de tuts en règle générale, ainsi qu'à tous les "anciens" que je n'aurai pas eu la chance de connaître mais que je tenais à remercier pour tout ce qu'ils me permettent d'apprendre de part leurs écrits.
|