Introduction:
Dans ce tutoriel nous allons voir du keygenning, ou plutot le principe du keychoosing, car l'application en question ne calcule rien!
Les outils:
OllyDbg v2.01 (http://Ollydbg.de/)
Detect It Easy (https://github.com/horsicq/DIE-engine/releases)
ADSR v5.0 (http://www.adrosoft.com/ADStreamRecorder5.exe)
I: Démarrage
On va faire le train-train habituel: installez l'application, scanné la avec DiE, ça ne semble pas compressé, super.
Voyons à quoi ressemble l'application en version d'évaluation maintenant. On l'ouvre, nous avons 'Unregistered' dans le titre de la fenêtre, ok
Pour s'enregistrer, il faut aller dans le menu 'Help' et cliquer sur 'Register...'
Une boîte de dialogue apparaît, essayons de nous enregistrer avec un serial bidon pour voir si un message d'erreur apparait..
Incorrect Code!
Bien, c'est parfait.
II: Trouver la procédure d'enregistrement
Chargez l'application dans le débogueur, puis allons chercher la chaîne de texte qu'on l'on a vu pour le mauvais serial.
Cliquez avec le bouton droit de la souris puis: Search for>All referenced strings
Appuyez ensuite sur Ctrl+F pour ouvrir la fenêtre de recherche, et recherchez "Incorrect Code!"
Nous avons un résultat, double-cliquez dessus
Nous examinons la procédure actuelle dans laquelle nous sommes et...
ça sent bon, il semble que nous sommes directement dans le segment d'enregistrement.
III: Comprendre la routine d'enregistrement
Mettez un point d'arrêt au début de la procédure (en 49C5A4)
Ensuite, lancez l'application avec F9 et essayez de vous enregistrer à nouveau avec un serial bidon.
Une fois avoir cliquer sur le bouton 'Register', le débogueur break, nous pouvons maintenant commencer à tracer le code de la procédure.
Nous le voyons récupérer la première partie de notre faux numéro de série, ça longueur et comparer avec zéro: si c'est bon on continue, sinon il quitte le segment.
Ensuite, nous entrons dans une boucle, un pointeur vers une chaine de texte "1014" et mis dans EDI, puis le programme reprend notre faux serial avec POP EAX et entre dans une procédure.
Voyons ce qui se passe dans cette procédure, entrez dedans avec F7 (Step into) une fois sur l'adresse 49C619 (CALL 00404498)
Nous sommes maintenant en 00404498, qui semble être appelé à partir de beaucoup d'endroits!
Continuons à tracer avec F8, nous rencontrons rapidement une comparaison
0040449B |. 89C6 MOV ESI,EAX ; ASCII "aaaa" 0040449D |. 89D7 MOV EDI,EDX 0040449F |. 39D0 CMP EAX,EDX ; ASCII "1014" 004044A1 |. /0F84 8F000000 JE 00404536
Notre première partie de notre serial bidon est comparée à 1014, si c'est conforme alors on quitte la procédure.
Nous continuons de tracer car notre bout de serial n'est pas le même, et nous sommes rapidement éjectés après une comparaison de caractères plus loin.
De retour sur le segment principal, nous continuons à tracer jusqu'à la fin de la boucle, juste avant de prendre le saut conditionnel de la boucle on observe le code.
On a une instruction ADD EDI, 5, qui incrémente EDI de 5, qui lui contient actuellement un pointeur sur la chaine en hard "1014"
Sur l'instruction suivante on a une décrémentation pour un pointeur dans [EBP-8] qui contient 32 (50 en décimal)
Jetons un coup d'œil dans la fenêtre de dump, CTRL+G et on entre 004A69C0 (notre nouveau pointeur contenu dans EDI)
Alors nous avons la... une table de numéro de série! et combien y en a-t-il? ? 50!
Donc pas de calcul ici, notre première partie doit simplement correspondre à une de ses 50 premières parties contenus dans cette table.
Et comme vous avez probablement remarqué aussi dans la fenêtre de dump, il y a une seconde table juste en dessous avec des nombres entiers plus grands.
En devinant, cela pourrait concerner simplement la deuxième partie du serial.
C'est ce que nous allons vérifier, reprenez l'exécution de l'application et re-entrer un serial bidon, mais avec une bonne première partie, par exemple: 1014
Cette fois les comparaisons sont bonnes, nous ne prenons pas le saut d'éjection de la première partie et nous continuons sur la deuxième partie du traitement du numéro de série.
Tout est similaire les mêmes procédures sont appeler, mais cette fois avec un pointeur sur la deuxième table du serial.
Le pointeur du serial valide et contenu dans EDX.
L'instruction POP EAX en dessous ne change pas pour sont utilisation ici: ça restaure la deuxième partie de notre serial bidon.
À la fin avant la boucle de la deuxième partie, EBX est incrémenté de 0B (11 en décimal), cela met à jour le pointeur de EBX pour le serial suivant de la table.
Sur la ligne suivante, ESI et décrémenté, c'est le compteur pour savoir où en sommes-nous dans la table), il indique également 50 en décimal, nous avons donc également une table de 50 serials pour la deuxième partie.
Nous avons maintenant terminé le segment d'enregistrement.
IV: Faire un keygen
Tout est relatif, cela dépend de ce que vous appelez un 'Keygen'
Il n'y a pas de calcul a faire ici vu que les serials sont en hard, j'ai tendance à appeler ce genre de keygen un «keychooser», car on ne calcule rien, on a juste a tiré deux serial de la table aléatoirement et d'assembler le résultat.
Quoi qu'il en soit chacun voit midi a ça porte, bref.
Pour le code, comment pouvons-nous faire cela?
Personnellement j'utilise simplement GetLocalTime et un peu de calcul derrière pour faire un nombre au hasard entre 1 et 50 (ce n’est pas vraiment de l'aléatoire, mais c'est amplement suffisant pour cette utilisation)
Certains utilisent GetTickCount aussi a la place de GetLocalTime, chacun ça came. Les deux sont populaire pour ce genre d'utilisation.
kg.asm:
.486 .model flat, stdcall option casemap :none ; case sensitive include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\masm32.inc include \masm32\macros\macros.asm includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\masm32.lib DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD KeychooseRand PROTO .const IDC_SERIAL equ 1002 IDB_GEN equ 1003 IDB_QUIT equ 1004 IDC_DATE_STATIC equ 1005 IDC_SERIAL_STATIC equ 1006 .data ;App hard serials details FirstPartTable dd FirstPart0 dd FirstPart1,FirstPart2,FirstPart3,FirstPart4,FirstPart5 dd FirstPart6,FirstPart7,FirstPart8,FirstPart9,FirstPart10 dd FirstPart11,FirstPart12,FirstPart13,FirstPart14,FirstPart15 dd FirstPart16,FirstPart17,FirstPart18,FirstPart19,FirstPart20 dd FirstPart21,FirstPart22,FirstPart23,FirstPart24,FirstPart25 dd FirstPart26,FirstPart27,FirstPart28,FirstPart29,FirstPart30 dd FirstPart31,FirstPart32,FirstPart33,FirstPart34,FirstPart35 dd FirstPart36,FirstPart37,FirstPart38,FirstPart39,FirstPart40 dd FirstPart41,FirstPart42,FirstPart43,FirstPart44,FirstPart45 dd FirstPart46,FirstPart47,FirstPart48,FirstPart49 FirstPart0 db "1014",0 FirstPart1 db "1530",0 FirstPart2 db "1542",0 FirstPart3 db "1686",0 FirstPart4 db "1941",0 FirstPart5 db "1966",0 FirstPart6 db "2203",0 FirstPart7 db "2219",0 FirstPart8 db "2256",0 FirstPart9 db "2400",0 FirstPart10 db "2759",0 FirstPart11 db "3124",0 FirstPart12 db "3153",0 FirstPart13 db "3201",0 FirstPart14 db "3275",0 FirstPart15 db "3284",0 FirstPart16 db "3303",0 FirstPart17 db "3319",0 FirstPart18 db "3370",0 FirstPart19 db "3389",0 FirstPart20 db "3511",0 FirstPart21 db "3520",0 FirstPart22 db "3558",0 FirstPart23 db "3868",0 FirstPart24 db "4336",0 FirstPart25 db "4401",0 FirstPart26 db "4534",0 FirstPart27 db "4627",0 FirstPart28 db "4978",0 FirstPart29 db "5360",0 FirstPart30 db "5710",0 FirstPart31 db "5919",0 FirstPart32 db "5978",0 FirstPart33 db "6043",0 FirstPart34 db "6829",0 FirstPart35 db "6874",0 FirstPart36 db "6892",0 FirstPart37 db "7136",0 FirstPart38 db "7384",0 FirstPart39 db "7521",0 FirstPart40 db "7605",0 FirstPart41 db "7787",0 FirstPart42 db "8149",0 FirstPart43 db "8329",0 FirstPart44 db "8727",0 FirstPart45 db "8928",0 FirstPart46 db "9108",0 FirstPart47 db "9198",0 FirstPart48 db "9457",0 FirstPart49 db "9811",0 LastPartTable dd LastPart0 dd LastPart1,LastPart2,LastPart3,LastPart4,LastPart5 dd LastPart6,LastPart7,LastPart8,LastPart9,LastPart10 dd LastPart11,LastPart12,LastPart13,LastPart14,LastPart15 dd LastPart16,LastPart17,LastPart18,LastPart19,LastPart20 dd LastPart21,LastPart22,LastPart23,LastPart24,LastPart25 dd LastPart26,LastPart27,LastPart28,LastPart29,LastPart30 dd LastPart31,LastPart32,LastPart33,LastPart34,LastPart35 dd LastPart36,LastPart37,LastPart38,LastPart39,LastPart40 dd LastPart41,LastPart42,LastPart43,LastPart44,LastPart45 dd LastPart46,LastPart47,LastPart48,LastPart49 LastPart0 db "1222364893",0 LastPart1 db "1270287066",0 LastPart2 db "1305304841",0 LastPart3 db "2598545182",0 LastPart4 db "2631440264",0 LastPart5 db "2762461399",0 LastPart6 db "2790638874",0 LastPart7 db "2931377392",0 LastPart8 db "3102034965",0 LastPart9 db "3295791575",0 LastPart10 db "3783355659",0 LastPart11 db "3842655416",0 LastPart12 db "3858899737",0 LastPart13 db "3908279940",0 LastPart14 db "3975031660",0 LastPart15 db "4224548141",0 LastPart16 db "4435696301",0 LastPart17 db "4736102958",0 LastPart18 db "4972171360",0 LastPart19 db "4995983048",0 LastPart20 db "5177857047",0 LastPart21 db "5312949967",0 LastPart22 db "5382846674",0 LastPart23 db "5637988746",0 LastPart24 db "5770144611",0 LastPart25 db "5833220750",0 LastPart26 db "5906272922",0 LastPart27 db "6278033873",0 LastPart28 db "6751510988",0 LastPart29 db "6845650629",0 LastPart30 db "6964277929",0 LastPart31 db "6971848904",0 LastPart32 db "7207170241",0 LastPart33 db "7279800735",0 LastPart34 db "7295540016",0 LastPart35 db "7772188109",0 LastPart36 db "7785709066",0 LastPart37 db "7885915183",0 LastPart38 db "7889616924",0 LastPart39 db "8127366835",0 LastPart40 db "8165713559",0 LastPart41 db "8402192109",0 LastPart42 db "8640699795",0 LastPart43 db "8761334210",0 LastPart44 db "9274566738",0 LastPart45 db "9661052246",0 LastPart46 db "9711970467",0 LastPart47 db "9732086725",0 LastPart48 db "9874918627",0 LastPart49 db "9977903809",0 ; Dialog details szTitle db "AD Stream Recorder v5.0 *keygen*",0 szGenButton db "gENERATE",0 szQuitButton db "cLOSE",0 szDateStatic db "14/06/2021",0 szSerialStatic db "sERIAL",0 Rndm dd 0 .data? hInstance dd ? ;dd can be written as dword pTime dd 4 dup(?) FinalSerial db 100h dup(?) .code start: invoke GetModuleHandle, NULL mov hInstance, eax invoke DialogBoxParam, hInstance, 101, 0, ADDR DlgProc, 0 invoke ExitProcess, eax DlgProc proc hWin :DWORD, uMsg :DWORD, wParam :DWORD, lParam :DWORD .if uMsg == WM_INITDIALOG ; Set the dialog controls texts. Done here in the code instead of resource ; file to reduce the required bytes (strings in the rc file are UNICODE not ANSI) invoke SetWindowText,hWin,ADDR szTitle ; Set the window title text invoke SetDlgItemText,hWin,IDB_GEN,ADDR szGenButton invoke SetDlgItemText,hWin,IDB_QUIT,ADDR szQuitButton invoke SetDlgItemText,hWin,IDC_DATE_STATIC,ADDR szDateStatic invoke SetDlgItemText,hWin,IDC_SERIAL_STATIC,ADDR szSerialStatic mov Rndm,'abcd' invoke GetLocalTime,addr pTime mov eax,dword ptr pTime add eax,dword ptr pTime+2 ;wMonth add eax,dword ptr pTime+4 ;wDay add eax,dword ptr pTime+6 ;wMinute add eax,dword ptr pTime+7 ;wSecond add eax,dword ptr pTime+8 ;wMilliseconds add Rndm,eax .elseif uMsg == WM_COMMAND .if wParam == IDB_GEN invoke KeychooseRand invoke lstrcat,addr FinalSerial,[edx*4+FirstPartTable] invoke lstrcat,addr FinalSerial,chr$('-') invoke KeychooseRand invoke lstrcat,addr FinalSerial,[edx*4+LastPartTable] invoke SetDlgItemText,hWin,IDC_SERIAL,addr FinalSerial invoke RtlZeroMemory,addr FinalSerial,sizeof FinalSerial .elseif wParam == IDB_QUIT invoke EndDialog,hWin,0 .endif .elseif uMsg == WM_CLOSE invoke EndDialog,hWin,0 .endif xor eax,eax ret DlgProc endp KeychooseRand Proc add Rndm,'abcd' ; Generating some random values Rol Rndm,4 mov eax,Rndm mov ecx,49 ; Serials xor edx,edx idiv ecx ; Rndm mod 49 Ret KeychooseRand endp end start
kg.rc:
;This Resource Script was generated by WinAsm Studio. #define IDC_SERIAL 1002 #define IDB_GEN 1003 #define IDB_QUIT 1004 #define IDC_DATE_STATIC 1005 #define IDC_SERIAL_STATIC 1006 101 DIALOGEX 0,0,183,34 FONT 8,"Tahoma" STYLE 0x10c00800 EXSTYLE 0x00000000 BEGIN CONTROL "",IDB_GEN,"Button",0x10000001,84,18,53,13,0x00000000 CONTROL "",IDB_QUIT,"Button",0x10000000,141,18,37,13,0x00000000 CONTROL "",IDC_SERIAL,"Edit",0x10000880,33,3,144,12,0x00000200 CONTROL "",IDC_SERIAL_STATIC,"Static",0x50000002,4,6,23,9,0x00000000 CONTROL "",IDC_DATE_STATIC,"Static",0x58000000,3,22,44,9,0x00000000 END
make.bat:
@echo off \masm32\bin\rc /v kg.rc \masm32\bin\cvtres.exe /machine:ix86 kg.res \masm32\bin\ml.exe /c /coff kg.asm \masm32\bin\link.exe /SUBSYSTEM:WINDOWS /OUT:keychooser.exe kg.obj kg.res del kg.RES del kg.OBJ pause
Une fois compilé, ça ressemble à ça:
Et c'est déjà la fin!
Xylitol, 14/06/2021
Copyright (C)- xtx Team (2021)