Keygenning 4 newbies CrackMe ~ coded by The Analyst

Je m’attaque dans cet article à un CrackMe de niveau fastidieux « for newbies ».

Pour download le KeygenMe : https://www.re-xe.com/wp-content/uploads/2010/11/The_Analyst_k4n1.zip

On ne perd pas de temps, on y va, on lance le binaire.

On obtient la chose suivante :

On analyse ensuite le binaire à coup de PEiD, ça m’étonnerait qu’on l’ai packé, étant donné qu’il est d’un niveau relativement facile.
On obtient la chose suivante :

Parfait, pas de packer en vue. Mais peut-être qu’on aura le droit à de la jolie crypto ? On utilise le plugin Kanal de PEiD, voici ce que l’on obtient :

Super, pas de crypto en vue ! On peut maintenant passer à l’analyse du binaire !

On tente un name & un serial au hasard :

W00t, This serial is *NOT* valid!

Allez op ! On ouvre notre binaire depuis Ollydbg.

Une fois votre binaire ouvert, tentez de checker les BadBoy & GoodBoy. Pour ce faire, nous allons lister les strings.

Cliquez droit dans ollydbg, puis allez dans ‘Ultra String Reference’ –> ‘1 Find Ascii’. On obtient ceci :


On aperçoit notre GoodBoy, et notre BadBoy :

Goob Boy : ‘Congratulation! IF this number comes *FROM YOUR* keygen …’
Bad Boy : ‘This serial is *NOT* Valid!! Try again… : UNREGISTRED’
On aperçoit aussi : %1X, ceci sert à formater notre string entrée.


Double cliquez sur le GoodBoy, ce qui vous renverra à son adresse (00401157) dans Ollydbg.
On obtient le code ci-dessous :

1
2
3
4
5
6
7
8
9
00401157   |.>PUSH 0040B43C                                                   ; /Text = « Congratulations! IF this number comes *FROM YOUR* keygen, Write a tutorial dude  . »
0040115C   |.>PUSH ESI                                                        ; |hWnd
0040115D   |.>CALL <JMP.&USER32.SetWindowTextA>; \SetWindowTextA              // G00d Boy
00401162   |.>JMP SHORT 0040117C00401164   |>>PUSH 0040B490                   ; /Text = « This serial is *NOT* Valid!! Try again… : UNREGISTERED »
00401169   |.>PUSH ESI                                                        ; |hWnd
0040116A   |.>CALL <JMP.&USER32.SetWindowTextA>; \SetWindowTextA              // Bad Boy
0040116F   |.>JMP SHORT 0040117C00401171   |>>PUSH 0040B4C9                   ; /Text = « Name must contain more than 4 chars and less than 50 chars !! »
00401176   |.>PUSH ESI                                                        ; |hWnd
00401177   |.>CALL <JMP.&USER32.SetWindowTextA>; \SetWindowTextA              // Bad Boy


Très bien.


On s’intéresse ensuite à cette ligne (située juste au dessus) :

1
004010AE  |.  E8 FB9B0000   CALL &lt;JMP.&USER32.GetWindowTextA&gt;        ; \GetWindowTextA


Ici GetWindowtext sert à récupérer les valeurs du champ name.


Ensuite, nous avons :

1
2
3
4
5
00401129   |.  FF75 C8              PUSH DWORD PTR [EBP-38]             ; /Arg3
0040112C   |.  68 38B44000          PUSH 0040B438                       ; |%lX
00401131   |.  8D8D 80FEFFFF        LEA ECX,[EBP-180]                   ; |
00401137   |.  51                   PUSH ECX                            ; |Arg1
00401138   |.  E8 873D0000          CALL 00404EC4                       ; \k4n.00404EC4


Ceci ressemble fortement à une fonction qui va formater notre string. Ce qui nous l’indique c’est le ‘ASCII « %lX »‘.


On descend encore un peu et on tombe sur :

