| 1ére partie : On va reverser la procedure de décryptage de VGcrypt pour pouvoir la réutiliser dans notre undecryptor. |
for VGCrypt PE Encryptor v0.75 Beta by LuTiN NoIR |
2ème partie : On peut enfin coder UnVGCrypt . Cependant il reste quelques choses à modifier. |
|
|
| 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