Protection    VG CRYPT   Les Protections Renforcées
Outils    ProcDump et SoftIce    
Cible    Notepad.exe  

By Christal


VG CRYPT: comment écrire un script automatisé pour ProcDump

Je vous encourage vivement à lire les essais de TaMaMBoLo sur la rédaction de script pour ProcDump. Sans ses indications, je n'aurais sans doute jamais appris a en écrire à mon tour.

Rapide présentation:

This is a fairly simple PE encryptor I wrote up. I commented everything
; that is relavent to PE appendation or insertion, more so than I needed to
; even. The most interesting feature of this encryptor is that it attempts to
; find a location to insert itself between object virtual size and the next
; file alignment boundary, thus not changing the physical file size.

VG Crypt comme son nom l'indique, est un crypteur de donnés de 9 ko! Son objectif ne semble pas la protection en tant que tel, dans la mesure ou SoftIce rend la main sur l'Entry Point au lancement de l'application-cible si vous passez par le Symbol Loader, et Wdasm peut réaliser un désassemblage du programme, en fournissant des ressources (String Data References…).
A ceci prêt que les String Datas ne seront pas aussi complète dans la version cryptée, que dans l'application d'origine, et limitées à un certain nombre.
En fait on pourrait croire que l'auteur de ce crypteur à volontairement cherché à noyer le poisson, lisez la suite:

Pour trouver comment réaliser ce script pour ProcDump, j'ai crypté NotePad.exe, et j'ai contrôlé le bon fonctionnement du script avec Calc.exe.

Première approche:

Une fois crypté, Notepad est passé de 56 ko à 59 ko, soit une augmentation, grosso modo de 5 %

Avant cryptage

.text     00003E9C     00001000      00003E9C      00001000       60000020
.data     0000084C     00005000      00000298      00005000       C0000040
.idata    00000DE8     00006000      00000DE8      00006000       40000040
.rsrc     00006000     00007000      00005600      00007000       40000040
.reloc    00000A9C     0000D000      0000093C      0000D000       42000040

Après cryptage

.text     00003E9C     00001000      00003E9C      00001000       60000020
.data     0000084C     00005000      00000298      00005000       C0000040
.idata    00000DE8     00006000      00000DE8      00006000       40000040
.rsrc     00006000     00007000      00005600      00007000       40000040
.reloc    00000BF4     0000D000      00001000      0000D000       E0000060

Vous remarquerez que la doc de VG Crtpt ne ment pas, il n'y a pas de création de section supplémentaire, le Loader de VG Crypt s'est simplement glissé dans la section .reloc en augmentant sa taille de 158 octets pour pouvoir s'y loger, et la section .text a été modifiée pour la rendre Readable, et eXécutable, suivant le principe suivant:

   0x00000020 IMAGE_SCN_CNT_CODE 
   0x20000000 IMAGE_SCN_MEM_EXECUTE 
   0x40000000 IMAGE_SCN_MEM_READ 
-----------------------------------
   0x60000020 

Eventuellement si vous souhaitez la rendre Writeable, il faudrait faire:

       0x60000020
OR 0x80000000 IMAGE_SCN_MEM_WRITE 
-----------------------------------
       0xE0000020 

Bon, du coup, VG Crypt sera difficile a identifier, d'autant plus qu'il n'y a aucune "signature" de ce cryptage si vous en recherchez une avec un hexéditeur (pas de CopyRight, rien de rien…)
La seule manière de repérer un programme qui aura été crypté, sera lors du traçage avec F10 dans SoftIce, les portions de sections se codant et se décodant sous vos yeux.
Pour autant vous ne saurez pas à qui vous avez affaire, dans ce cas précis.
Pas souvent que l'auteur d'un bidule de ce genre soit aussi discret…


Prenons les problèmes dans l'ordre

Le Loader:

Crypté ou compressé, il doit toujours y avoir un moyen pour obtenir une version au plus proche du programme d'origine…

Commençons par repérer les sections non cryptées, elles feront obligatoirement partie du Loader.
Il y a certainement plusieurs solutions pour trouver où se termine une section clean (comprenez non cryptée ou compressée), mais l'une de celle que j'utilise me donne satisfaction quand l'exécutable à étudier n'est pas trop long: je fouille dans le programme avec un éditeur hexadécimal, à la recherche de zones où ne se trimballent pas des masses d'octets nuls.

0000DA60 FFB7 6467 FF36 0000 6467 8926 0000 8DB5 ..dg.6..dg.&....
0000DA70 4726 4000 8BFE B9CA 0000 008A A511 2740 G&@...........'@
0000DA80 00AC 32C4 FEC4 C0C4 0280 C490 AAE2 F2E9 ..2.............
0000DA90 CBFE FFFF 0000 0000 0000 0000 0000 0000 ................