1
0040114E  |.  E8 339C0000   CALL <JMP.&amp;KERNEL32.lstrcmpA>            ; \lstrcmpA


lstrcmp s’occupe de comparer les chaines entrées juste avant d’afficher le BadBoy ou GoodBoy. On peut facilement en déduire que la routine de génération du serial est dans le coin ! Yes on s’en rapproche …
Le fait que’on ai une boucle juste avant, et que le résultat de celle-ci soit passé en argument à la fonction de formatage indique qu’on est tout proche de la routine !


On remonte un peu plus haut, et on trouve :

1
2
00401102  |.  837D D8 32    CMP DWORD PTR SS:[EBP-28],32
00401106  |.  7D 69         JGE SHORT k4n.00401171


Ici le programme vérifie la taille du name entré : si il est supérieur ou égal à 50d. (c’est à dire 50 chars). Si on entre un name supérieur à 50 chars, le programme nous enverra directement vers un BadBoy.
Vous pouvez en avoir le cœur net maintenant ! On est sûr et certain que la routine est située entre les vérifications de la taille de la string entrée en name et son formatage. C’est à dire de :

1
0040110C   |> /0FBE840D 48FFFFFF    /MOVSX EAX,BYTE PTR [EBP+ECX-B8]


À :

1
00401124   |.  03C3                 ADD EAX,EBX

On ne prendra pas :

1
00401126   |.  8945 C8              MOV [EBP-38],EAX


Car cette ligne ne fait que sauvegarder eax dans la pile. La valeur de eax ne changera donc plus.


La routine correspond donc à ceci (lignes grisées) :


On se procure cette routinz & on code notre keygen !!
Quelques commentaires à propos de la routine :

1
2
3
4
5
6
7
8
9
MOV AL,BYTE PTR [ecx+NameBuffer]       ; Met dans AL chaque char du name un par un à chaque fois que ça boucle ( car ECX est incrémenté ligne suivante ).
INC ECX                                ; Incrémentation de ECX pour le définir comme compteur de chars contenus dans le name.
XOR EAX,ECX                            
ADD EBX,EAX                            ; Additionne eax à ebx. eax contenant les chars du name.
CMP ECX,DWORD PTR [LenName]            ; Compare le nombre de chars du compteur au nombre de chars du name.
jne @B                                 ; Boucle si le résultat du cmp précédent n'a pas été égal à 0, c'est à dire si ecx, le compteur, n'a pas été égal au nombre de chars du nom.
IMUL EAX,EAX,6                         ; Multiplie le char pécédemment xoré par 6.
SHL EBX,7                              ; Multiplie ebx par 2^7.
ADD EAX,EBX                            ; Additionne eax à ebx.

Lors de cette opération : ADD EAX,EBX
On a :
– eax qui est la valeur hexadécimale du dernier char multiplié par 6.
– ebx : la somme de tous les chars xorés, multipliés par 2^7.

Je vous laisse cogiter …

Keygen.asm :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
.386
.model flat,stdcall
option casemap:none

; Include sur les librairies utilisées :
include Keygen.inc


; Les variables déclarées :
.data

Format                         db       "%X",0
Message                        db       "Entrez moins de caractères !",0
MessageShort                   db       "Entrez plus de caractères !",0
WinTitle                       db       "First Keygen By int_0x80",0

; Les variables non déclarées :
.data?

hInstance                      HINSTANCE       ?
NameBuffer                     db       50 dup(?)
SerialBuffer                   db       50 dup(?)
LenName                        db       50 dup(?)

.code

start:

    invoke GetModuleHandle, NULL
    mov hInstance, eax
    AllowSingleInstance addr WinTitle          
    ; Cette macro limite le programme à une instance.

    invoke DialogBoxParam, hInstance, IDD_KEYGEN, NULL, addr DlgProc, NULL
    invoke ExitProcess, eax

   
; Début des procédures du dialogue :
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM  ; http://msdn.microsoft.com/en-us/library/ms645469(VS.85).aspx

