FruityLoops 1.40


Introduction

FruityLoops est un petit programme qui permet d'éditer et de modifier des fichiers audio. Il a l'air très sympa mais c'est évidement un shareware et il y a donc un nag au démarrage et quelques fonctions désactivées.

Le but de ce tut sera donc de montrer comment éliminer tous ces problèmes.

Outils nécessaires

Pour ce tut, il faut :

 - SoftICE 3.2+ (SoftICE 3.23 pour moi)
 - Un désassembleur : W32Dasm suffit ici (W32Dasm 8.93 pour moi)
 - ProcDump 1.3.0-1.4.0
 - FileMonitor
 - Un éditeur hexadécimal (j'utilise HEdit "customisé" et je déteste HexWorkShop mais c'est personnel ;)
- Un ou deux bon CD (moi j'écoute beaucoup U2 en ce moment, mais vous pouvez préférer les Spice Girls :)

Tut

I. Première Approche

Personnellement, j'utilise toujours SoftICE au début, pour voir à quoi j'ai à faire. Donc ici on voit un nag apparaitre donc "BPX ShowWindow" et on trace, on trace....et on voit qu'il y a beaucoup de "CALL [EAX+40]" et de trucs dans le même style, ça ressemble pas trop à un prog écrit en C/C++ mais plutôt à un RAD style Delphi. Conclusion, on va essayer avec W32Dasm, mais alors là, c'est la claque : pas de Strings Reference et le code est complétement bidon, on se croirait dans du Visual Basic c'est dire :). Deuxième conclusion : le prog est compressé et/ou crypté.

Pour savoir si un prog est compressé, il y a une technique simple : utiliser le PE Editor de ProcDump. On lance donc ProcDump, on clique sur "PE Editor" et on choisit FruityPro.exe". Une boite de dialogue apparait et on clique sur "Sections", une autre boite apparait, nous montrant toutes les sections de FruityPro.exe (pour plus d'infos sur les sections et sur le format PE en général, allez chez Wotsit's Format: The programmer's file formats and data formats resource, section "binaries"). Maintenant, il suffit de comparer la Virtual Size de chaque section avec la Raw Size. Si elles sont à peut près égales, le fichier n'est pas compressé, si la Virtual Size est bien plus grande que la Raw Size, le fichier est compressé. CQFD :)
Quel intérêt de savoir que le fichier n'est pas compressé ? Si on veut restorer le fichier initial, il suffit de dumper les sections une par une à partir de SoftICE et de les remplacer dans le fichier original, pas la peine de créer un nouveau fichier, de modifier sa taille...

Mais, me direz vous, pourquoi ne pas simplement utiliser ProcDump pour décompresser/décoder le fichier ? Comme ça ProcDump fait tout et on se fout de savoir s'il y a cryptage, compression... C'est sûr, mais ça peut toujours être utile, et puis on se sent plus intelligent non :)

Bon, maitenant, on a son fichier décrypté grâce à ProcDump et on saute dessus pour l'exécuter ! Ca marche pas !!! En fait, le problème est que ProcDump n'arrive pas à retrouver l'EIP originale, c'est à dire le point de départ du programme avant qu'il soit protégé. Pas grave, on a maintenant un fichier décrypté avec pleins de Strings Reference qu'on va pouvoir utiliser avec W32Dasm.


II. Cracker FruityLoops - 1ere méthode

On regarde donc les Strings Reference et on voit des trucs du style "RegisterAutomation", "Registering FruityLoops"
, "Registration failed (please check "... Bref, il semble qu'il s'agisse ici d'une version demo enregistrable !

Question : comment s'enregsitrer ? Pas d'infos dans la doc et rien dans les menus....
Il y peut-être des infos dans la base de registre ou dans un fichier, qui sait ?
Après quelques essais avec RegMonitor et FileMonitor, on trouve un fichier bizzare : "Ilrc.scr". On peut donc essayer de créer ce fichier, de tracer le prog et de voir ce qu'il en fait, mais bon, ça risque d'être long et pas évident. Et puis de toute manière, ce fichier ne doit contenir que le nom et le serial, et ce nom et ce serial, faut bien les saisir quelque part !

Deux solutions
- examiner le code et se débrouiller pour faire apparaitre la "Registration Box" (pour un exemple concret, regardez une des soluces du Strainer 99 à propos de BrainsBreaker). Mais bon, ici c'est du Delphi, alors comprendre le code à ce niveau là, moi j'ai encore des progrès à faire... ;)
- essayer des combinaisons au hazard : essayez et vous finirez par trouver CTRL+ALT+F9.

1. Trouver le code vérifiant le serial

Donc, on a une Registration Box avec un nom et un serial.

Première idée : "BPX GetDlgItemTextA" et "BPX GetWindowTextA", les deux classiques. Ca donne rien !

