1ére partie : On va reverser la procedure de décryptage de VGcrypt pour pouvoir la réutiliser dans notre undecryptor.
How to code an Uncryptor/Unpacker
for VGCrypt PE Encryptor v0.75 Beta
by LuTiN NoIR
2ème partie : On peut enfin coder UnVGCrypt . Cependant il reste quelques choses à modifier.
"Cracking and Reverse Engineering is just for fun and pleasure"

 
 
I_Avant Propos :

Il y a plusieurs facon de coder un unpacker/uncryptor en laissant le prog le faire ou en le faisant nous même (et encore d'autre variante). Je ne présenterais ici qu'une méthode : on va utiliser la routine du cryptor. Pourquoi VGCrypt ? Et bien parce qu'il est relativement simple donc c'est très bien pour expliquer et pour que ce texte soit accessible au plus grand nombre. Il s'agit ici d'un cypteur codé par Virogen (good work man ;)) et c'est un peu plus simple qu'un packer car il ne compresse pas les données donc la routine que le prog utilise pour decrypter est donc plus simple (en général) que pour un packer qui utilise souvent des routines complexes. Comme je l'ai dit c'est une première approche après pour coder certain unpackers/uncryptors il est nécessaire de reconstruire par exemple une table d'import ou plus exactement de modifier la procédure du packer. Mais ici ca restera relativement simple.
 
 
 
II_How to : (part 1)

Pourquoi un undecryptor pour VGCrypt ? Et bien parce qu'il existe encore une personne qui utilise ce prog dans ces crackmes , j'ai nommé Christal ! ;). Donc l'occasion était trop belle :). Pour Commencer soit on recupère le crackme 2 de Christal, soit on recupère VGCrypt et on crypt un prog. J'ai fait cette essai en cryptant le notepad de windows. Bon on va donc commencer. Pour ce faire on lance notepad (ou autre prog crypter avec VGCrypt) avec symbol loader de softice (ou avec TRW2000) et on break à l'eop du prog :
 

015F:00404E9C  9C                  PUSHFD                    <-- début
015F:00404E9D  55                  PUSH      EBP
015F:00404E9E  E8EC000000          CALL      00404F8F        <-- on rentre direct dans ce call
015F:00404EA3  87D5                XCHG      EDX,EBP
015F:00404EA5  5D                  POP       EBP
015F:00404EA6  60                  PUSHAD
015F:00404EA7  87D5                XCHG      EDX,EBP
015F:00404EA9  80BD1527400001      CMP       BYTE PTR [EBP+00402715],01
015F:00404EB0  7439                JZ        00404EEB
015F:00404EB2  C6851527400001      MOV       BYTE PTR [EBP+00402715],01

Bon dès le début on a un call, il faut donc rentrer dedans (et oui notre but est de reverser le loader de VGCrypt qui est forcément dès le début du prog) et on voit ca :

015F:00404F8A  3D1E0000EA          CMP       EAX,EA00001E
015F:00404F8F  E800000000          CALL      00404F94             <-- un deuxième call qui nous ammène à
                                                                      l'instruction suivante
015F:00404F94  8B2C24              MOV       EBP,[ESP]            <-- on récupère le contenu de la pile
015F:00404F97  81ED1C274000        SUB       EBP,0040271C         <-- on enlève 40271C
015F:00404F9D  83C404              ADD       ESP,04               <-- et rétablit la pile et on repart
015F:00404FA0  C3                  RET
015F:00404FA1  B8E81B0000          MOV       EAX,00001BE8
015F:00404FA6  008B642408E8        ADD       [EBX+E8082464],CL
015F:00404FAC  DFFF                ESC

Bon ici en 404f8f il appel ce qu'il y a en 404f94, soit l'instruction qui suit. Il fait cela pour récupérer l'adresse courante en mémoire. Lorsque l'instrucion call 404f94 s'éffectue et bien l'adresse suivante (de retour est placé sur la pile) donc le programme sait à quelle adresse mémoire il est. Comme cela en soustrayant 40271c à 404f94 (adresse sur la pile de retour du call) VGCrypt saura se repérer dans son code. C'est de cette manière que le code du crypteur peut être mis dans n'importe quel programme. On note alors que cette valeur est 2878h. On continue de tracer et on arrive là :

