Name/ Lucifer48 #/ 6260-603811 Name/ Lucifer48 #/ 11955-1267739 Name/ LUCIFER48 #/ 4788-326403 Name/ LUCIFER48 #/ 9758-842520 Programme : mIRC v5.31 32bit PlateForme : Windows 95/98 Date : Dimanche 15 novembre 1998, 14h41 Protection : Serialzzz Fichier : mirc32.exe Outils : Soft-ice v3.2 + W32dasm 8.9 Ou ça? : http://www.mirc.co.uk Temps passé: Quelques heures (comme d'hab) Cours : 20 Matos : Bloc-notes en 800*600 ================== 1. ACTE I: W32DASM ================== Menu Help, Register..., je remplis les cases et click sur "Register!", un message "mIRC Registration" me dit: "Sorry, your registration name and number don't match! Please make sure you're typing them in using the correct capitalization and spacing. Thanks!" Je desassemble mirc32.exe: je trouve une chaîne "Sorry, your registration name " qui a l'air d'être la bonne. * Possible StringData Ref from Data Obj ->"Your registration has been entered " ->"successfully." | :00437E4F 68C64D4B00 push 004B4DC6 :00437E54 8B4508 mov eax, dword ptr [ebp+08] :00437E57 50 push eax * Reference To: USER32.MessageBoxA, Ord:0000h | :00437E58 E89E440700 Call 004AC2FB :00437E5D B801000000 mov eax, 00000001 :00437E62 E9AE000000 jmp 00437F15 <---- Très intéressant... * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00437DFB(C) <---- Très intéressant aussi... | :00437E67 6A00 push 00000000 * Reference To: USER32.MessageBeep, Ord:0000h | :00437E69 E893440700 Call 004AC301 :00437E6E 68284E4B00 push 004B4E28 :00437E73 6A00 push 00000000 :00437E75 6A0C push 0000000C * Possible Reference to Dialog: DialogID_0033, CONTROL_ID:0083, "" | * Possible Reference to String Resource ID=00131: "Tile windows" | :00437E77 6883000000 push 00000083 :00437E7C 8B4508 mov eax, dword ptr [ebp+08] :00437E7F 50 push eax * Reference To: USER32.SendDlgItemMessageA, Ord:0000h | :00437E80 E822440700 Call 004AC2A7 :00437E85 682A4E4B00 push 004B4E2A :00437E8A 6A00 push 00000000 :00437E8C 6A0C push 0000000C * Possible Ref to Menu: MenuID_0012, Item: "Register..." | * Possible Reference to Dialog: DialogID_0033, CONTROL_ID:0082, "" | :00437E8E 6882000000 push 00000082 :00437E93 8B4508 mov eax, dword ptr [ebp+08] :00437E96 50 push eax * Reference To: USER32.SendDlgItemMessageA, Ord:0000h | :00437E97 E80B440700 Call 004AC2A7 :00437E9C 6A10 push 00000010 * Possible StringData Ref from Data Obj ->"mIRC Registration!" | :00437E9E 68C24E4B00 push 004B4EC2 * Possible StringData Ref from Data Obj ->"Sorry, your registration name " ;voilà ce que l'on cherchait ->"and number don't match!" | :00437EA3 682C4E4B00 push 004B4E2C :00437EA8 8B4508 mov eax, dword ptr [ebp+08] :00437EAB 50 push eax Comme souvent on a le schéma suivant 1) Bon serial ??? Si non vas en 3) Si oui va en 2) 2) J'enregistre le shareware JMP on_continue 3) Mauvais serial: petit cracker! Message: mauvais serial On voit qu'après le jmp 00437F15, il y a une adresse de saut conditionnelle, alons donc faire un tour en 00437DFB :00437DE2 E8C0440700 Call 004AC2A7 :00437DE7 68CC074C00 push 004C07CC :00437DEC 6810054C00 push 004C0510 :00437DF1 E8DAA40400 call 004822D0 :00437DF6 83C408 add esp, 00000008 :00437DF9 85C0 test eax, eax :00437DFB 746A je 00437E67 * Possible StringData Ref from Data Obj ->"mirc.ini" Si eax=0, il y saut donc c'est un mauvais serial. S'il n'y a pas de saut, alors on est enregistré, il y appel à USER32.DeleteMenu ... C'est tellement gros que c'est impossible de se tromper. On sait donc où tout ce fait, c'est maintenant que W32dasm passe la main à soft-ice pour voir un peu les deux calls qui précèdent cette instruction test eax,eax. Remarque: que celui qui nop le 'je' périsse en enfer... C'est du crack de bas étage... ============================= 2. ACTE II: SOFT-ICE EN FORCE ============================= Je lance mirc avec "Symbol Loader", je mets un BPX 00437DE2 et je click sur Register..., je remplis et click sur le boutton "Register!" et *boom*, je suis en plein dans soft-ice... Je recopie les même sept lignes (que ci-dessus) avec soft-ice: XXXX:00437DE2 E8C0440700 CALL USER32!SendDlgItemMessageA XXXX:00437DE7 68CC074C00 PUSH 004C07CC ;mon serial XXXX:00437DEC 6810054C00 PUSH 004C0510 ;mon nom XXXX:00437DF1 E8DAA40400 CALL _CheckRegMatch XXXX:00437DF6 83C408 ADD ESP,08 XXXX:00437DF9 85C0 TEST EAX,EAX XXXX:00437DFB 746A JZ 00437E67 Là, on peut pas se tromper! c'est plus que clair... Allons dans le CALL _CheckRegMatch; je ne résiste pas à l'envie de mettre l'intégralité de la routine: _CheckRegMatch XXXX:004822D0 55 PUSH EBP XXXX:004822D1 8BEC MOV EBP,ESP XXXX:004822D3 53 PUSH EBX XXXX:004822D4 56 PUSH ESI XXXX:004822D5 57 PUSH EDI XXXX:004822D6 8B750C MOV ESI,[EBP+0C] ;mon nom XXXX:004822D9 8B5D08 MOV EBX,[EBP+08] ;mon serial XXXX:004822DC 53 PUSH EBX ;sauvegarde de mon serial XXXX:004822DD E87E1D0200 CALL _strlen ;ça veut pas dire string length ??? XXXX:004822E2 59 POP ECX ;ressort l'adresse de mon serial XXXX:004822E3 83F805 CMP EAX,05 XXXX:004822E6 7304 JAE 004822EC ;si serial >=5, alors c'est OK XXXX:004822E8 33C0 XOR EAX,EAX ;mauvais serial XXXX:004822EA EB77 JMP 00482363 ;fin de la routine XXXX:004822EC 56 PUSH ESI ;mon serial XXXX:004822ED 53 PUSH EBX ;mon nom XXXX:004822EE E8FDFEFFFF CALL _checknormreg ;<---- à explorer XXXX:004822F3 83C408 ADD ESP,08 XXXX:004822F6 85C0 TEST EAX,EAX ;bon serial ? XXXX:004822F8 7407 JZ 00482301 XXXX:004822FA B801000000 MOV EAX,00000001 ;c'est un bon serial XXXX:004822FF EB62 JMP 00482363 ;fin de la routine XXXX:00482301 56 PUSH ESI ;mon serial XXXX:00482302 BEC4D64C00 MOV ESI,004CD6C4 XXXX:00482307 8BFB MOV EDI,EBX ;mon nom XXXX:00482309 33C0 XOR EAX,EAX XXXX:0048230B 83C9FF OR ECX,-01 ;ECX=FFFFFFFF XXXX:0048230E F2AE REPNZ SCASB XXXX:00482310 F7D1 NOT ECX ;ECX= taille du nom+1 XXXX:00482312 2BF9 SUB EDI,ECX ;EDI pointe vers mon nom XXXX:00482314 87F7 XCHG ESI,EDI XXXX:00482316 8BC7 MOV EAX,EDI XXXX:00482318 8BD1 MOV EDX,ECX ;taille de mon nom+1 XXXX:0048231A C1E902 SHR ECX,02 ;div entière par 4 XXXX:0048231D F3A5 REPZ MOVSD ;copie de ESI->EDI (par 4 octets) XXXX:0048231F 8BCA MOV ECX,EDX ;taille du nom+1 XXXX:00482321 83E103 AND ECX,03 XXXX:00482324 F3A4 REPZ MOVSB ;recopie le reste du nom XXXX:00482326 5E POP ESI ;mon serial XXXX:00482327 6A02 PUSH 02 XXXX:00482329 68C4D64C00 PUSH 004CD6C4 ;endroit de la copie de mon nom XXXX:0048232E E819C1FBFF CALL _encrypt ;<---- à explorer XXXX:00482333 83C408 ADD ESP,08 XXXX:00482336 56 PUSH ESI ;mon serial XXXX:00482337 68C4D64C00 PUSH 004CD6C4 ;mon nom encrypté XXXX:0048233C E8AFFEFFFF CALL _checknormreg XXXX:00482341 83C408 ADD ESP,08 XXXX:00482344 85C0 TEST EAX,EAX ;bon serial ? XXXX:00482346 7407 JZ 00482363 XXXX:00482348 B801000000 MOV EAX,00000001 ;c'est ok! XXXX:0048234D EB14 JMP 00482363 ;fin de la routine XXXX:0048234F 56 PUSH ESI ;mon serial XXXX:00482350 E823FEFFFF CALL _checkcnetreg ;<---- à explorer XXXX:00482355 59 POP ECX ;ressort mon serial XXXX:00482356 85C0 TEST EAX,EAX XXXX:00482358 7407 JZ 00482361 ;si EAX=0 alors mauvais serial XXXX:0048235A B801000000 MOV EAX,00000001 XXXX:0048235F EB02 JMP 00482363 ;on saute 2 octets XXXX:00482361 33C0 XOR EAX,EAX XXXX:00482363 5F POP EDI XXXX:00482364 5E POP ESI XXXX:00482365 5B POP EBX XXXX:00482366 5D POP EBP XXXX:00482367 C3 RET ;FIN C'est assez simple: on a trois calls nouveaux à explorer: _checknormreg _encrypt _checkcnetreg En fait on a 3 possibilités pour sortir de ce call avec EAX=1. La première (la plus simple) n'encrypte pas notre nom et appelle _checknormreg La deuxième après l'appel à _encryp et reexécute _checknormreg La troisième, appel à _checkcnetreg Petit tour dans le call _checknormreg J'ai la flemme de tout taper donc, je tronque un peu le début. Il y a deux boucles principales. Avant "...": un call _strchr a coupé en deux le serial (c'est à dire qu'on doit avoir un serial du type 1234-5678), un autre call _atol a converti en hexa ces deux valeurs. Remarque: si il n'y a pas de caractère "-" dans le serial on dégage. ... XXXX:0048225C 0FB631 MOVZX ESI,BYTE PTR [ECX] XXXX:0048225F 0FAF348544BB4B00 IMUL ESI,[EAX*4+_reglock] ;lit "i","f","e","r","4","8" XXXX:00482267 03DE ADD EBX,ESI XXXX:00482269 40 INC EAX XXXX:0048226A 83F826 CMP EAX,26 XXXX:0048226D 7E02 JLE 00482271 XXXX:0048226F 33C0 XOR EAX,EAX ;nom contenant trop de caractères XXXX:00482271 42 INC EDX XXXX:00482272 41 INC ECX ;ECX pointe sur mon nom XXXX:00482273 3B55FA CMP EDX,[EBP-0C] XXXX:00482276 7CE4 JL 0048225C XXXX:00482278 3B5DFC CMP EBX,[EBP-04] ;compare le résultat trouvé avec la partie gauche de notre serial XXXX:0048227B 7404 JZ 0048225C XXXX:0048227D 33C0 XOR EAX,EAX XXXX:0048227F EB45 JMP 004822C6 XXXX:00482281 33C0 XOR EAX,EAX XXXX:00482283 33DB XOR EBX,EBX C'est la première boucle qui calcule une sorte de checksum, on multiplie chaque caractère par une valeur _reglock (des valeurs fixées en mémoire). C'est la première verification (avec la partie gauche du serial) Remarque: cettre première boucle commence à partir du 4ème caractère. En XXXX:0048227B noter la valeur de EBX et covertir en décimal, on a la première moitié du serial... XXXX:00482295 0FB631 MOVZX ESI,BYTE PTR [ECX] ;lit les lettres de mon nom... XXXX:00482298 0FB679FF MOVZX EDI,BYTE PTR [ECX-01] XXXX:0048229C 0FAFF7 IMUL ESI,EDI XXXX:0048229F 0FAF348544BB4B00 IMUL ESI,[EAX*4+_reglock] XXXX:004822A7 03DE ADD EBX,ESI XXXX:004822A9 40 INC EAX XXXX:004822AA 83F826 CMP EAX,26 ;même bla-bla qu'en haut XXXX:004822AD 7E02 JLE 004822B1 XXXX:004822AF 33C0 XOR EAX,EAX ;pas très bon de passer ici... XXXX:004822B1 42 INC EDX XXXX:004822B2 41 INC ECX XXXX:004822B3 3B55F4 CMP EDX,[EBP-0C] ;EDX=indice de boucle XXXX:004822B6 7CDD JL 00482295 XXXX:004822B8 3B5DF8 CMP EBX,[EBP-08] ;Noter la valeur d'EBX XXXX:004822BB 7404 JZ 004822C1 Ca ressemble pas mal à la première boucle... un petite différence, on se sert ici du caractère précedent [ECX-01], l'indice de boucle commence toujours à 3. De la même façon en XXXX:004822BB noter la valeur de EBX et covertir en décimal, on a la deuxième moitié du serial. Donc un bon serial... Remarque: les deux premières lettres du nom de servent à rien. Voilà on a fini avec la routine "_checknormreg" ================ 3. DERNIERS MOTS ================ Est-ce vraiment la peine d'aller voir dans la routine _encrypt ??? J'ai jeté un coup d'oeuil.. ça a l'air chiant (des nouvelles routines _reverse, _swap, _rand) Pour le call _checkcnetreg c'est assez facile, on se sert que des caractères composant le serial c'est sur le même prince que la boucle ci-dessus, on multiplie... On va donc s'arrêter là. Denière petite chose, on s'apperçoit que le fait de lancer le "symbol loader" sert à quelque chose: ========================= C:\mirc\mirc32.exe opened successfully Loading symbols for C:\mirc\mirc32.exe. . . Symbols for C:\mirc\mirc32.exe successfully loaded Loading module C:\mirc\mirc32.exe. . . Module C:\mirc\mirc32.exe successfully loaded Au lieu d'avoir un "CALL _CheckRegMatch" on a un "CALL 004822D0" qui n'est pas très parlant. Moralité de ce tutorial: surgir dans le code via CTRL+D n'est pas toujours l'idéal... Lancer le loader de soft-ice, peut parfois nous aider... Lucifer48