Deuxième idée : un "BMSG hWnd WM_GETTEXT". Ca donne rien non plus !
En fait les programmes Delphi utilisent leurs propres messages (WM_USER+???) donc un BMSG ne donnera rien.

Troisième et dernière idée : "s 30:0 l FFFFFFFF 'Serial Bidon'" et mettre une BPM dessus. Ca, ça a des chances de marcher ! (Pour les utilisateurs de WinNT, le segment de données change tout le temps, il faut donc remplacer 30:0 par DS:0 quand vous être dans le process de FruityLoops)
Mais, sous Win9x, il y a un truc plus rapide "BPX hmemcpy".

On met donc un "BPX hmemcpy" et on trace jusqu'à ce que le serial soit utilisé

015F:0049586A 8B45F8			MOV EAX,[EBP-08] <--- Utilisation du nom
015F:0049586D 8D55FC 			LEA EDX,[EBP-04]
015F:00495870 E827FCFFFF 		CALL 0049549C
015F:00495875 8B55FC 			MOV EDX,[EBP-04]
015F:00495878 A1802B4B00 		MOV EAX,[004B2B80]
015F:0049587D E8EEE1F6FF 		CALL 00403A70
015F:00495882 33D2 			XOR EDX,EDX
015F:00495884 8BC6 			MOV EAX,ESI
015F:00495886 E839A2F8FF 		CALL 0041FAC4
015F:0049588B 8B9BF0010000 		MOV EBX,[EBX+000001F0]
015F:00495891 8D55F4 			LEA EDX,[EBP-0C]
015F:00495894 A1F84B4B00 		MOV EAX,[004B4BF8]
015F:00495899 E86E1CF7FF 		CALL 0040750C
015F:0049589E 8D45F4			LEA EAX,[EBP-0C]
015F:004958A1 50 			PUSH EAX
015F:004958A2 8D55F8 			LEA EDX,[EBP-08]
015F:004958A5 8BC3 			MOV EAX,EBX
015F:004958A7 E8E8A1F8FF 		CALL 0041FA94
015F:004958AC 8B55F8 			MOV EDX,[EBP-08] <--- Utilisation du serial
015F:004958AF 58 			POP EAX
015F:004958B0 E8EBE3F6FF 		CALL 00403CA0
015F:004958B5 8B45F4 			MOV EAX,[EBP-0C]
015F:004958B8 8D55FC 			LEA EDX,[EBP-04]
015F:004958BB E8DCFBFFFF 		CALL 0049549C
015F:004958C0 8B55FC 			MOV EDX,[EBP-04] <--- Truc bizzare
015F:004958C3 A1BC294B00 		MOV EAX,[004B29BC]
015F:004958C8 E8A3E1F6FF 		CALL 00403A70
015F:004958CD 33D2 			XOR EDX,EDX
015F:004958CF 8BC3 			MOV EAX,EBX
015F:004958D1 E8EEA1F8FF 		CALL 0041FAC4
015F:004958D6 E801FDFFFF 		CALL 004955DC
015F:004958DB B840594900 		MOV EAX,00495940 <--- "Registration failed..."
015F:004958E0 E8FB8A0000 		CALL 0049E3E0
015F:004958E5 A130294B00 		MOV EAX,[004B2930]
015F:004958EA 833800 			CMP DWORD PTR [EAX],00
015F:004958ED 7515 			JNZ 00495904
015F:004958EF 6A00 			PUSH 00
015F:004958F1 668B0D74594900 		MOV CX,[00495974]
015F:004958F8 33D2 			XOR EDX,EDX
015F:004958FA B880594900 		MOV EAX,00495980 <--- "Your registration failed"
015F:004958FF E8B47BFAFF 		CALL 0043D4B8
015F:00495904 33C0 			XOR EAX,EAX
015F:00495906 .... 			...

A en juger par le code, il semble que le prog utilise le nom, le serial, fasse quelque chose et affiche en 004958DB "Registration failed" sans effectuer aucun test (pas de CMP, TEST...). Par contre il y a un test après (004958EA) qui décide d'afficher ou non "Your registration failed". En étudiant un peu plus le code avant 004958DB et plus particulièrement le CALL 004955DC on s'aperçoit qu'en fait le prog encrypte le nom, le serial et les enregistre dans le fichier "Ilrc.scr" même si le serial est faux !

2. Cracker le code vérifiant le serial

En fait, le vrai test est après, c'est le CALL 0049E3E0 et plus précisement le code en 0049E2FC