.if uMsg == WM_INITDIALOG                  
    invoke  LoadIcon,hInstance,MyIcon          
    invoke  SendMessage,hWnd,WM_SETICON,1,eax
    invoke  GetDlgItem,hWnd,IDC_NAME
    invoke  SetFocus, eax      
    invoke  uFMOD_PlaySong, IDM_MUSIK, 0, XM_RESOURCE        ; Play SFX :)
   
.elseif uMsg == WM_COMMAND
        mov eax,wParam
       
.if eax == IDC_GENERATE
    invoke GetDlgItemText,hWnd,IDC_NAME,addr NameBuffer,sizeof NameBuffer
    CALL Generate
    invoke SetDlgItemText,hWnd,IDC_SERIAL,addr SerialBuffer
   
.elseif eax == IDC_COPY
    invoke SendDlgItemMessage,hWnd,IDC_SERIAL,EM_SETSEL,0,-1
    invoke SendDlgItemMessage,hWnd,IDC_SERIAL,WM_COPY,0,0
   
.elseif eax == IDC_EXIT
    invoke SendMessage,hWnd,WM_CLOSE,0,0
.endif

.elseif uMsg == WM_CLOSE
    invoke EndDialog,hWnd,0
.endif

        xor eax,eax         ; MOV eax, 0
        xor ecx, ecx        ; MOV ecx, 0
        Ret
       
DlgProc EndP
; Fin de la procédure du dialogue.

;//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

; Génération du serial
Generate proc  hWnd:HWND

        invoke lstrlen,addr NameBuffer
        mov dword ptr [LenName], eax           ; Stockage de eax dans LenName .
        cmp eax, 04h                           ; On compare la taille à 4d.
        jl NoInput                             ; On saute si inférieur, le je saute si c'est égal.
        cmp eax, 32h                           ; Puis on la compare à 50d (50 chars max).
        ja Erreur                              ; On saute vers le label appelé 'erreur' si supérieur.
        xor eax, eax                           ; MOV eax, 0
        xor ebx, ebx                           ; MOV ebx, 0
        xor ecx, ecx                           ; MOV ecx, 0
        xor edx, edx                           ; MOV edx, 0

; Routine
@@:
        MOV AL,BYTE PTR [ecx+NameBuffer]       ; Met dans AL chaque char du name un par un à chaque fois que ça boucle ( car ECX est incrémenté ligne suivante ).
        INC ECX                                ; Incrémentation de ECX pour le définir comme compteur de chars contenus dans le name.
        XOR EAX,ECX                            
        ADD EBX,EAX                            ; Additionne eax à ebx. eax contenant les chars du name.
        CMP ECX,DWORD PTR [LenName]            ; Compare le nombre de chars du compteur au nombre de chars du name.
        jne @B                                 ; Boucle si le résultat du cmp précédent n'a pas été égal à 0, c'est à dire si ecx, le compteur, n'a pas été égal au nombre de chars du nom.
        IMUL EAX,EAX,6                         ; Multiplie le char pécédemment xoré par 6.
        SHL EBX,7                              ; Multiplie ebx par 2^7.
        ADD EAX,EBX                            ; Additionne eax à ebx.
; Fin de la routine.


; Conversion du sérial :
    invoke wsprintf,addr SerialBuffer,addr Format,eax    ; wsprintf --> http://msdn.microsoft.com/en-us/library/aa450993.aspx      
        Ret
; Fin de la procédure de génération du serial.

; On arrive ici si il n'y a pas de nom entré :
NoInput:
    invoke SetDlgItemText,hWnd,IDC_SERIAL, addr MessageShort
        Ret

; On arrive ici si le nom fait plus de 20 caractères :
Erreur :
    invoke SetDlgItemText,hWnd,IDC_SERIAL, addr Message
        Ret

;//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Generate endp

end start
; Fin du programme

