Advanced Mail List Verify v2. 00
by ub0.g0ss
Type de programme : Vérificateur d'adresses E-mail.
Protection : Asprotect, anti softice, anti windasm, checksum, serial number.
Outils : Softice, Procdump.
Introduction
Salut tout le monde!!! Je viens de passer 3 jours à essayer de cracker ce programme!!! Pas évident pour un débutant comme moi, mais finalement la protection est tombée. Je n'ai pas encore commencé ce tut mais je sens qu'il va être long et compliqué. Je vais essayer d'être le plus clair possible, en essayant de na pas trop entrer dans des détails inutiles. Bon je me lance.
Les protections rencontrées
D'abord, j'essaye de lancer le prog, et la on a droit à un joli nag : "debugger detected..." Ca commence bien. J'essaye de lancer le FP Loader de frogice, mais quand on lance le prog, ça fait planter complètement l'ordi! Bon, je vais poser un BPX createfilea afin de voir si on a affaire à Meltice, je lance le prog à nouveau et là softice break, par contre après une 20taine de F12, l'ordi plante et il faut rebooter. Bien sûr impossible de le désassembler avec windasm.
Bon je retrousse mes manches, je lance Procdump et je change toutes les sections de AMV en E0000020 (readable writable) à l'aide du PE editor. Ensuite je lance le symbol loader de softice et je commence à tracer.
Entry point : 00462001
PREMIERE PARENTHESE :
Bon j'ai pas fait de plan et j'espère que je vais pas tout mélanger. Asprotect change constamment les adresses des zones mémoires décompressées, à chaque redémarrage du prog les adresses sont différentes, donc c'est vraiment pas évident à tracer, impossible de placer des bpx et de plus très difficile pour se repèrer. En fait il y a un moyen de figer ces adresses, et ainsi cela depuis plus facile de tracer (ou moins difficile). Il faut poser un bpx GetTickCount, on arrive alors automatiquement à un truc du genre :
AND EAX, XXXXXXXX
il faut remplacer par :
AND EAX, 00000000
Et ainsi, les adresses ne varieront plus. Il faut relever le code hexa et faire la modif définitive avec un éditeur hexa.
Ici quand on fait un BPX GetTickCount, softice break en 00462224, ici :
:00462224 25FFFF0100 AND EAX,0001FFFF on remplace donc par : :00462224 2500000000 AND EAX,00000000
Maintenant on peut tracer tranquillement :
:00462001 60 PUSHAD :00462002 E801000000 CALL 00462008 :00462007 90 NOP :00462008 5D POP EBP :00462009 81EDBBAF4500 SUB EBP,0045AFBB :0046200F BBB4AF4500 MOV EBX,0045AFB4 :00462014 03DD ADD EBX,EBP ... :00462C1E 5B POP EBX :00462C1F EB04 JMP 00462C25 :00462C21 E8EB04E9EB CALL EC2F3111 :00462C26 FB STI :00462C27 E9C3A8C14B JMP 4C07D4EF :00462C28 C3 RET >> fin de ZD1
Bon, je ne vais pas détailler le tracé, il faut savoir que l'on a affaire à du code CCA (code changeant d'apparence), il existe un tut de Christal qui parle de ce code, il faut savoir que le code se transforme au fur et à mesure qu'on le trace, il est rempli de jump et de call. Il faut donc tracer le prog très lentement et entrer à l'intérieur du CALL qui précède l'affichage de la boite "debugger detected". Il faut poser un maximum de breakpoint pour éviter de recommencer depuis le début. Ensuite on a une zone constituée d'un grand nombre de sauts de toutes sortes. Ici aussi, il faut repèrer les boucles et poser des breakpoint juste après afin de gagner du temps. On arrive finalement à la fin de la décompression de la première partie (ZD1) en 00462C28.
On fait F10 puis F12 pour sortir du kernel, et on arrive dans une zone mémoire (ZM1). Ici, si vous n'avez pas forcé EAX à 0 en 00462224, les adresses ne seront jamais les mêmes et pour patcher c'est beaucoup plus compliqué (ça l'est déjà assez comme ca).
Donc la ZM1 commence en 004C407D :
:004C407D 60 PUSHAD :004C407E E844060000 CALL 004C46C7 :004C4083 EB44 JMP 004C40C9 :004C4085 0000 ADD [EAX],AL ...
Ici c'est pareil, le code apparait durant le traçage.
DEUXIEME PARENTHESE :
Je tiens à faire un aparthé à ce niveau car si je n'en parle tout de suite, cela faussera l'ordre de mon tut et il sera beaucoup plus difficile à comprendre. j'avais oublié une zone la première fois que j'avais fait mon patch et donc le prog plantait. J'ai donc cherché à quel endroit j'avais oublié une partie de décompression, et en fait elle se trouve un peu après la ZM1. J'ai donc modifié un peu mon patch pour rajouter cette section. Voila, c'était juste pour dire qu'il faut vraiment faire très attention en traçant, on peut passer à côté de zones vitales pour notre patch et c'est parfois difficile de rajouter du code quand tout est ficelé.
On trace un moment, et on tombe sur cette partie de code :
:004C4167 F3AA REPZ MOVSB :004C4169 8B8539294400 MOV EAX,[EBP+00442939] :004C416F 680080000000 PUSH 00008000 :004C4174 6A00 PUSH 00 :004C4176 50 PUSH EAX :004C4177 FF9541294400 CALL [EBP+00442941] :004C417D 8D85152C4400 LEA EAX,[EBP+00442C15] :004C4183 50 PUSH EAX :004C4184 C3 RET >> fin de ZD2, on va vers ZM2 ...
Le REPZ MOVSB est caractéristique d'une décompression, on a donc une deuxième zone de décompression (ZD2) dont la fin se trouve en 004C4184. Ensuite on tombe dans une nouvelle zone de mémoire (ZM2).
On continue à tracer dans cette zone jusqu'à la fin d'une troisième zone de décompression (ZD3) :
:004C4641 61 POPAD :004C4642 7508 JNZ 004C464C :004C4644 B801000000 MOV EAX,00000001 :004C4649 C20C00 RET 000C :004C464C 6894644B00 PUSH 004B6494 :004C4651 C3 RET >> fin ZD3 vers ZM3
Voila, on arrive maintenant dans une troisième zone mémoire (ZM3). C'est dans cette zone que l'on va trouver le test de présence de softice ainsi que le checksum qui est apparu quand on a modifié les sections. Les deux sont dans la même zone c'est déjà ça.
Ici il faut continuer à tracer et entrer dans les CALL à chaque fois quele message d'erreur apparait.
Je ne vais pas vous mettre tout le code, seulement les calls dans lesquels il faut entrer :
On arrive au début de la ZM3 en 004B6491, on trace jusqu'au CALL en 004B64B9 :
:004B64B9 E89A0BFFFF CALL 004A7058 >> on entre dedans
On trace , on passe un LEAVE puis un RET et on entre dans le premier CALL qui se présente après ça :
:004B5923 E8D0F9FFFF CALL 004B52F8
On continue à tracer, on arrive à la routine qui va contrôler la présence de softice :
:004B536B 8945F4 MOV [EBP-0C],EAX :004B536E 837DF400 CMP DWORD PTR [EBP-0C],00 :004B5372 0F8419010000 JZ 004B5491 >> on remplace le JZ en JMP :004B5378 E8AF070000 CALL 004B5B2C
Ici on remplace le JZ par un JMP afin de sauter par dessus la routine de contrôle de présence de softice : 004B5372 E91A010000 JMP 004B5491
On continue à tracer on va maintenant chercher le CALL qui va afficher le message d'erreur "file corrupted!" :
:004B55A8 E8A70FFFFF CALL 004A6554 :004B55AD 8B55F4 MOV EDX,[EBP-0C] :004B55B0 8B5205 MOV EDX,[EDX+05] :004B55B3 E8B0F4FFFF CALL 004B4A68 >> on entre dans ce CALL
Un D EDX en 004B55B3 affiche le message "File corrupted ! Please..." dans la fenêtre des datas. On a donc notre checksum. Maintenant on a le chois, soit on noppe le CALL, soit on entre à l'intérieur et on met un RET aussitôt entré, comme ça il ressort du CALL sans faire quoi que ce soit. J'ai opté pour la seconde méthode car on ne modifie qu'un seul bit par rapport au NOP qui lui en modifie 5. C'est plus simple!! :o)
:004B4A68 C3 RET
Bon on a viré l'anti softice ainsi que le checksum (pensez à poser des breakpoint aux endroits stratégiques afin de ne plus avoir à tracer par la suite).
Il reste à trouver l'OEP, pour voir ou commence le prog décompressé.
On fait sous softice :
s 0 l ffffffff 61 EB 01
et on pose un BPX sur l'adresse renvoyée par softice : ici 004B5294, on y va :
:004B5294 61 POPAD :004B5295 EB01 JMP 004B5298 :004B5298 50 PUSH EAX >> on met l'adresse de l'entry point sur la pile :004B5299 EB02 JMP 004B529D :004B529D E80200000000 CALL 004B52A4 :004B52A4 POP EAX >> on récupère l'adresse de l'OEP :004B52A5 C3 RET >> on y va. (fin ZM3)
L'OEP se trouve dans EAX, on a l'adresse : 00421BFC
Maintenant le prog se lance, on va pouvoir voir ce qu'il a comme protection. Il s'agit d'un serial unique à entrer et on est enregistré. Bon je vais poser un BPX hmemcpy pour voir ce que cela va nous donner.
En traçant, on arrive ici :
:0041888F 52 PUSH EDX :00418890 E8ABFBFFFF CALL 00418440 >> on entre dedans :00418895 83C404 ADD ESP,04 :00418898 742B JZ 004188C7 >> ici on saute si le serial entré est incorrect
Bon si on inverse le saut en 00418898, on est enregistré, mais commele prog doit sûrement vérifier au démarrage à un autre endroit si on est enregistré ou non, à mon avis au redémarrage il faudra à nouveau s'enregistrer (j'ai pas essayé). Donc soit on trouve le bon serial, soit on s'arrange pour que EAX soit toujours différent de 0 (condition pour que l'on soit enregistré).
Trouver le serial est un peu chiant, surtout que je n'ai pas fait tout ce chemin pour rien, je vais plutôt faire en sorte que EAX soit différent de 0 à la sortie du CALL.
Donc on trace dans ce CALL en 00418890, ici j'ai pas fait trop de notes alors je me souviens plus ou il faut entrer, mais je crois qu'il faut entrer dans pas mal de CALL pour arriver ici :
:0041841D 83C404 ADD ESP,04 :00418420 3BD8 CMP EBX,EAX :00418422 5D POP EBP :00418423 7507 JNZ 0041842C :00418425 33C0 XOR EAX,EAX >> à NOPPER :00418427 5B POP EBX :00418428 83C408 ADD ESP,08 :0041842B C3 RET >> on sort du CALL
Et voilà, on essaye et c'est bon, on est enregistré!!
Bon on va pouvoir construire notre patch avec tout ça :
RECAPITULATION :
Pour pouvoir appliquer le patch en mémoire, il faut entrer le code dans une zone vide du programme, et commencer de la fin en remontant le courant et en appliquant un lien vers notre patch avant la fin d'une décompression. En effet, le code n'existe pas encore avant décompression il faut donc appliquer le patch au moment ou la zone est décompressée.
D'abord je cherche de la place dans le programme, pour ça je vais voir avec mon éditeur hexa un endroit rempli de 0 et je place des 90 sur une grande surface. Je sauvegarde et je vais voir après avoir décompressé le prog si j'ai toujours mes NOP avec softice à l'adresse ou je les ai placé. C'est une technique un peu empirique mais là elle a marché . J'ai trouvé de quoi appliquer mon patch à partir de l'adresse 00462CAF (offset 2EEAF).
Maintenant que j'ai la place pour mon patch, je vais pouvoir le construire :
Pour ça, je commence de la fin et je place un lien vers l'adresse ou je vais appliquer mon patch juste avant la fin de la décompression.
Donc pour changer le XOR EAX,EAX à l'adresse 00418425 en NOP NOP (33C0 en 9090), je vais partir de la fin de la ZM3 qui se trouve en 004B5294 :
:004B5294 61 POPAD :004B5295 EB01 JMP 004B5298 >> on va contourner ici :004B5298 50 PUSH EAX :004B5299 EB02 JMP 004B529D :004B529D E80200000000 CALL 004B52A4 :004B52A4 POP EAX :004B52A5 C3 RET
Donc en 004B5295, je vais remplacer le JMP 004B5298 par :
004B5298 E915DAFAFF JMP 00462CAF >> en rouge c'est ce qui va servir pour notre lien vers ce patch
et en 00462CAF je construit mon premier patch (P1):
:00462CAF 66C705258441009090 MOV WORD PTR [00418425],9090 >> je met 9090 à l'adresse 00418425 :00462CB8 E93FEFFBFF JMP 00421BFC >> je saute directement vers l'OEP :00462CBD >> on relève cette adresse elle va servir
Voila, notre patch qui va cracker le programme est créé, il faut maintenant remonter à la zone précédente afin de créer le lien vers l'adresse 004B5298, de manière à la transformer en ce que l'on souhaite (c'est à dire changer le jmp 004B5298 en JMP 00462CAF). Eh oui, cette zone n'existe pas avant décompression, il faut donc ruser pour qu'on puisse la patcher après qu'elle soit créée. En fait le prog va s'auto patcher.
Voici les différentes étapes de décompression :
serial à cracker fin de ZM3 >> appliquer le patch P1 (saut vers zone libre + crack du serial) protection anti softice et checksum à retirer fin de ZD3 >> appliquer le patch P2 (lien vers saut de P1 + crack de anti si et checksum) zone mémoire 2 fin de ZD2 >> appliquer le patch P3 (lien vers saut de P2) zone mémoire 1 fin de ZD1 >> appliquer le patch P4 (lien vers saut de P3) zone de décompression 1 >> saut vers P4 à modifier directement avec un éditeur hexa.
Donc voila le principe, j'espère que c'est assez clair, franchement c'est difficile à expliquer.
Pour P2, nous devons créer le saut qui va se trouver en 004B5298 ainsi que les modifs pour virer les protections.
En fin de ZD3, on a ceci :
:004C4641 61 POPAD :004C4642 7508 JNZ 004C464C >> on va contourner ici vers l'adresse 00462CBD :004C4644 B801000000 MOV EAX,00000001 :004C4649 C20C00 RET 000C :004C464C 6894644B00 PUSH 004B6494 :004C4651 C3 RET
Donc on obtient ça :
:004C4642 E976E6F9FF JMP 00462CBD >> pareil, ce code hexa va servir pour P3
Et donc notre patch en 00462CBD (j'ai rajouté le précédent pour montrer l'ensemble) :
:00462CAF 66C705258441009090 MOV WORD PTR [00418425],9090 :00462CB8 E93FEFFBFF JMP 00421BFC :00462CBD C70572534B00E91A0100 MOV DWORD PTR [004B5372],00011AE9 >> notre JZ changé en JMP pour l'anti softice :00462CC7 C605684A4B00C3 MOV BYTE PTR [004B4A68],C3 >> le RET dans notre CALL pour le checksum :00462CCE C70595524B00E915DAFA MOV DWORD PTR [004B5295],FADA15E9 >> on créé le JMP 00462CAF en 004B5295 :00462CD8 C60599524B00FF MOV BYTE PTR [004B52299],FF >> la suite de notre JMP en 004B5295 :00462CDF E968190600 JMP 004C464C >> on retourne en 004C464C :00462CE4 >> on relève cette adresse elle va servir
Bon le patch 2 est terminé lui aussi, il faut maintenant créer le patch qui va construire celui ci. Donc P3.
Pour P3, on va devoir le placer avant la fin de ZD2 donc ici :
:004C4167 F3AA REPZ MOVSB :004C4169 8B8539294400 MOV EAX,[EBP+00442939] >> on détourne ici :004C416F 680080000000 PUSH 00008000 :004C4174 6A00 PUSH 00 :004C4176 50 PUSH EAX :004C4177 FF9541294400 CALL [EBP+00442941] :004C417D 8D85152C4400 LEA EAX,[EBP+00442C15] :004C4183 50 PUSH EAX :004C4184 C3 RET
ici on remplace le MOV EAX, [EBP+00442939] par CALL 00462CE4
:004C4169 E876EBF9FF CALL 00462CE4 >> on détourne ici, pour une question de poids de bits :004C416E 90 NOP >> je vais utiliser un CALL plutôt qu'un JMP :004C416F 680080000000 PUSH 00008000 >> ne change pas :004C4174 6A00 PUSH 00 ...
Ici vous pouvez constater que j'ai viré un MOV, il va falloir le restaurer dans le patch. Donc on va en 00462CE4 (en faisant F8 sur le CALL) et on arrive ici :
:00462CAF 66C705258441009090 MOV WORD PTR [00418425],9090 :00462CB8 E93FEFFBFF JMP 00421BFC :00462CBD C70572534B00E91A0100 MOV DWORD PTR [004B5372],00011AE9 :00462CC7 C605684A4B00C3 MOV BYTE PTR [004B4A68],C3 :00462CCE C70595524B00E915DAFA MOV DWORD PTR [004B5295],FADA15E9 :00462CD8 C60599524B00FF MOV BYTE PTR [004B52299],FF :00462CDF E968190600 JMP 004C464C :00462CE4 C70542464C00E976E6F9 MOV DWORD PTR [004C4642],F9E676E9 >> je créé le JMP 00462CBD à l'adresse 004C4642 :00462CEE C60546464C00FF MOV BYTE PTR [004C4646],FF >> la suite du JMP :00462CF5 8B8539294400 MOV EAX,[EBP+00442939] >> on restaure le MOV :00462CFB C3 RET >> on sort :00462CFC >> on note cette adresse qui va servir pour P4
Voilà le troisième patch terminé, il n'y en a plus qu'un à placer, et c'est en fin de première décompression (ZD1)
:00462C1E 5B POP EBX :00462C1F EB04 JMP 00462C25 >> on contourne ici :00462C21 E8EB04E9EB CALL EC2F3111 :00462C26 FB STI :00462C27 E9C3A8C14B JMP 4C07D4EF :00462C28 C3 RET
Donc on va contourner en 00462C1F, c'est à dire on remplace : :00462C1F EB04 JMP 00462C25 par :00462C1F E9D8000000 JMP 00462CFC >> l'adresse pour applqiuer le dernier patch
Voila, on arrive donc ici :
:00462CAF 66C705258441009090 MOV WORD PTR [00418425],9090 :00462CB8 E93FEFFBFF JMP 00421BFC :00462CBD C70572534B00E91A0100 MOV DWORD PTR [004B5372],00011AE9 :00462CC7 C605684A4B00C3 MOV BYTE PTR [004B4A68],C3 :00462CCE C70595524B00E915DAFA MOV DWORD PTR [004B5295],FADA15E9 :00462CD8 C60599524B00FF MOV BYTE PTR [004B52299],FF :00462CDF E968190600 JMP 004C464C :00462CE4 C70542464C00E976E6F9 MOV DWORD PTR [004C4642],F9E676E9 :00462CEE C60546464C00FF MOV BYTE PTR [004C4646],FF :00462CF5 8B8539294400 MOV EAX,[EBP+00442939] :00462CFB C3 RET :00462CFC C70569414C00E876EBF9 MOV DWORD PTR [004C4169],F9EB76E8 >> notre CALL 00462CE4 en 004C4169 :00462D06 66C7056D414C00FF90 MOV WORD PTR [004C416D],90FF >> la suite de notre CALL avec le NOP :00462D0F E914FFFFFF JMP 00462C28 >> on retourne au prog
Voila le patch au complet, le JMP 00462CFC est à modifier directement avec un éditeur hexa.
En ce qui concerne le patch, on se place à l'offset 2EEAF avec un éditeur hexa et on se tape tout le code, soit :
66C705258441009090E93FEFFBFFC70572534B00E91A0100C605684A4B00C3C70595524B00E915DAFAC60599524B00FFE96819
0600C70542464C00E976E6F9C60546464C00FF8B8539294400C3C70569414C00E876EBF966C7056D414C00FF90E914FFFFFF
Have fun !!!
Maintenant on peut lancer le proggy et super il passe impeccable, en plus on est enregistré.!!! CQFD
Conclusion
Je tiens à remercier deux personnes sans qui ce tut n'aurait
probablement jamais vu le jour, il s'agit de Christal (merci
"Master") et de LutinNoir. Christal m'a beaucoup aidé
sur la manière de supprimer l'anti softice ainsi que le checksum,
et LutinNoir m'a montré comment supprimer le problèmes des
adresses variables.
Ce tut leur est donc dédié.
J'ai franchement eu beaucoup de mal à y arriver, mais la persévérance m'a permis de venir à bout de cette merde.
Voilà, en espèrant avoir était très clair, et que ce tut vous apprendra des choses, je vous souhaite une bonne journée (ou une bonne nuit).
ub0.g0ss (ub0.g0ss@caramail.com)