015F:0049E2FC 55 			PUSH EBP
015F:0049E2FD 8BEC 			MOV EBP,ESP
015F:0049E2FF 6A00 			PUSH 00
015F:0049E301 6A00 			PUSH 00
015F:0049E303 6A00 			PUSH 00
015F:0049E305 33C0 			XOR EAX,EAX
015F:0049E307 55 			PUSH EBP
015F:0049E308 68D5E34900 		PUSH 0049E3D5
015F:0049E30D 64FF30 			PUSH DWORD PTR FS:[EAX]
015F:0049E310 648920 			MOV FS:[EAX],ESP
015F:0049E313 8D55FC 			LEA EDX,[EBP-04]
015F:0049E316 A1604C4B00 		MOV EAX,[004B4C60]
015F:0049E31B E81C72FFFF 		CALL 0049553C
015F:0049E320 B83F080000 		MOV EAX,0000083F
015F:0049E325 E832FBFFFF 		CALL 0049DE5C
015F:0049E32A 8D45F8 			LEA EAX,[EBP-08]
015F:0049E32D 50 			PUSH EAX
015F:0049E32E 8D55F4 			LEA EDX,[EBP-0C]
015F:0049E331 A15C4C4B00 		MOV EAX,[004B4C5C] <--- Serial codé
015F:0049E336 E80172FFFF 		CALL 0049553C
015F:0049E33B 8B45F4 			MOV EAX,[EBP-0C] <--- Serial décodé
015F:0049E33E B907000000 		MOV ECX,00000007
015F:0049E343 BA01000000 		MOV EDX,00000001
015F:0049E348 E84F5BF6FF 		CALL 00403E9C
015F:0049E34D A15C4C4B00 		MOV EAX,[004B4C5C]
015F:0049E352 E84159F6FF 		CALL 00403C98 <--- renvoie en EAX la longueur du serial
015F:0049E357 83E809 			SUB EAX,09 <--- Longueur = 9
015F:0049E35A 7405 			JZ 0049E361 <--- Oui
015F:0049E35C 48 			DEC EAX <--- Longueur = 10
015F:0049E35D 7425 			JZ 0049E384 <--- oui
015F:0049E35F EB48 			JMP 0049E3A9 <--- On arrête
<---- Longueur = 9 ----> 
015F:0049E361 8D55F4 			LEA EDX,[EBP-0C]
015F:0049E364 8B45FC 			MOV EAX,[EBP-04] <--- Nom
015F:0049E367 E8F8FAFFFF 		CALL 0049DE64
015F:0049E36C 8B55F4 			MOV EDX,[EBP-0C]
015F:0049E36F 8B45F8 			MOV EAX,[EBP-08]
015F:0049E372 E8315AF6FF 		CALL 00403DA8
015F:0049E377 0F94C0 			SETZ AL
015F:0049E37A 83E07F 			AND EAX,7F
015F:0049E37D A3F0264B00 		MOV [004B26F0],EAX
015F:0049E382 EB2C 			JMP 0049E3B0
<---- Longueur = 10 ----> 
015F:0049E384 8D55F4 			LEA EDX,[EBP-0C]
015F:0049E387 8B45FC 			MOV EAX,[EBP-04] <--- Nom
015F:0049E38A E821FCFFFF 		CALL 0049DFB0
015F:0049E38F 8B55F4 			MOV EDX,[EBP-0C]
015F:0049E392 8B45F8 			MOV EAX,[EBP-08]
015F:0049E395 E80E5AF6FF 		CALL 00403DA8
015F:0049E39A 0F94C0 			SETZ AL
015F:0049E39D 83E07F 			AND EAX,7F
015F:0049E3A0 03C0 			ADD EAX,EAX
015F:0049E3A2 A3F0264B00 		MOV [004B26F0],EAX
015F:0049E3A7 EB07 			JMP 0049E3B0
015F:0049E3A9 33C0 			XOR EAX,EAX 
015F:0049E3AB A3F0264B00 		MOV [004B26F0],EAX
015F:0049E3B0 B8F7000000 		MOV EAX,000000F7
015F:0049E3B5 E8A2FAFFFF 		CALL 0049DE5C
015F:0049E3BA 33C0 			XOR EAX,EAX
015F:0049E3BC 5A 			POP EDX
015F:0049E3BD 59 			POP ECX
015F:0049E3BE 59 			POP ECX
015F:0049E3BF 648910 			MOV FS:[EAX],EDX
015F:0049E3C2 68DCE34900 		PUSH 0049E3DC
015F:0049E3C7 8D45F4 			LEA EAX,[EBP-0C]
015F:0049E3CA BA03000000 		MOV EDX,00000003
015F:0049E3CF E86C56F6FF 		CALL 00403A40
015F:0049E3D4 C3 			RET