Keygen.inc :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
; Includes sur les librairies utilisées :
include MyMacros.asm
include windows.inc
include user32.inc
include kernel32.inc
include comctl32.inc
include winmm.inc
includelib kernel32.lib
includelib user32.lib
includelib comctl32.lib
includelib winmm.lib
include SFX/ufmod.inc                 ; Pour la musique.
includelib SFX/ufmod.lib              ; Aussi pour la musique.


; Prototype des fonctions :
DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD

; Définition des constantes ici :
IDD_KEYGEN                 equ 1001
IDC_NAME                   equ 1002
IDC_SERIAL                 equ 1003
IDC_GENERATE               equ 1004
IDC_COPY                   equ 1005
IDC_EXIT                   equ 1006
LOGO                       equ 1007
MyIcon                     equ 1008
IDM_MUSIK                  equ 1009

Keygen.rc :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#define IDD_KEYGEN 1001
#define IDC_NAME 1002
#define IDC_SERIAL 1003
#define IDC_GENERATE 1004
#define IDC_COPY 1005
#define IDC_EXIT 1006
#define LOGO 1007
#define Serial 1011
#define Name 1012
#define MyIcon 1013
#define IDM_MUSIK 1009

LOGO BITMAP DISCARDABLE "int_0x800.bmp"
MyIcon ICON DISCARDABLE "favicon.ico"
IDM_MUSIK RCDATA DISCARDABLE "SFX/Class cracktro #15.xm"

IDD_KEYGEN DIALOGEX 0,0,262,215
CAPTION "First Keygen By int_0x80"
FONT 8,"MS Sans Serif"
STYLE 0x10cc0000
EXSTYLE 0x00000000
BEGIN
    CONTROL "#1007",LOGO,"Static",0x1080020e,-7,0,277,222,0x00000000
    CONTROL "Your Name",IDC_NAME,"Edit",0x50010080,53,92,191,19,0x00000200
    CONTROL "",IDC_SERIAL,"Edit",0x50010080,53,120,191,19,0x00000200
    CONTROL "Generate",IDC_GENERATE,"Button",0x50010000,17,166,51,16,0x00000000
    CONTROL "Serial:",Serial,"Static",0x50000001,7,123,37,13,0x00000000
    CONTROL "Name:",Name,"Static",0x10000001,7,95,37,13,0x00000000
    CONTROL "Exit",IDC_EXIT,"Button",0x50010000,190,166,51,16,0x00000000
    CONTROL "Copy",IDC_COPY,"Button",0x50010000,103,166,51,16,0x00000000
END

MyMacros.asm :

1
2
3
4
5
6
7
8
9
10
11
12
AllowSingleInstance MACRO lpTitle
        invoke FindWindow,NULL,lpTitle
        cmp eax, 0
        je @F
          push eax
          invoke ShowWindow,eax,SW_RESTORE
          pop eax
          invoke SetForegroundWindow,eax
          mov eax, 0
          ret
        @@:
      ENDM

Voici à quoi ressemble le miens :

J’ai entré ‘int0x80’ en name, et j’ai cliqué sur Generate. Le serial que l’on me propose est : ‘139CA’.
Retournons vers notre KeygenMe & essayons le serial …

W00t ! KeygenMe Keygenné ! Bien joué ! Si vous galérez pour coder votre keygen, n’hésitez pas à jeter un œil au miens que voici :
(exécutable + sources) —> https://www.re-xe.com/wp-content/uploads/2010/11/KeyGen.zip

Have fun et bon courage pour la suite ! Greetz to Horgh pour m’avoir aidé à coder ce Keygen !

Ce contenu a été publié dans Keygen, avec comme mot(s)-clef(s) . Vous pouvez le mettre en favoris avec ce permalien.

Une réponse à Keygenning 4 newbies CrackMe ~ coded by The Analyst

  1. nops0n dit :

    Int_0x80 fait ses pas en RCE. Good luck & bonne continuation boy.
    <3

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Protected by WP Anti Spam

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.