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.
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 !
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