Arrivé en 0000DA90 je (re)commence à trouver ces octets nuls (0000), et juste avant, un E9 CB FE FF FF qui me semble caractéristique d'un jmp long.
A l'aide de Hiew, une recherche sur cette chaîne va vous permettre d'en connaître l'adresse: 0040DA8F.

Voyons maintenant ce que va nous donner SoftIce. Via son Symbol Loader, vous allez charger l'application cryptée, et tracer doucement avec F10 depuis le point d'entrée: 0040D93C. En soit même cet Entry Point a de quoi mettre la puce à l'oreille, les points d'entrée des programmes honnêtes étant plutôt du genre 00401000…

Vous allez très rapidement arriver a l'adresse recherchée:

0177:0040DA7B  8AA511274000        MOV       AH,[EBP+00402711] > Chaîne à traiter
0177:0040DA81  AC                  LODSB               > charge EAX avec le contenu de DS:SI
0177:0040DA82  32C4                XOR       AL,AH     > ou logique entre AL(E8h) et AH
0177:0040DA84  FEC4                INC       AH        > ajoute 1 à AH
0177:0040DA86  C0C402              ROL       AH,02     > rotation à gauche de 2
0177:0040DA89  80C490              ADD       AH,90     > ajoute 90h à AH
0177:0040DA8C  AA                  STOSB               > transfère double mot par double mot 
                                                       > le contenu de EAX dans ES:DI
0177:0040DA8D  E2F2                LOOP      0040DA81  > et ce tant que CX est <> de 0 (boucle)
0177:0040DA8F  E9CBFEFFFF          JMP       0040D95F    (JUMP)  ici
0177:0040DA94  0000                ADD       [EAX],AL
0177:0040DA96  0000                ADD       [EAX],AL

Juste au dessus du Jmp 0040D95F, vous avez la routine de décryptage. J'avais eu l'occasion de lire un texte très intéressant sur le principe du cryptage, qui aurait permis de compléter cet essai. Hélas, je n'arrive pas à remettre la main dessus…
Mais je pense que les commentaires ont du vous permettre d'en appréhender le principe.

Donc en 0040DA8F, le Loader a fini de décrypter la seconde partie de celui ci, mais le programme d'origine est encore crypté. Pour le moment seul le loader est devenu clean (et vous verrez, pas pour longtemps…)
F10 pour continuer la ballade, et vous voici ici:

0177:0040D95F  E800000000          CALL      0040D964
0177:0040D964  8B9D05274000        MOV       EBX,[EBP+00402705]
0177:0040D96A  83C328              ADD       EBX,28
0177:0040D96D  58                  POP       EAX
0177:0040D96E  2BC3                SUB       EAX,EBX
0177:0040D970  89850D274000        MOV       [EBP+0040270D],EAX
0177:0040D976  CC                  INT       3
0177:0040D977  8DBD24264000        LEA       EDI,[EBP+00402624]
0177:0040D97D  B93B000000          MOV       ECX,0000003B
0177:0040D982  F3AA                REPZ STOSB
0177:0040D984  64678F060000        POP       DWORD PTR FS:[0000]
0177:0040D98A  5A                  POP       EDX
0177:0040D98B  8B850D274000        MOV       EAX,[EBP+0040270D]
0177:0040D991  018509274000        ADD       [EBP+00402709],EAX
0177:0040D997  61                  POPAD      > restauration
0177:0040D998  9D                  POPFD
0177:0040D999  8B9A09274000        MOV       EBX,[EDX+00402709]
0177:0040D99F  898A09274000        MOV       [EDX+00402709],ECX
0177:0040D9A5  FFE3                JMP       EBX
0177:0040D9A7  8DBDCD264000        LEA       EDI,[EBP+004026CD]
0177:0040D9AD  8B37                MOV       ESI,[EDI]

Si vous avez un tant soit peu l'habitude des programmes cryptés/compressés, le jmp EBX devrait vous sauter aux Yeux!
Dans la très grande majorité des cas, vous retrouverez un tel saut, ou l'une de ses variantes (Call EAX, Push Eax/Ret, Jmp Eax…) quand vous avez affaire à ce type de programme.

Donc, entre 0040D95F et 0040D9A5, vous êtes sensé trouver:

- Le "dépôt" de l'entry point de l'application d'origine dans EBX (004010CC)
- Le décryptage de l'application d'origine
- La restauration des registres qui semble être une constante des programmes compressés (POPAD)

Faites un d 004010CC en arrivant en 0040D95F. Vous verrez des ????? dans la fenêtre des Datas (codes invalides). Tracez avec F10, et en passant sur l'INT 3 en 0040D976, vous pourrez voir que ce mnémonique va permettre la décompression de NotePad, dans sa version pré-cryptée (par contre je ne sais pas quelle est le rôle exacte que joue l'interruption 3 dans l'opération de décryptage…). En continuant à tracer pas à pas, le REPZ STOSB va refermer les portes derrière vous en RECRYPTANT toutes les adresses précédant la 0040D77 (vous y verrez à la place des jolies codes que vous aviez, de vilains OUTSB), y compris le premier jmp que nous avions repéré en 0040DA8F.

