######{{{{{{{{|||||||||||||||||}}}}}}}}###### ~~éè$$$¤¤¤--)( KeyGen Tutorial )(--¤¤¤$$$éè~~ ######{{{{{{{{|||||||||||||||||}}}}}}}}###### Nom : Fluid Promotion Version : 1.0 Disponibilité : Http://www.fluidpoint.com Protections : packed,name+serial,nag,limitations Tools : Softice 4.0 Fploader 0.43 Tasm Brain/ganja etc.. FluidPromotion est un soft permettant de faciliter vos recherches sur le net. Je crois qu'on appelle ça un metacrawler, enfin bon c'est poa ce qui nous interresse ici . Le soft est protégé par des nags et des limitations .Il y a une option qui nous permet d'entrer un nom plus un serial . C'est ca qui est cool car on va keygener tout ça . L'algo est interressant et pas trop dur à la fois . Vous allez voir aussi pourquoi c'est pratique de coder un keygen en asm ... Step 1 : serial fishing alors la première fois qu'on lance le soft, y veut poa se charger si SI est en mémoire ,lol . C'est une detection par simple meltice. On va utiliser le soft de +Frog's print, FPloader 0.43 .De cette façon la détection de notre debugger favoris est out ... Bon on commence par aller catcher le serial . On va à l'option pour rentrer un name + le serial 123456789 (c important 9 chiffres) .On ne valide pas . On fait plutot surgir SI avant : CTRL D . Et on entre notre breakpoint : BPX HMEMCPY et on relance avec F5 . Boom! SI se déclenche .On est dans l'api HMEMCPY. Faut qu'on remonte à l'aide d'une backtrace , F12 . On appuie donc 12 fois sur F12 et on arrive à ceci : 015F:004F9FC1 CMP DWORD PTR [EBP-14],00 --- 12 fois F12,on arrive ici 015F:004F9FC5 JZ 004FA1E7------ saute si rien d'entré dans le nom(bad) 015F:004F9FCB LEA EDX,[EBP-18] 015F:004F9FCE MOV EAX,[EBP-04] 015F:004F9FD1 MOV EAX,[EAX+00000304] 015F:004F9FD7 CALL 00432520 015F:004F9FDC CMP DWORD PTR [EBP-18],00 015F:004F9FE0 JZ 004FA1E7----- saute si rien d'entré dans le serial(bad) 015F:004F9FE6 LEA EDX,[EBP-20] 015F:004F9FE9 MOV EAX,[EBP-04] 015F:004F9FEC MOV EBX,[EAX+00000304] 015F:004F9FF2 MOV EAX,EBX 015F:004F9FF4 CALL 00432520 015F:004F9FF9 MOV EAX,[EBP-20] Si vous avez bien appuyé 12 fois sur F12 vous avez du atterrir en 4F9FC1 . En continuant la trace avec F10, on arrive à ceci : 015F:004FA0A1 MOV BL,02 015F:004FA0A3 MOV EAX,[EBP-08] 015F:004FA0A6 CALL 00403E3C --- calcule la longueur du No de 015F:004FA0AB SUB EAX,09 serie entrée 015F:004FA0AE JZ 004FA0C1 ---ici 015F:004FA0B0 SUB EAX,02 015F:004FA0B3 JZ 004FA0C5 --- les 4 registrations 015F:004FA0B5 SUB EAX,02 015F:004FA0B8 JZ 004FA0C9 --- differentes 015F:004FA0BA SUB EAX,02 015F:004FA0BD JZ 004FA0CD --- ... 015F:004FA0BF JMP 004FA0CF 015F:004FA0C1 MOV BL,02 015F:004FA0C3 JMP 004FA0CF 015F:004FA0C5 MOV BL,03 015F:004FA0C7 JMP 004FA0CF 015F:004FA0C9 MOV BL,04 015F:004FA0CB JMP 004FA0CF 015F:004FA0CD MOV BL,05 015F:004FA0CF LEA EDX,[EBP-38] 015F:004FA0D2 MOV EAX,[EBP-04] 015F:004FA0D5 MOV EAX,[EAX+00000300] 015F:004FA0DB CALL 00432520 015F:004FA0E0 MOV EDX,[EBP-38]--- ici 015F:004FA0E3 LEA ECX,[EBP-34]--- on calcule le serial 015F:004FA0E6 MOV EAX,EBX ------ en fonction du nom 015F:004FA0E8 CALL 004FF464 ------ pour une registration 'Basic' 015F:004FA0ED MOV EAX,[EBP-34]--- et ici le bon serial 015F:004FA0F0 MOV EDX,[EBP-08]--- là le fake serial kon a entré 015F:004FA0F3 CALL 00403F4C ------ on compare les deux 015F:004FA0F8 JNZ 004FA1D8 ------ c poa bon ; on saute 015F:004FA0FE MOV DL,01 015F:004FA100 MOV EAX,[00489CBC] Bon en traçant avec F10,on arrive en 4FA0A3 .Cet endroit du code va calculer la longueur totale du serial (9 pour 123456789) . Et le call qui calcule ça est suivit de 4 sauts conditionnels .En fait , il y a 4 types de registration différentes: basic,standart,advanced et enterprise . Le soft determine selon le nombre de chiffres entrés dans le serial , quelle type de registration il doit calculer. Pour 9 chiffres c'est la registration basic, pour 11 chiffres la standart, pour 13 chiffres l'advanced et pour 15 chiffres l'enterprise . Nous on va s'interresser pour l'instant à la basic.En continuant à tracer avec F10, on arrive à l'addresse 4FA0E0.C'est la CALL 4FF464 qui va calculer le serial en fonction du nom et la longueur du serial qu'on a entré .Et à l'addresse 4FA0ED on trouve le bon serial dans EBP-34 et le serial bidon dans EBP-08 à l'addresse 4FA0F0. le CALL 403F4C compare les deux et le JNZ 004FA1D8 est effectué si la comparaison des deux serials n'est poa bonne . On est a peu près sur que c'est le CALL 4FF464 qui calcule le serial en fonction du nom . Y'a plus qu'a voir ce qui se passe dedans pour trouver l'algorythme ... Step 2 : l'algo ... C'est le CALL 4FF464 qui génère ne serial ,soit : 015F:004FF464 PUSH EBP 015F:004FF465 MOV EBP,ESP 015F:004FF467 PUSH 00 015F:004FF469 PUSH 00 015F:004FF46B PUSH 00 015F:004FF46D PUSH 00 015F:004FF46F PUSH 00 015F:004FF471 PUSH 00 015F:004FF473 PUSH EBX 015F:004FF474 PUSH ESI 015F:004FF475 PUSH EDI 015F:004FF476 MOV [EBP-08],ECX 015F:004FF479 MOV [EBP-04],EDX 015F:004FF47C MOV EBX,EAX 015F:004FF47E MOV EAX,[EBP-04] 015F:004FF481 CALL 00403FF0 --- ici on calcule la longueure du serial 015F:004FF486 XOR EAX,EAX 015F:004FF488 PUSH EBP 015F:004FF489 PUSH 004FF5B5 015F:004FF48E PUSH DWORD PTR FS:[EAX] 015F:004FF491 MOV FS:[EAX],ESP 015F:004FF494 MOV EAX,EBX 015F:004FF496 SUB AL,02 015F:004FF498 JZ 004FF4A8 --- registration 'Basic' 015F:004FF49A DEC AL 015F:004FF49C JZ 004FF4B7--- registration 'standart' 015F:004FF49E DEC AL 015F:004FF4A0 JZ 004FF4C6--- registration 'advanced' 015F:004FF4A2 DEC AL 015F:004FF4A4 JZ 004FF4D5 --- registration 'enterprise' 015F:004FF4A6 JMP 004FF4E2 015F:004FF4A8 LEA EAX,[EBP-14] 015F:004FF4AB MOV EDX,004FF5CC-------4FF5CC= LTE 015F:004FF4B0 CALL 00403C54 015F:004FF4B5 JMP 004FF4E2 015F:004FF4B7 LEA EAX,[EBP-14] 015F:004FF4BA MOV EDX,004FF5D8-------4FF5D8= STD 015F:004FF4BF CALL 00403C54 015F:004FF4C4 JMP 004FF4E2 015F:004FF4C6 LEA EAX,[EBP-14] 015F:004FF4C9 MOV EDX,004FF5E4-------4FF5E4 = PRO 015F:004FF4CE CALL 00403C54 015F:004FF4D3 JMP 004FF4E2 015F:004FF4D5 LEA EAX,[EBP-14] 015F:004FF4D8 MOV EDX,004FF5F0-------4FF5F0 - ENT 015F:004FF4DD CALL 00403C54 015F:004FF4E2 SUB BL,02 015F:004FF4E5 JZ 004FF4F5 015F:004FF4E7 DEC BL 015F:004FF4E9 JZ 004FF4FC 015F:004FF4EB DEC BL 015F:004FF4ED JZ 004FF503 015F:004FF4EF DEC BL 015F:004FF4F1 JZ 004FF50A 015F:004FF4F3 JMP 004FF50F 015F:004FF4F5 MOV EDI,00000009-- basic registration, EDI=9 015F:004FF4FA JMP 004FF50F 015F:004FF4FC MOV EDI,0000000B-- standart registration , EDI=B (11 en dec) 015F:004FF501 JMP 004FF50F 015F:004FF503 MOV EDI,0000000D-- Advanced registration , EDI=D (13 en dec) 015F:004FF508 JMP 004FF50F 015F:004FF50A MOV EDI,0000000F-- Enterprise registration , EDI=F (15 en dec) 015F:004FF50F LEA EAX,[EBP-10] 015F:004FF512 MOV ECX,004FF5FC-- 4FF5FC= FluidPromotion Version 1 015F:004FF517 MOV EDX,[EBP-14]-- EBP-14= LTE (pour basic registration) 015F:004FF51A CALL 00403E88------ recopie le contenu de 4FF5FC(FluidPromotion Version 1) à la suite de LTE . Bon cette partie de l'algo n'est pas dure a comprenndre .Le plus chiant c'est qu'il y a 4 registrations différentes.Bon si la longueur du serial entrée est egale à 9 on saute en 4FF4A8 , la registration basic . Et on va stocker LTE dans un endroit. Si la longeur du serial=11 on saute en 4FF4BA et on sotcke STD .Et ainsi de suite. Cherchez pas plus loin, c'est quattre groupes de lettres (LTE,SDT,PRO et ENT) servent à calculer le serial pour les 4 differentes registrations . En continunant la trace avec F10 on arrive encore à 4 tests pour determiner quelles registrations sont entrées (de 4FF4E2 à 4FF4F1) .En continuant à tracer on arrive en 4FF512 où il y a une case mémoire (4FF5FC) qui contient FluidPromotion Version 1 . Et le CALL 00403E88 de l'addresse 4FF51A va recopier FluidPromotion Version 1 à la suite de LTE, ca qui va nous donner cette chaine : LTEFluidPromotion Version 1 . Et juste derrière on tombe sur ça : 015F:004FF51F LEA EAX,[EBP-0C]- et ici on recopie LTEFluidPromotion Version 1 015F:004FF522 MOV ECX,[EBP-10]- à la suite notre nom. Donc pour moi : 015F:004FF525 MOV EDX,[EBP-04]- TaMaMBoLoLTEFluidPromotion Version 1 015F:004FF528 CALL 00403E88 015F:004FF52D XOR ESI,ESI 015F:004FF52F MOV EAX,[EBP-0C]- et la on calcule la longueur du nom+la chaine 015F:004FF532 CALL 00403E3C----- ajoutée. pour moi, 015F:004FF537 MOV EBX,EAX ----- ici EAX=24 en hexa soit la longueur de 015F:004FF539 TEST EBX,EBX------ TaMaMBoLoLTEFluidPromotion Version 1 015F:004FF53B JLE 004FF550 Le CALL 403E88 de l'addresse 4FF528 va ajouter la chaine LTEFluidPromotion Version 1 à la suite de notre nom, ce qui donne pour moi:TaMaMBoLoLTEFluidPromotion Version 1. Et juste derriere on calcule la longueur de la chaine finale : 24h pour moi . Maintenant que le programme a la chaine final(TaMaMBoLoLTEFluidPromotion Version1), il peut calculer le serial en fonction des lettres et du type de registration qu'on a chosit . Ce qui nous donne la routine suivante : 015F:004FF53D MOV EAX,00000001-- on prend le 1er caratère de la chaine 015F:004FF542 MOV EDX,[EBP-0C] 015F:004FF545 MOVZX EDX,BYTE PTR [EAX+EDX-01]-- on prend chaque caractère de la 015F:004FF54A ADD ESI,EDX------------------ chaine et on les additionne à ESI 015F:004FF54C INC EAX 015F:004FF54D DEC EBX 015F:004FF54E JNZ 004FF542-le traitement de la chaine est finie?non,on boucle Cette routine va additionner la valeur hexa de chaque lettre de la chaine TaMaMBoLoLTEFluidPromotion Version 1 et stocker le résultat de l'addition dans un registre ESI , dans notre cas . On remarke au passage que la routine qui prend les lettres du nom caractère par caractère ressemble furieusement à celle de La Calculatrice 4.51 et à celle de de Photoslider : MOVZX EDX,BYTE PTR [EAX+EDX-01]. Bon,une fois la boucle terminée on arrive à ceci : 015F:004FF550 MOV EAX,[00503C70]-on garde une place pour stocker le resultat 015F:004FF555 MOV [EAX],ESI-- ESI=D13=l'addition de tous les caractères 015F:004FF557 LEA EAX,[EBP-0C] 015F:004FF55A CALL 00403BBC 015F:004FF55F MOV EBX,EDI 015F:004FF561 DEC EBX 015F:004FF562 TEST EBX,EBX 015F:004FF564 JL 004FF587 -- ce saut n'est jamais effectué 015F:004FF566 INC EBX En 4FF550 on réserve une place pour stocker le serial final qui est pour l'instant dans ESI .Et en 4FF555 on met le serial final dans l'endroit qu'on lui a réservé à la ligne précédente . A cet instant, pour moi ESI=D13h . Et enfin on arrive au calcul du serial final : 015F:004FF567 MOV EAX,00000009--- ici on met eax à 9 et 015F:004FF56C CALL 00402B6C------- on calcule le serial final lettre/lettre 015F:004FF571 LEA EDX,[EBP-18] 015F:004FF574 CALL 00408C74--- et on 015F:004FF579 MOV EDX,[EBP-18]--- stocke la valeur Ascii du serial 015F:004FF57C LEA EAX,[EBP-0C]--- final 015F:004FF57F CALL 00403E44 015F:004FF584 DEC EBX 015F:004FF585 JNZ 004FF567 ---- finit ? non, on boucle 015F:004FF587 MOV EAX,[EBP-08] 015F:004FF58A MOV EDX,[EBP-0C]-- Le serial final dans EBP-0C ... 015F:004FF58D CALL 00403C10 015F:004FF592 XOR EAX,EAX 015F:004FF594 POP EDX 015F:004FF595 POP ECX 015F:004FF596 POP ECX 015F:004FF597 MOV FS:[EAX],EDX 015F:004FF59A PUSH 004FF5BC 015F:004FF59F LEA EAX,[EBP-18] 015F:004FF5A2 MOV EDX,00000004 015F:004FF5A7 CALL 00403BE0 015F:004FF5AC LEA EAX,[EBP-04] 015F:004FF5AF CALL 00403BBC 015F:004FF5B4 RET Cette partie de l'algo va faire une transformation de l'addition de tous les caratères de la chaine TaMaMBoLoLTEFluidPromotion Version 1. C'est le CALL 00402B6C de l'addresse 4FF56C qui va se charger de ça . On va jetter un coup d'oiel dedans : 015F:00402B6C IMUL EDX,[00504040],08088405 ---on fait une 015F:00402B76 INC EDX -----------------------petite operation 015F:00402B77 MOV [00504040],EDX-------------sur le 015F:00402B7D MUL EDX------------------------ serial et 015F:00402B7F MOV EAX,EDX--- ici EDX=la valeur hexa du serial final pour 015F:00402B81 RET un caractère Cette routine multiplie le contenu de 504040 (en fait c l'endroit où on avait stocké me résultat de l'addition de tous les caractères , pour moi CT egal à 0d13h) avec le registre EDX qu'on finit par multiplier par 8088405h .On fait encore une petite multiplication entre EDX et EAX (MUL EDX à l'addresse 402B7D) . Enfin à l'addresse 402B7F on a le premier chiffre du serial qui est mis dans EAX .Je rappelle que cette routine (le call 402b6c) va etre exécuté 9 fois car nous sommes dans le cas d'une registration basic . Pour calculer une registration standart, la chaine final sera pour moi TaMaMBoLoSTDFluidPromotion Version 1 et le call 402b6c sera effectué 11 fois. En fait c'est le call 402b6c qui est interressant . En effet additionner tous les caractères d'une chaine c'est facile à coder .Par contre la routine en 402b6c est un peu plus chiante . C'est pour ça que coder un keygen en asm c'est vachement pratique , vous allez voir ... Step 3 : keygener tout ça Je récapitule l'algorythme qui calcul le serial en fonction du nom : 1. Le programme va determiner combien de chiffers on a entrée pour notre serial 9 chiffres = registration basic 11 chiffres = registration standart 13 chiffres = registration advanced 15 chiffres = registration enterprise 2.Si serial=9 chiffres on stocke 'LTE' dans un endroit memoire Si serial=11 chiffres on stocke 'STD' dans un endroit memoire Si serial=13 chiffres on stocke 'PRO' dans un endroit memoire Si serial=15 chiffres on stocke 'ENT' dans un endroit memoire 3. On rajoute 'FluidPromotion Version 1' a la suite de 'LTE','STD','PRO','ENT' selon le cas .Ce qui donne pour une registration basic : LTEFluidPromotion Version 1 4. On rajoute la chaine calculée dans 3. à la suite de notre nom.Pour moi et dans le cas d'une registration basic :TaMaMBoLoLTEFluidPromotion Version 1 5. On ajoute tous les caractères en hexa de la chaine trouvée dans 4. . 6. On fait une dernière opération sur l'addition de tous les caractères . Bon,ba moi je me suis pas fait chier à recopier FluidPromotion Version 1 à la suite de LTE .Puisque l'addition hexa de tous les caractères de la chaine LTEFluidPromotion Version 1 sera toujours la meme, j'ai calculé ça une fois pour toute .Ensuite j'ai juste à additionner les lettres du nom et à additioner le tout avec le resultat de LTEFluidPromotion Version 1. Pour les 4 registrations différentes , l'addition donne cela : *Registration basic : LTEFluidPromotion Version 1=09f7h en hexa *Registration standart : STDFluidPromotion Version 1=09fDh en hexa *Registration advanced : PROFluidPromotion Version 1=0a03h en hexa *Registration enterprise : ENTFluidPromotion Version 1=09f9h en hexa Pour la petite operation je me suis pas fait chier j'ai repris celle qui était dans le prog ...héhéhé. Ce qui nous donne l'algo final : Key proc, Nom :dWord, Taille :Dword xor esi,esi ;on met ESI à 0 mov edx, Taille ;la taille de la chaine dans EDX mov eax, 1 ;on commence avec la première lettre : EAX=1 NextChar: mov edi, Nom ;le nom dans EDI movzx edi, byte ptr [edi+eax-1] ;Et on prend une lettre que l'on met dans EDI add esi, edi ;on additionned ESI & EDI inc eax ;on passe à la lettre suivante dec edx ;on soustrait -1 à la taille jne NextChar ;tous les caractères ont été traité ? non,on boucle ADD ESI,09f7h ;et on addtionne 9f7h au resultat de l'addition de ;tous les caractères de notre nom . ;remplacez par 09fDh pour standart registration ;par 0a03h pour advanced registration ;par 09f9h pour enterprise MOV EAX,[offset stockserial1] ;et on se reserve une place (stockserial1) ;pour stocker le serial afin de faire la ;deuxième transformation MOV [EAX],ESI ;et on fout le résultat de l'addition de ;toutes les lettre notre nom dans l'endroit ;qu'on a réservé xor ebx,ebx ;ici on commence la deuxième transformation ;du serial . J'ai EXACTEMENT repris la meme ;routine qui été dans le proggy : j'ai fait ;un copier/coller,lol. bcl: mov eax,9 call calcule ; voir plus bas inc ebx cmp ebx,9 ;on fait la boucle 9 fois pour une registration basic ;remplacer par 11 pour advanced registration, ;par 13 pour professionnal,et par 15 pour enterprise jz endbcl jmp bcl endbcl: ret ;have the ser, bye Key EndP calcule: IMUL EDX,[stockserial1],08088405h ;voilà,regardez le INC EDX ;desassemblage du step 2 MOV [stockserial1],EDX ;et vous verrez que c'est MUL EDX ;EXACTEMENT la meme routine que le proggy ADD EDX,030h ;j'additionne 30h pour convertir la valeur ;de EDX en valeur ASCII de façon à l'afficher ;à l'écran MOV [finalserial+EBX],EDX ;et on fout la valeur ASCII de chaque lettre ;dans un endroit memoire (finalserial) . ret héhéhé...C'est vraiment pratique l'asm... Pour le label 'Calcule' ,c'est un copier/coller de la routine du prog lui-meme...Pratique et terriblement efficace l'asm . Bon,il y a un truc dont j'ai pas parlé , c'est de la convertion du resultat hexa en valeur ASCII.C'est le 'call calcule' qui donne la valeur finale de chaque chiffre . En fait, c'est l'instruction MUL EDX qui donne un chiffre de 0 à 9 mais en hexa . Si vous essayez d'afficher le caractere ASCII 8 par exemple ca va poa etre joli (y'aura rien surtout).Il faut savoir que les nombres en ASCII vont des valeurs 30h pour le 0 à 039h pour le 9.Il suffit donc d'ajouter 030h a chaque chiffres pour avoir sa valeur ASCII . C'est le ADD EDX,030h qui se charge de cela . Ce coup-ci on a meme poa besoin de passer par l'api _wsprintfA. La j'ai configuré l'algo pour une registration basic, mais il ne tient qu'a vous de changer les paramètres pour vous enregistrer dans les différentes registrations .Le mieux c'est encore de faire un algo pour les 4 registrations,héhéhé.Jetez un coup d'oeil à l'exe contenu dans l'archive 'SourceKeygen_tutor3' . TaMaMBoLo.