Bon, je vais pas expliquer plus le code mais si on se souvient des Strings Reference dans W32Dasm, on peur supposer qu'il y a deux modes d'enregistrement : Basic et Pro (c'est aussi écrit dans le fichier InfoTxt.rtf), d'où une longueur égale à 9 ou 10. Il n'y a plus qu'à regarder le code en 0049E36C ou en 0049E38F pour rapidement trouver un bon serial.

S'il y a un p'tit gars courageux, il pourra même écrire un petir KeyGen, c'est pas trop dur à faire :)


III. Cracker FruityLoops - 2eme méthode


Tout ça c'est bien beau, mais si FruityLoops ne pouvait pas être enregistré, comment on aurait fait, hein ?
Vous vous souvenez au début, quand on avait décodé FruityLoops avec ProcDump, ça ne marchait pas. On va donc étudier la question un peu plus.

Un des points importants quand on décompresse/décode un programme, c'ets la section .idata qui contient en fait les fonctions utilisées dans le prog et qui sont dans des DLL communes (USER32.DLL, KERNEL32.DLL...) En effet, la pluspart des protections aujourd'hui codent aussi cette section et la charge "en live" lors du décodage. Normalement ProcDump permet de restaurer aussi cette section mais d'après mon expérience personnelle, ça ne marche pas tout le temps, surtout sous NT (un problème avec NTDLL.DLL :( Mais dans FruityLoops, quand on regarde les Imports grâce à W32Dasm par exemple, on s'apperçoit qu'ils n'ont pas été codées : bonne chose !

Le seul problème reste donc de trouver l'EIP originale du programme, avant que la protection ne soit appliquée.

Première solution : tracer complétement le code de décryptage ! Vous pouvez essayer, mais c'est pas la solution la plus rapide ni la plus simple.

Deuxième solution : Utiliser ProcDump et un petit script spécial CodeSafe
Pour ça, il faut étudier un programme protégé avec CodeSafe qui soit le plus simple possible. Un truc du style

INT 03
PUSH ...
CALL MessageBoxA
PUSH 0
CALL ExitProcess

en assembleur parait pas trop mal. Pourquoi, une INT 03 au début, je vais expliquer :)
Il suffit donc de compiler ça et de protéger le résultat avec CodeSafe. Ensuite on lance SoftICE en mettant bien I3HERE à ON. Voilà l'utilité du INT 03 au début : peu importe ce que CodeSafe fera, SoftICE arrivera toujours au moment où la protection rend la main au programme principal pour s'exécuter. A ce moment là on peut étudier le contenu de la pile, des registres... et trouver la dernière instruction de la protection.

Ici, en faisant un "U *(ESP-4)", on arrive juste à une instruction intéressante : "JMP ECX". Or dans ECX il y a 401000h, l'EIP originale ! On vient donc de trouver la dernière instruction de la protection !

Maintenant, si on pouvait écrire un petit script pour ProcDump qui automatiserait tout ça, ce serait le rêve !
Si on regarde dans la doc de ProcDump, on voit des instructions très pratiques du style : LOOK, BP.... Le script suivant devrait donc marcher :

P11=CodeSafe 3.X

[CodeSafe 3.X]
L1=LOOK FF,E1,C3
L2=BP
L3=STEP
OPTL1=00000000
OPTL2=01010001
OPTL3=01010001
OPTL4=00010000
OPTL5=00000000

FF,E1,C3 est le code Hexa pour "JMP ECX ; RET".

Mais en fait ne code n'existe pas au début de la protection, il est crypté ! Il faut donc rechercher les instructions qui décryptent "JMP ECX ; RET", mettre un BP dessus, et, à ce moment là, faire un LOOK FF,E1,C3. Je vous passe les détails, c'est assez facile...

Ce qui donne donc le script final suivant pour décoder tout fichier codé avec CodeSafe 3.X (avec ProcDump 1.4.0) :

P11=CodeSafe 3.X

[CodeSafe 3.X]
L1=LOOK 89,04,8A
L2=ADD 5
L3=BP
L4=LOOK FF,E1,C3
L5=BP
L6=STEP
OPTL1=00000000
OPTL2=01010001
OPTL3=01010001
OPTL4=00010000
OPTL5=00000000

A partir de là, on a un fichier FruityPro.Exe décodé et qui marche, il n'y a plus qu'à le cracker comme il faut. Je vous laisse faire ça comme exercice ;)


Notes Finales

Ben c'était pas si terrible que ça en fin de compte, non ? J'espère que ce tut vous aura appris quelque chose, et que demain c'est vous qui en écrierez pour moi :) Blague à part, si vous avez des questions, envoyez moi un mail : fmi_ethan@iname.com.


Remerciements (pendant que j'y suis :):
- A mon maître : +Frog's Print (sans lui et ses tuts je serais encore à chercher des cracks sur le Net au lieu de les faire moi même ;)
- A tous les p'tits gars d'+HCU et à Fravia+ en particulier
- A toute l'équipe de ProcDump et G-RoM en particulier
- A tous les habitués du forum d'FP (je donne pas de noms, comme ça je suis sûr d'oublier personne ;)
- A mon Olivia bien aimée !!!

Ethan - Mars (Avril maintenant !) 1999