Continuez jusqu'au jmp EBX, et au F10 suivant, vous aurez changé de section, pour passer de .reloc à .text: vous êtes dans NotePad.exe, Bye Bye le Loader.

Obtenir une version Clean du programme compressé/crypté:

Ce qui va nous intéresser, maintenant, c'est de pouvoir obtenir l'ensemble des String Data References que Wdasm est supposé nous donner, et de réussir ensuite à modifier le programme en enlevant les erreurs de type Shareware qui pourraient y avoir été glissées…

Pour réaliser un Dump exécutable, vous allez remplacer le jmp ebx par un jmp eip. Ainsi le programme effectuera une boucle sans fin sur lui même, alors que l'application d'origine sera décompressée en mémoire.
Ceci fait, quittez SoftIce (F5), et ouvrez ProcDump. Dans "options", sélectionnez "Rebuit import table", puis Notepad (en version crypté) dans la liste des applications actives de la fenêtre de ProcDump. Clic_droit sur Notepad, et choisissez Dump (Full), puis sauvegardez le nouvel exécutable décompressé.
Cliquez ensuite "PE Editor", et remplacez le précédent point d'entrée par celui donné par EBX, soit 4010CC - 400000 (image base) = 10CC, en lieu est place du D93C.
Le résultat est exécutable et désassemblable avec toutes les ressources habituelles.
Notepad passe de 59 ko à 60 ko, ce qui semblerait prouver qu'il y a bien eu cryptage ET compression, bien que sur 1 seul ko, il est difficile d'être affirmatif.

Désormais, vous pouvez traiter votre nouvel exécutable comme n'importe lequel des programmes dont vous avez l'habitude: il est clean, patchable à souhait, et fonctionne sans problème.

Mais si à chaque fois que vous tombez sur un programme encrypté par VG Crypt, vous devez refaire toutes ces manipulations, j'ai peur que vous finissiez par vous lasser…

Rédaction d'un script automatisé pour ProcDump.

Comme nous avons déjà repéré les deux goulets d'étranglement par lesquels VG Crypt nous a fait passer, il ne devrait plus être difficile d'automatiser tout le processus…

Voici ma proposition:

[VGCrypt]
L1=LOOK E9,CB         > recherche du JMP 0040D95F (1)
L2=BP                 > pose d'un break point
L3=LOOK 00,FF,E3      > recherche du JMP EBX (2)- 1 byte
L4= ADD 1             > avance de 1 byte
L5=BP                 > pose d'un break point sur le jmp EBX
L6=STEP               > commence à tracer le programme pas à pas
OPTL1=00000000
OPTL2=01010001
OPTL3=01010001 
OPTL4=00010000
OPTL5=00000000

Bien sur, vous n'oublierez pas de rajouter une entête dans l'index de ProcDump:

P1C=Shrinker 3.4
P1D=SalesAgent
P1E=Photo 1.0
P1F=VGCrypt

2 ou 3 détails pour finir:

En (1), la recherche ne porte que sur E9 CB pour E9 CB FE FF FF. Inutile de chercher plus de 2 octets, c'est suffisant, il n'y en a pas d'autres. Nous dirons que c'est la signature de VG Crypt, et ce pourra être utile pour identifier désormais que ce crypteur a été appliqué à un exécutable.

En (2), la recherche porte sur 00 FF E3, soit sur la fin du MOV[EDX+00402709],ECX (-> 89 8A 09 27 40
00), et sur le JMP EBX (FF E3), et ceci parce que le Loader, au moment ou il recrypte derrière lui sa première partie, va aussi traiter, sans modifications, les codes allant jusqu'au JMP EBX. Si vous ne mettez pas le 00 dans la chaîne à chercher, le Breakpoint va être posé trop vite, et faire planter l'opération. (Bien que je reste un peu dans l'expectative par rapport à cette solution, et à l'explication que je cherche à en donner…). Le ADD 1 servira simplement à avancer d'un octet, et à se recaller sur le JMP EBX.

ProcDump, au moment de la copie du Dump vous redonnera les 2 breakpoints (0040DA8F et 0040D9A5), et vous indiquera l'adresse à laquelle l'EIP a été sauvé.
En cryptant Calc.exe avec VG Crypt, puis en utilisant ProcDump, ces adresses seront différentes: le premier Breakpoint sera donné en 01017069, et le suivant en 01017253. Le script fonctionnera sans problème, E9 CB FE FF FF correspondant à la longueur du saut à faire, et non pas à une adresse physique...

Bonne Journée                                                 Remerciements tout spécialement à TaMaMBoLo, G-Rom et Koba Yashi

Christal