KEYGEN du Crackme 1.0 de FredBug |
Outils: SoftIce, OllyDbg
Date: 24 / 05 / 2002
FerdBug nous dit qu il faut patcher et trouver / keygener le crackme. C’est ce que nous allons faire.
1 )
Patch du crackme
2 ) Keygen
du crackme
Avant de commencer, il faut le dumper car il est compressé
avec UPX je crois. Ceci fait, on l ouvre avec OllyDbg. Mais la on se retrouve
dans le thread de Kernel32. Nous on veut être dans celui de l executable. On va
allez a l entry point en faisant CTRL+G et on entre imagebase + entrypoint = 400000
+ 130B. C’est bon, on est bien dans l exe. Ensuite,
clic droit puis search / All reference
text string :
Cliquez sur “Rentrez votre nom”, on arrive ici :
:00401067 C704247C804000 mov dword ptr [esp], 0040807C
:0040106E
E8EA010000
call
0040125D
:00401073 8D4598
lea eax, dword ptr [ebp-68]
:00401076 50
push eax
:00401077 E897010000
call
00401213
=> Call Prenant votre nom et le nombre de caracteres
:0040107C 6864804000
push
00408064
:00401081 E8D7010000
call
0040125D
=> Call du serial
:00401086 8D45FC
lea eax, dword ptr [ebp-04]
:00401089 50
push eax
*
Possible StringData Ref from Data Obj ->"%d"
:0040108A
6860804000
push
00408060
:0040108F E868010000
call
004011FC
:00401094 FF75FC
push [ebp-04]
:00401097 8D4598
lea eax, dword ptr [ebp-68]
:0040109A 50
push eax
:0040109B E823000000
call
004010C3
=> Routine du serial
:004010A0 83C41C
add esp, 0000001C
:004010A3 85C0
test eax, eax
:004010A5 7407
je 004010AE
:004010A7 6848804000
push
00408048
=> ASCII “ Ouah
trop fort”
:004010AC
EB05
jmp
004010B3
:004010AE 6830804000
push
00408030
=> ASCII “Encore
un effort”
Vous l’avez compris, pour patcher le crackme, il faut inverser le saut en 4010A5, ce qui affichera « Ouah trop fort » à la place de « Encore un effort ».
Pour ce faire, on entre dans le call a l adresse 40109B. Vous tracez un peu le code jusqu ici :
Le nom doit etre compris entre 4 et 10 caracteres :
:004010DF 83F804
cmp eax, 00000004
=> eax contient le nombre de caracteres du nom et est comparé
a 4
:004010E2 59
pop ecx
:004010E3 7E51
jle 00401136
=> si inferieur ou egal a 4 saute
:004010E5 83F80A
cmp eax, 0000000A
=> compare eax a 10 en decimal
:004010E8 7F4C
jg 00401136
=> si superieur saute
…..
Ensuite, la routine suivante s occupe des deux premiers caracteres :
:004010EC
0FBE0C30
movsx
ecx, byte ptr [eax+esi]
=> prend l ascii du caracteres en cours
:004010F0
69C9F0000000 imul ecx, 000000F0
=> multiplie l ascii précédent par F0
:004010F6
81C13F2A0000 add ecx, 00002A3F
=> lui ajoute 2A3F
:004010FC 81F149596900 xor ecx, 00695949
=> le xor par 695949
:00401102 03F9
add edi, ecx
=> met le tout dans edi ( on l appelle buffer1 )
:00401104 40
inc eax
=> passe au caractere suivant
:00401105 83F802
cmp eax, 00000002
=> compare si les deux premiers caracteres sont passes
:00401108 7CE2
jl 004010EC
=> si non on saute au debut
…
Ensuite la routine suivante s’occupe du 3eme et 4eme caractere du nom :
:00401148
0FBE0432
movsx eax, byte ptr [edx+esi]
=> prend l ascii du caractere en cours ( au depart edx est
egal a 2 )
:0040114C 0FAFC0
imul eax, eax
=> le multiplie par lui meme
:0040114F 83F00A
xor eax, 0000000A
=> le xor par A
:00401152 83C009
add eax, 00000009
=> lui ajoute 9
:00401155 3523010000
xor
eax, 00000123
=> le xor par 123
:0040115A 0524100000
add
eax, 00001024
=> lui ajoute 1024
:0040115F 8D0440
lea eax, dword ptr [eax+2*eax]
=> charge l adresse de eax+2*eax dans eax
:00401162
C1E002
shl eax, 02
=> decalage a gauche
:00401165 0101
add dword ptr [ecx], eax
=> met le tout a l adresse pointee par ecx ( on l appelle
buffer2 )
:00401167 42
inc edx
=> passe au caractere suivant
:00401168 83FA04
cmp edx, 00000004
=> le 3eme et 4eme caracteres sont passes ?
:0040116B 7CDB
jl 00401148
=> si non on saute au debut
…
Ensuite la routine suivante s’occupe du 5eme, 6eme et 7eme caractere du nom :
:00401190
0FBE043E
movsx eax, byte ptr [esi+edi]
=> prend l ascii du caracteres en cours( au depart esi est
egal à 4 )
:00401194 83C033
add eax, 00000033
=> lui ajoute 33
:00401197 6A03
push
00000003
=> met 3 sur la pile
:00401199 5B
pop ebx
=> ebx prend le chiffre 3 de la pile
:0040119A
8D04C0
lea eax, dword ptr [eax+8*eax]
=> charge l adresse dans eax
:0040119D 99
cdq
=> ? ( si quelqu un veut me le dire ce serait cool
)
:0040119E F7FB
idiv ebx
=> division signee
:004011A0 3589070000
xor
eax, 00000789
=> le xor par 789
:004011A5 83C032
add eax, 00000032
=> lui ajoute 32
:004011A8 8D04C0
lea eax, dword ptr [eax+8*eax]
=> charge l adresse dans eax
:004011AB D1E0
shl eax, 1
=> decalage a gauche
:004011AD 3576980000
xor
eax, 00009876
=> le xor par 9876
:004011B2 0101
add dword ptr [ecx], eax
=> met le tout a l adresse pointee par ecx ( buffer3 )
004011B4 46
inc esi
=> passe au caractere suivant
:004011B5 83FE07
cmp esi, 00000007
=> les caracteres sont passes ?
:004011B8
7CD6
jl 00401190
=> si non retour au debut
…
La derniere routine s occupe des derniers caracteres :
:004011D7 0FBE0402
movsx
eax, byte ptr [edx+eax]
=> prend l ascii du caracteres en cours( au depart esi est
egal à 7 )
:004011DB 8D048544010000 lea eax, dword ptr [4*eax+00000144] => charge l adresse dans eax
:004011E2 83F038
xor eax, 00000038
=> le xor par 38
:004011E5 83C05D
add eax, 0000005D
= lui ajoute 5D
:004011E8 83F005
xor eax, 00000005
=> le xor par 5
:004011EB 8D0440
lea eax, dword ptr [eax+2*eax]
=> charge l adresse dans eax
:004011EE C1E002
shl eax, 02
=> decalage a gauche
:004011F1 0101
add dword ptr [ecx], eax
=> met le tout dans ecx( buffer4 )
:004011F3
42
inc edx
=> passe au caracteres suivants
:004011F4 83FA0A
cmp edx, 0000000A
=> compare edx a A ( 10 en decimal )
:004011F7
7EDA
jle 004011D3
=> si inferieur ou egal on saute au debut de la routine
Pour
cette routine, il faut que j éclaircisses un point. Vous avez remarquer que la
routine prend l ascii de tout les caracteres, c’est a dire 10 meme si le
nom en fait moins. Prenons un exemple. J entre comme nom DalKiT, qui est composé
de 6 caracteres. Au depart, apres l appui sur « Entrer » pour valider
le nom, il y a une routine que je vais expliquer. Tout d’abord il y a une
chaine hexadecimale constante : 00 00 65 00 58 A5 F7 BF 00 00 65.
L hexa
des lettres de dalkit serait : 64 61 6C 6B 69 74 avec 64 correspondant a
« d », 61 a « a », etc… .
Ensuite le nom remplace
le debut de la chaine constante par lui meme.
Donc 00 00 65 00 58 A5 F7 BF
00 00 65 devient
64 61 6C 6B 69
74 F7 BF 00 00 65
En fait ce n est pas complique mais g eu du mal a comprendre pourquoi mes serials marchaient pour des noms egales a 10 caracteres et pas moins.
Bon tracer le code pour arriver ici :
:0040111C 8B45FC
mov eax, dword ptr [ebp-04]
=> ebp-04 contient buffer4
:0040111F 8B4DF8
mov ecx, dword ptr [ebp-08]
=> ebp-08 contient buffer3
:00401122 03C8
add
ecx, eax
=> ecx = buffer3 + buffer4
:00401124 83C410
add esp, 00000010
:00401127 034DF4
add ecx, dword ptr [ebp-0C]
=> ecx = ecx + buffer2
:0040112A 33C0
xor eax, eax
:0040112C 03CF
add ecx, edi
=> ecx = ecx + buffer1
:0040112E 394D0C
cmp dword ptr [ebp+0C], ecx
=> compare le vrai serial ( ecx ) au serial entre
Pour resumer le serial correspondant est egal a buffer1 + buffer2 + buffer3 + buffer4
Voilà,
le keygen est terminé. Si vous avez des questions, mailez moi ( dalkit@hotmail.com )
Je remercie
FredBug d’avoir codé ce crackme, N-GeN et tous le autres que j ai oublié.
DalKiT