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)