015F:00404FA2  E81B000000          CALL      00404FC2                    <-- on rentre dans ce call
015F:00404FA7  8B642408            MOV       ESP,[ESP+08]
015F:00404FAB  E8DFFFFFFF          CALL      00404F8F
015F:00404FB0  C685CC264000C3      MOV       BYTE PTR [EBP+004026CC],C3
015F:00404FB7  E84BFFFFFF          CALL      00404F07
015F:00404FBC  E916FFFFFF          JMP       00404ED7

On rentre donc dans le call en 404fa2 (je rappel qu'on analyse comment fonctionne le loader/decrypteur de VGCrypt qui est dans notepad) :

015F:00404FC2  6467FF360000        PUSH      DWORD PTR FS:[0000]       <-- on met un petit SEH
015F:00404FC8  646789260000        MOV       FS:[0000],ESP
015F:00404FCE  8DB547264000        LEA       ESI,[EBP+00402647]        <-- met dans esi 402647+2878h
015F:00404FD4  8BFE                MOV       EDI,ESI                   <-- pareil dans esi
015F:00404FD6  B9CA000000          MOV       ECX,000000CA              <-- ecx == cah
015F:00404FDB  8AA511274000        MOV       AH,[EBP+00402711]         <-- on récupère un code dans AH
015F:00404FE1  AC                  LODSB                               <-- on met dans al ce qu'il y a à l'adresse
                                                                           pointée par esi
015F:00404FE2  32C4                XOR       AL,AH                     <-- quelques manip de decryptage
015F:00404FE4  FEC4                INC       AH
015F:00404FE6  C0C402              ROL       AH,02
015F:00404FE9  80C490              ADD       AH,90
015F:00404FEC  AA                  STOSB                               <-- et hop on remet la véritable valeur
015F:00404FED  E2F2                LOOP      00404FE1                  <-- et on boucle
015F:00404FEF  E9CBFEFFFF          JMP       00404EBF                  <-- et on s'en va
015F:00404FF4  0000                ADD       [EAX],AL
015F:00404FF6  0000                ADD       [EAX],AL

Malheuresement le decrypteur n'est pas si simple. Et oui le cah mis dans ecx est une valeur constante (voir dans s'autre prog). En fait il décrypte bien un code mais c'est celui du loader de VGCrypt !!! Et oui son propre loader/decrypteur est crypté.
Bon alors on continue de tracer :

015F:00404EBF  E800000000          CALL      00404EC4                     <-- call vers instruction suivante
015F:00404EC4  8B9D05274000        MOV       EBX,[EBP+00402705]
015F:00404ECA  83C328              ADD       EBX,28
015F:00404ECD  58                  POP       EAX
015F:00404ECE  2BC3                SUB       EAX,EBX
015F:00404ED0  89850D274000        MOV       [EBP+0040270D],EAX
015F:00404ED6  CC                  INT       3                            <-- provoque une exception et nous envoie
                                                                              en 404f07
