Name/ Lucifer48 #/ 4CAD0E4B028D4744 Programme : WinRAR v2.05 PlateForme : Windows 95/98 Date : Samedi 6 mars 1999 (premier tut de l'année 99) Protection : Serialzzz Fichier : winrar95.exe Outils : Soft-ice v3.24 Ou ça? : www.shareware.com Temps passé: 10 heures (un journée) Cours : 21 Matos : Bloc-notes en 800*600 (moi je suis en 1024*768 en grosses polices) Ce tutorial est loin d'être complet! J'ai fait ce que j'ai pu, mais je crois que je ne suis pas assez bon cracker (manque d'expérience) pour pouvoir tout expliquer, expliquer la protection de winrar est relativement complexe. J'ai essayé de faire ce que j'ai pu. ================================ 1. LOCALISATION DE LA PROTECTION ================================ Je remplie les cases de la façon suivante: Enter your registration (AV) text/ Lucifer48 Enter your regisrtation code/ 361578009911 Cette phase est carrément simple car après deux rituels "CALL USER32!GetDlgItemTextA" on tombe directement sur la protection: XXXX:00413C47 83C408 ADD ESP,08 XXXX:00413C4A 8D8D54FFFFFF LEA ECX,[EBP-00AC] ;mon serial XXXX:00413C50 51 PUSH ECX XXXX:00413C51 8D459C LEA EAX,[EBP-64] ;mon nom XXXX:00413C54 50 PUSH EAX XXXX:00413C55 E84B68FFFF CALL 0040A4A5 ; <----- méchant XXXX:00413C5A 83C408 ADD ESP,08 ; dé"pop" les deux arguments XXXX:00413C5D 85C0 TEST EAX,EAX XXXX:00413C5F 7532 JNZ 00413C96 ;si EAX=0, mauvais serial Notre mission est donc de sortir du CALL 0040A4A5 avec EAX non nul (EAX=1 en règle générale). ============== 2. A L'ATTAQUE ============== Zou, on entre dans le CALL 0040A4A5. Le call commence avec quelques menues vérifications, on remarque que, qu'il ne faut qu'on évite une certaine instruction "JMP 0040A785"... F10, F10, F10,... on est ici: --->:0040A595 33D2 XOR EDX,EDX XXXX:0040A597 8A10 MOV DL,[EAX] ;eax pointe vers mon nom XXXX:0040A599 3155F8 XOR [EBP-08],EDX ;xorification des caractères de mon nom XXXX:0040A59C 43 INC EBX ;indice de boucle++ XXXX:0040A59D 40 INC EAX ;caractère suivant XXXX:0040A59E 3B5DFC CMP EBX,[EBP-14] ;fini? XXXX:0040A5A1 7CF2 JL 0040A595 Pour moi, j'obtient l'octet "4E" Une autre boucle suit, et procède à quelques additions sur mon nom: L u c i f e r 4 8 4C 75 63 69 66 65 72 34 38 00 00 00 00 00 00 00 ... devient (après cinq boucles): 4C 75 63 69 66 4C 75 63 69 66 65 72 34 38 00 65 72 34 38 -- -- -- -- -- -- -- -- -- FD 5C FA 0A CC 65 72 34 38 <----- une petite encrytion maison! Je saute volontairement un bout du code pour mieux y revenir ensuite: Voici la fin du call (l'endroit du test clé, si vous préférez) XXXX:0040A6FF 8D9574FFFFFF LEA EDX,[EBP-008C] XXXX:0040A705 52 PUSH EDX ;nom encodé (FD 5C FA 0A CC ...) XXXX:0040A706 FF3504BF4200 PUSH DWORD PTR [042BF04] ;serial encodé XXXX:0040A70C E833280100 CALL 0041CF44 ;comparaison XXXX:0040A711 83C40C ADD ESP,0C XXXX:0040A714 85C0 TEST EAX,EAX XXXX:0040A716 0F94C1 SETZ CL :CL=00 ou CL=01 selon la retenue (ZF) XXXX;0040A719 83E101 AND ECX,01 XXXX:0040A71C 890D5C574200 MOV [0042575C],ECX ;il faut que ECX=1 et c'est un bon serial ... Pour être enregistré, il faut que le serial encodé soit égal au nom encrypté. Résumons nous: * Pour mon nom j'ai: FD 5C FA 0A CC 65 72 34 38 00 00 00 00 ... * Pour mon serial j'ai: 18 10 17 2D 1F 00 00 00 00 00 00 00 00 ... ça ne va donc pas. Pour être ok, un bon serial encrytpé aurait été: FD 5C FA 0A CC 65 72 34 38 mais, comme le call 0041cf44 effectue que cinq boucles, le serial (toujours encodé): FD 5C FA 0A CC doit être celui-ci. esi pointe vers notre serial XXXX:0040A5F4 803E39 CMP BYTE PTR [ESI],39 XXXX:0040A5F7 7611 JBE 0040A60A ;un chiffre ou une lettre? XXXX:0040A5F9 33C0 XOR EAX,EAX XXXX:0040A5FB 8A06 MOV AL,[ESI] ;lecture du caractère XXXX:0040A5FD 50 PUSH EAX XXXX:0040A5FE E809810100 CALL 0042270C XXXX:0040A603 59 POP ECX XXXX:0040A604 04C9 ADD AL,C9 ;traitement pour une lettre XXXX:0040A606 8806 MOV [ESI],AL ;écriture du caractère XXXX:0040A608 EB03 JMP 0040A60D ;on saute 3 octets XXXX:0040A60A 8006D0 ADD BYTE PTR [ESI],D0 ;traitement pour un chiffre XXXX:0040A60D 43 INC EBX ;indice de boucle++ XXXX:0040A60E 46 INC ESI ;caractère suivant XXXX:0040A60F 3BFB CMP EDI,EBX XXXX:0040A611 7FE1 JG 0040A5F4 ;loopy... C'est évident mais je fais quand même un exemple: 3 6 1 5 7 8 0 0 9 9 1 1 33 36 31 35 37 38 30 30 39 39 31 31 devient: 03 06 01 05 07 08 00 00 09 09 01 01 (évident non? de même, la lettre "A" (41h) devient 0A...) Juste après, le serial subit encore quelques modifications. Il y a encore une boucle (0040A61F - 0040A63F), qui réalise la chose suivante: 03 06 01 05 07 08 00 00 09 09 01 01 ----- ----- ----- ----- ----- ----- 36 15 78 00 99 11 4E 4E 4E 4E 4E 4E xor avec 4E (obtenu à partir du nom) 78 5B 36 4E D7 5F <--------- serial encodé qu'est-ce qui se passe jusqu'à l'obtention de 18 10 17 2D 1F XXXX:0040A6B2 6A00 PUSH 00 XXXX:0040A6B4 6800100000 PUSH 00001000 XXXX:0040A6B9 FF353C574200 PUSH DWORD PTR [0042573C] ;emplacement final du serial encodé XXXX:0040A6BF E8709EFFFF CALL 00404534 ;<-------- TRES IMPORTANT XXXX:0040A6C4 83C40C ADD ESP,0C ... ... comparaison XXXX:0040A6FF (voir ci-dessus) ============================ 3. PHASE FINALE D'ENCRYPTION ============================ C'est là que les choses se corsent! Analysons le call 00404534, on entre tout de suite dans le call 00410F8C Encore une transformation du serial! En XXXX:00410FE3 CALL 0040E51E Dans le call 0040FA3C (en XXXX:00403952) chaque octet et retranché par un indice de boucle ainsi 78 5B 36 4E D7 5F devient 75 57 31 48 D0 57 (78-3=75 / 5B-4=57 / 36-05=31 /...) On peut maintenant revenir au call 00410F8C principal Voilà la boucle principale: XXXX:0041103B 8127FFFF0F00 AND DWORD PTR [EDI],000FFFFF XXXX:00411041 813D... CMP DWORD PTR [004318F8],00001FE2 XXXX:0041104B 7608 JBE 00411055 ... ... XXXX:00411110 833DCC8142... CMP DWORD PTR [004281CC],00 XXXX:00411117 0F8D1EFFFFFF JGE 0041103B ;boucle ... RET Dans cette boucle, le call important est le CALL 004118AF, en effet celui ci détermine l'encyption finale du serial. A partir de l'encrytion 75 57 31 48 D0 57, on procède à 5 boucles (755731 SHR 8 ) AND FFFF = 75 57 (755731 SHR 2 ) AND FFFF = 55 CC (573148 SHR 4 ) AND FFFF = 73 14 (3148D0 SHR 6 ) AND FFFF = C5 23 (48D057 SHR 7 ) AND FFFF = 91 A0 Attention les SHR 8,2,4,... varient ce ne sont pas ceux-là tout le temps. Remarque1: il nous faut donc dans ce cas 6 octets minimum (soit un serial de 12 caractères) car sinon la lecture des 3 caractères pointerait en mémoire n'importe où. (mais encore une fois ca dépend)! Un paramètre en plus intervient: XXXX:00411B34 015D00 ADD [EBP+00],EBX XXXX:00411B37 8B4500 MOV EAX,[EBP+00] XXXX:00411B3A C1E808 SHR EAX,08 XXXX:00411B3D 294500 SUB [EBP+00],EAX donc en (ebp+0) y'a un mot (un word) qui determine quels arguments donner à donner au call 00411EB0. (voir juste après). Dans ce call 004118AF toujours, il y a encore un call 00411EB0 qui est interessant en effet, il détermine a partir d'un paire d'octet la valeur FINALE d'un nouvelle octet. Exemple 75 57 ==[CALL 00411EB0 (en XXXX:00411981)]==> 18 PS: n'oublions pas qu'on doit obtenir les cinq octets suivants: FD 5C FA 0A CC XXXX:00411EE8 A3FC184300 MOV [004318FC],EAX XXXX:00411EED B910000000 MOV ECX,00000010 XXXX:00411EF2 2BCA SUB ECX,EDX XXXX:00411EF4 85DB TEST EBX,EBX XXXX:00411EF6 7409 JZ 00411F01 XXXX:00411EF8 8B4510 MOV EAX,[EBP+10] XXXX:00411EFB 8B4498FC MOV EAX,[EBX*4+EAX-04] XXXX:00411EFF EB02 JMP 00411F03 XXXX:00411F01 33C0 XOR EAX,EAX XXXX:00411F03 50 PUSH EAX XXXX:00411F04 8BC6 MOV EAX,ESI XXXX:00411F06 5B POP EBX XXXX:00411F07 2BC3 SUB EAX,EBX XXXX:00411F09 D3E8 SHR EAX,CL ;(*) obtenu par 10-edx XXXX:00411F0B 8B4D14 MOV ECX,[EBP+14] XXXX:00411F0E 030491 ADD EAX,[EDX*4+ECX] ;(**) XXXX:00411F11 5E POP ESI XXXX:00411F12 5B POP EBX XXXX:00411F13 5D POP EBP XXXX:00411F14 C3 RET Soit 'V' le mot fournie en argument du call 00411EB0 (en XXXX:00411981) (exemple: V=75 57) Valeur de 'V' (*) (**) [0 2000[ EDX=5 SHR EAX,B variable malheureusement! [2000 C000[ EDX=6 SHR EAX,A Aller pointer en [edx*4+ecx] [C000 E000[ EDX=7 SHR EAX,9 afin d'obtenir les valeurs! [E000 F000[ EDX=8 SHR EAX,8 [F000 F200[ EDX=9 SHR EAX,7 [F200 F7E0[ EDX=B SHR EAX,5 [F7E0 FFFF[ EDX=C SHR EAX,4 Quelques exemples du call 00411EB0 (ne pas oublier que le premier quartet est ignoré, un 1234 équivaut à un 1230). call 00411EB0 à l'adresse 00411981 * call 00411EB0 à l'adresse 0041195E * 1230 ==[call 00411EB0]==> 02 * 5000 ==[call 00411EB0]==> B5 ECE0 ==[call 00411EB0]==> CE * 8000 ==[call 00411EB0]==> 35 EEE0 ==[call 00411EB0]==> 4A * E000 ==[call 00411EB0]==> B5 EF00 ==[call 00411EB0]==> 4B * E500 ==[call 00411EB0]==> BF F000 ==[call 00411EB0]==> 4C * EA00 ==[call 00411EB0]==> C9 F100 ==[call 00411EB0]==> 4E * EC00 ==[call 00411EB0]==> CD F200 ==[call 00411EB0]==> 50 * F000 ==[call 00411EB0]==> DE F2F0 ==[call 00411EB0]==> 57 * F3A0 ==[call 00411EB0]==> 5D * Rem: j'aurais du faire un tableau, F3B0 ==[call 00411EB0]==> 5D * s'eut été plus clair... F3C0 ==[call 00411EB0]==> 5E F3E0 ==[call 00411EB0]==> 5F F400 ==[call 00411EB0]==> 60 F500 ==[call 00411EB0]==> 68 F600 ==[call 00411EB0]==> 70 FC00 ==[call 00411EB0]==> F1 FC40 ==[call 00411EB0]==> C5 FCE0 ==[call 00411EB0]==> F4 FCF0 ==[call 00411EB0]==> D0 FD00 ==[call 00411EB0]==> D1 FE00 ==[call 00411EB0]==> E1 FF00 ==[call 00411EB0]==> F1 FFC0 ==[call 00411EB0]==> FD FFD0 ==[call 00411EB0]==> FE FFE0 ==[call 00411EB0]==> FF FFF0 ==[call 00411EB0]==> 100 Dernière chose après ce call 00411EB0, il y a une instruction dec EBX, qui est retranché au résultat (finalement FFF0 est encodé en FF). Je met l'adresse du call 00411EB0 car il y en a 4 différents (dépend des arguments). Pour savoir lequel des 4, va être exécuté; ça dépend en fait de [EBP+00], il y a 4 fourchettes: 0DFF / 35FF / 5DFF / 75FF Valeur de [EBP+00]: le programme ce sert du résultat de l'octet obtenu avec le call 00411EB0. Extrait du code en question: ADD [EBP+00], EBX ;ebx contient l'octet du résultat de l'un des 4 call 00411EB0. MOV EAX,[EBP+00] SHR EAX,08 SUB [EBP+00],EAX ======================== 4. TROUVER UN BON SERIAL ======================== On a tout les éléments pour trouver un bon serial: on doit obtenir. Comme on ne sait pas ce que va renvoyer la call 00411EB0 (Rem : j'aurais du vraiment faire un tableau pour savoir...), il faut procéder petit à petit, on modifie le serial, on avance, on recommence, mais on peut pas juste essayer le call 00411EB0 avec des valeurs, car ça dépend des arguments. FD 5C FA 0A CC + 1 1 1 1 1 ---------------- FE 5D FB 0B CD Soit x un quartet quelconque (i.e. xx est un octet quelconque). (FFDxxx SHR 8) AND FFFF = FFDx donc si V=FFDx ==[call 00411EB0]==> FE On aurait un truc du genre FF D0 xx xx xx + 3 / +4 / +5 / +... 02 D4 xx xx xx xor 4E: 4C 9A xx xx xx On expérimente un nouveau serial: 4C9A123456 (la premiere boucle marche) j'obtient une encryption du serial: (DF3Axx SHR 4) AND FFFF =F3A0 et F3A0 ==[call 00411EB0]==> 5D On aurait un truc du genre FF DF 3A xx xx +3 / +4 / +5 / +... 02 E3 3F xx xx xor 4E: 4C AD 71 xx xx On expérimente un nouveau serial: 4CAD715555 (deux boucles marchent) (3BFF40 SHR 1) AND FFFF = FFAx ==[call 00411EB0]==> FB On aurait un truc du genre FF DF 3B FF 40 +3 / +4 / +5 / +... 02 E3 40 05 47 xor 4E: 4C AD 0E 4B 09 On expérimente un nouveau serial: 4CAD0E4B09 (trois boucles marchent) (45A000 SHR 5) AND FFFF = 2D0x ==[call 00411EB0, en 41195E]==> 0B On aurait un truc du genre FF DF 3B FF 45 A0 00 +3 / +4 / +5 / +... 02 E3 40 05 4C A8 09 xor 4E: 4C AD 0E 4B 02 E6 47 On expérimente un nouveau serial: 4CAD0E4B02E647 (quatre boucles marchent) (BB0000 SHR 6) AND FFFF = EC00 =[call 00411EB0, en 41195E]==> CD On aurait un truc du genre FF DF 3B FF 45 BB 00 00 +3 / +4 / +5 / +... 02 E3 40 05 4C C3 09 0A xor 4E: 4C AD 0E 4B 02 8D 47 44 On expérimente un nouveau serial: 4CAD0E4B028D4744 (youpi!!!!!!!!!! ça marche) bpx importants: =============== XXXX:0040A6BF :call global XXXX:0041108D :call encryption serial XXXX:004118D1 :3->2 XXXX:00411981 :2->1 XXXX:00411B79 :écriture de l'octet ============= 5. CONCLUSION ============= Seul moyen pour trouver un serial, il faut y aller petit à petit. Tracer, tracer et tracer. En plus j'avait pas de calculatrice sous la main, et j'ai été obligé d'utiliser celle de w98. Donc ça facilite pas les choses... Y'aurait moyen de sortir une formule qui détermine le résultat du call 00411EB0 mais désolé je n'ai pas le temps, et de+ je n'est que 10 mois de crack derrière moi, je suis encore un newbie... Mais finalement, l'important c'est d'avoir trouvé une serial qui marche! lucifer48@yahoo.com