015F:00404ED7  8DBD24264000        LEA       EDI,[EBP+00402624]           <-- fin du décryptage
015F:00404EDD  B93B000000          MOV       ECX,0000003B
015F:00404EE2  F3AA                REPZ STOSB                             <-- mutile le décrypteur
015F:00404EE4  64678F060000        POP       DWORD PTR FS:[0000]
015F:00404EEA  5A                  POP       EDX
015F:00404EEB  8B850D274000        MOV       EAX,[EBP+0040270D]
015F:00404EF1  018509274000        ADD       [EBP+00402709],EAX
015F:00404EF7  61                  POPAD
015F:00404EF8  9D                  POPFD
015F:00404EF9  8B9A09274000        MOV       EBX,[EDX+00402709]           <-- récupère le vrai eop
015F:00404EFF  898A09274000        MOV       [EDX+00402709],ECX
015F:00404F05  FFE3                JMP       EBX                          <-- et va vers le début du prog
015F:00404F07  8DBDCD264000        LEA       EDI,[EBP+004026CD]           <-- /*** ici débute le decrypteur ***/
015F:00404F0D  8B37                MOV       ESI,[EDI]                    <-- recup une valeur (1000) dans esi
015F:00404F0F  0BF6                OR        ESI,ESI
015F:00404F11  7431                JZ        00404F44
015F:00404F13  03B50D274000        ADD       ESI,[EBP+0040270D]           <-- ajoute 400000 (imagebase)
015F:00404F19  8B4F04              MOV       ECX,[EDI+04]                 <--une autre valeur dans ecx
015F:00404F1C  57                  PUSH      EDI
015F:00404F1D  8BFE                MOV       EDI,ESI                      <-- on met 401000 dans edi aussi
015F:00404F1F  8B9D11274000        MOV       EBX,[EBP+00402711]           <-- tient encore une valeur dans ebx
015F:00404F25  F8                  CLC                                    <-- some intructions :)
015F:00404F26  83E904              SUB       ECX,04
015F:00404F29  AD                  LODSD                                  <-- recupère le code crypté
015F:00404F2A  03C3                ADD       EAX,EBX                      <-- et décrypte
015F:00404F2C  33C3                XOR       EAX,EBX
015F:00404F2E  D1CB                ROR       EBX,1
015F:00404F30  81EB66708090        SUB       EBX,90807066                 <-- avec une valeur intérressante
015F:00404F36  03DB                ADD       EBX,EBX
015F:00404F38  AB                  STOSD                                  <-- et recopie le code décryptée
015F:00404F39  83E904              SUB       ECX,04                       <-- boucle 1
015F:00404F3C  73EB                JAE       00404F29
015F:00404F3E  5F                  POP       EDI
015F:00404F3F  83C708              ADD       EDI,08
015F:00404F42  EBC9                JMP       00404F0D                     <-- boucle 2
015F:00404F44  CF                  IRETD                                  <-- heu en fait c c3h ret le dump a merdé:(
015F:00404F45  0010                ADD       [EAX],DL                         c la fin de la decryption et on retourne un
015F:00404F47  0000                ADD       [EAX],AL                         peu plus haut en 404ed7

Bon là on a tous le code pour faire le uncryptor ... sauf que les valeurs recupérer : ebp+40270d puis edi+4 ont été décrypter avec le loader de VGCrypt qui utilisait un décryptage basé sur le précédent. On va donc devoir décrypter le loader de VGCrypt pour récupérer les valeurs nécessaire au décryptage du reste. Bon pour la valeur 90807066 qu'il utilise pour savoir si elle est constante soit on reverse VGCrypt (le packer le vrai) soit on compare es progs cryptés avec et on constate qu'elle est constante. Pour celle récupérer en 402711+ebp elle est dans le code dès le début donc on peut la récupérer à chaque fois (cette une clef de décryptage qui change d'un prog a un autre). Cette clef est modifié pendant le décryptage même !!! .
Maintenant il faut pouvoir ce repérer dans le programme !!! En fait c'est relativement simple. VGCrypt doit s'adapter à n'importe quel programme donc sont code est identique donc si par exemple on note l'eop du programme crypté et qu'on note les adresse (par exemple le début du loader cryptées, l'adresse de la clef ....) et bien la différence entre les deux sera toujours la même :).
Bon cette dernière routine récupère en fait le virtual offset de chaque section cryptées ainsi que la taille, puis la decrypte avec la clef. On va donc utilser la même routine.
Passons maintenant à notre uncryptor : soit on lance l'applicaton désiré comme process, soit comme fichier. J'ai décidé de le faire comme fichier. Il faudra donc aller dans le peheader et faire des conversions entre les virtual address et les raw offset. Si on avait lancer le prog en tant que process on aurait pas eu ce problème mais on aurait eu un prog plus gros et on aurait du réaligner les sections...
Voilà pour le code regarder les sources ... :)
 

Résumé: on doit mapper le prog en mémoire, récupérer les infos dans le peheader, puis décrypter le loader pour récupérer les virtual address des sections et l'eop, ensuite on peut les décrypter et voilà ...
 
 
III_Conclusion finale :

Bon voilà une première approche d'un décrypteur. Bien sur ici c'est relativement simple mais il vaut mieux ca pour apprendre que vous expliquer comment écrire un unpacker pour asprotect :). Je ne suis pas non plus rentré dans les détails mais il vaut mieux que vous analysiez vous même pour bien saisir ... et puis je n'ai pas trop le temps en ce moment ....
N'hésitez pas à me contacter : city_of_bitch@caramail.com

Greetz to:  Virogen , Teeji, Christal, MrPhilex, TaMaMBoLo , CoRsIcA, The AnALyST, Falcon, R!SC, the_owl, ep-180, vrom, meRlin, et tous ceux que jai oublié sur #crack.fr et #cracking4newbies ....

Amicalement
LuTiN NoIR