[ - Intro - Explications - L'outil expliqué - Liens - Notes de fin - ] |
[
- Tutoriaux :
Bases |
Emplacement : http://www.gamani.com
Outils : W32Dasm8.93 et
Hexworkshop 2.54
On lance le programme et on tombe sur un Nag-Screen puis un autre.
D'accord, passons à la suite... Regardons dans le menu "Aide".
Si l'on clique sur "A propos de GMG...", on tombe sur une fenêtre "non standard".
On nous rappelle le Trial
de 30 jours.
Si l'on clique sur "S'enregistrer
maintenant", on tombe sur une boîte.
On rentre un nom et un numéro bidon et on tombe sur le truc suivant.
Bien, bien. Fermons le programme.
Hum, on retombe sur la fenêtre du "A propos de GMG..." sauf que le
bouton Ok n'apparait qu'au bout de quelques secondes, histoire de bien
nous faire comprendre le message.
On désassemble MOVGEAR.EXE
Recherchons le texte de notre
boîte qui nous est renvoyé quand on rentre un serial bidon
dans les SDR.
Et on tombe sur :
:00431CEE C21000 ret 0010
*
Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00431C3E(C)
|
:00431CF1
6A30
push 00000030
*
Possible Reference to String Resource ID=40213: "Renseignements d'enregistrement
invalides"
|
:00431CF3
68159D0000
push 00009D15
*
Possible Reference to String Resource ID=40212: "Les renseignements que
vous venez d'entrer sont erronés. Vér"
|
:00431CF8
68149D0000
push 00009D14
Donc on repère que
c'est un saut conditionnel en 431C3E qui nous fait atterir ici.
Cliquons sur
et entrons 431C3E pour revenir au saut.
:00431C32
50
push eax
:00431C33
51
push ecx
:00431C34
E8E7FAFFFF
call 00431720
:00431C39
83C408
add esp, 00000008
:00431C3C
85C0
test eax, eax
:00431C3E
0F84AD000000
je 00431CF1 <===
on revient ici
:00431C44
8D542410
lea edx, dword ptr [esp+10]
:00431C48
8D44240C
lea eax, dword ptr [esp+0C]
:00431C4C
52
push edx
:00431C4D
50
push eax
:00431C4E
6A00
push 00000000
:00431C50
683F000F00
push 000F003F
:00431C55
6A00
push 00000000
:00431C57
6894FE4400
push 0044FE94
:00431C5C
6A00
push 00000000
*
Possible StringData Ref from Data Obj ->"Software\gamani\GIFMovieGear\2.0"
<===
un chemin
|
:00431C5E
68D0C44400
push 0044C4D0
:00431C63
6801000080
push 80000001
*
Reference To: ADVAPI32.RegCreateKeyExA, Ord:015Fh <===
oh ! on crée une clé dans la base de registre
|
:00431C68
FF1510904400
Call dword ptr [00449010]
:00431C6E
8D7C2460
lea edi, dword ptr [esp+60]
:00431C72
83C9FF
or ecx, FFFFFFFF
:00431C75
33C0
xor eax, eax
:00431C77
8B54240C
mov edx, dword ptr [esp+0C]
:00431C7B
F2
repnz
:00431C7C
AE
scasb
:00431C7D
F7D1
not ecx
*
Reference To: ADVAPI32.RegSetValueExA, Ord:0186h <===
on demande à fixer des infos dedans
|
:00431C7F
8B1D18904400
mov ebx, dword ptr [00449018]
:00431C85
51
push ecx
:00431C86
8D4C2464
lea ecx, dword ptr [esp+64]
:00431C8A
51
push ecx
:00431C8B
6A01
push 00000001
:00431C8D
50
push eax
*
Possible StringData Ref from Data Obj ->"RegName3" <===
ce type d'info portant le nom RegName3
|
:00431C8E
68FCE54400
push 0044E5FC
:00431C93
52
push edx
:00431C94
FFD3
call ebx
:00431C96
8DBC24C4000000 lea
edi, dword ptr [esp+000000C4]
:00431C9D
83C9FF
or ecx, FFFFFFFF
:00431CA0
33C0
xor eax, eax
:00431CA2
F2
repnz
:00431CA3
AE
scasb
:00431CA4
F7D1
not ecx
:00431CA6
8D8424C4000000 lea
eax, dword ptr [esp+000000C4]
:00431CAD
51
push ecx
:00431CAE
8B4C2410
mov ecx, dword ptr [esp+10]
:00431CB2
50
push eax
:00431CB3
6A01
push 00000001
:00431CB5
6A00
push 00000000
*
Possible StringData Ref from Data Obj ->"RegCode3" <===
et un autre avec le nom RegCode3
|
:00431CB7
6808E64400
push 0044E608
Ok, ok, combien vous pariez
que ces informations ( RegName3 et RegCode3 ) sont notre nom et serial
que l'on a rentré ?
Le plus intéressant
vient d'en haut :
:00431C32
50
push eax
:00431C33
51
push ecx
:00431C34
E8E7FAFFFF
call 00431720 <===
un call ?
:00431C39
83C408
add esp, 00000008
:00431C3C
85C0
test eax, eax <===
eax = 0 ?
:00431C3E
0F84AD000000
je 00431CF1 <===
notre saut
Donc la valeur d'eax semble conditionnée notre enregistrement. Ici si eax = 0 : c'est pas bon.
Rentrons dans notre call.
*
Referenced by a CALL at Addresses:
|:00431979
, :00431C34
|
:00431720
8B442408
mov eax, dword ptr [esp+08]
:00431724
8B4C2404
mov ecx, dword ptr [esp+04]
:00431728
50
push eax
:00431729
51
push ecx
:0043172A
E811000000
call 00431740 <===
un autre call ?
:0043172F
83C408
add esp, 00000008
:00431732
C3
ret
Ah ah, déjà,
on a un autre appel se référant à la même fonction.
Donc il n'y a pas qu'ici qu'on teste notre nom + serial.
Suivons notre code et entrons
dans le call 00431740.
*
Referenced by a CALL at Address:
|:0043172A
|
:00431740
81ECD8000000
sub esp, 000000D8
:00431746
83C9FF
or ecx, FFFFFFFF
:00431749
33C0
xor eax, eax
:0043174B
8D542410
lea edx, dword ptr [esp+10]
..................
..........................
..................
..........................
..................
..........................
:00431787
8D7C2420
lea edi, dword ptr [esp+20]
:0043178B
7422
je 004317AF
*
Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004317AD(C)
|
:0043178D
0FBE16
movsx edx, byte ptr [esi]
:00431790
52
push edx
*
Possible StringData Ref from Data Obj ->"KSDF234897544URTFBBMNZXCSDKA"
|
:00431791
682CE64400
push 0044E62C
:00431796
E885DC0000
call 0043F420
:0043179B
83C408
add esp, 00000008
..................
..........................
..................
..........................
:004318C1
83D8FF
sbb eax, FFFFFFFF
*
Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004318BD(U)
|
:004318C4
5F
pop edi
:004318C5
5E
pop esi
:004318C6
5D
pop ebp
:004318C7
5B
pop ebx
:004318C8
85C0
test eax, eax
:004318CA
750C
jne 004318D8
:004318CC
B801000000
mov eax, 00000001
:004318D1
81C4D8000000
add esp, 000000D8
:004318D7
C3
ret
*
Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004318CA(C)
|
:004318D8
33C0
xor eax, eax
:004318DA
81C4D8000000
add esp, 000000D8
:004318E0
C3
ret
Ok, nous y voici !
Donc en traçant un
peu dans le code on voit beaucoup d'instructions dont certaines seront
revues dans le cas d'une keygennisation, mais ce n'est pas notre cas ici.
Nous sommes dans un call
et donc le premier "ret" que nous rencontrons sera celui qui nous fera
sortir de la fonction, donc la valeur d'eax devrait déjà
être fixée et c'est le cas car si vous voyez les instructions
avant le ret, c'est un mov eax,00000001 ( eax =1 ) et un xor eax, eax (
remet la valeur d'eax à 0 ) si le saut en 4318CA est fait.
Nous voulons que eax = 1.
Voici deux solutions équivalentes.
Première
solution
**********************
:004318C5
5E
pop esi
:004318C6
5D
pop ebp
:004318C7
5B
pop ebx
:004318C8
85C0
test eax, eax
:004318CA
750C
jne 004318D8 <===
on remplace par NOP ( 2 x )
:004318CC
B801000000
mov eax, 00000001
:004318D1
81C4D8000000
add esp, 000000D8
:004318D7
C3
ret
*
Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004318CA(C)
|
:004318D8
33C0
xor eax, eax
:004318DA
81C4D8000000
add esp, 000000D8
:004318E0
C3
ret
Le saut ne sera jamais car
il n'existe plus, remplaçé par 2 NOP.
Donc on remplace 750C par
9090.
Deuxième solution
**********************
:004318C5
5E
pop esi
:004318C6
5D
pop ebp
:004318C7
5B
pop ebx
:004318C8
85C0
test eax, eax
:004318CA
750C
jne 004318D8
:004318CC
B801000000
mov eax, 00000001
:004318D1
81C4D8000000
add esp, 000000D8
:004318D7
C3
ret
*
Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004318CA(C)
|
:004318D8
33C0
xor eax, eax <===
on remplace par mov eax,01
:004318DA
81C4D8000000
add esp, 000000D8
:004318E0
C3
ret
Que le saut soit fait ou
non, on aura une valeur d'eax différente de "0".
On remplace 33C0 par B001.
Mais il y a encore une AUTRE
solution !
***********************************************
On vient de voir que le
call dans lequel nous sommes n'est appellé qu'une fois dans le programme.
Donc si on revient en arrière,
au premier call fait.
*
Referenced by a CALL at Addresses:
|:00431979
, :00431C34
|
:00431720
8B442408
mov eax, dword ptr [esp+08]
:00431724
8B4C2404
mov ecx, dword ptr [esp+04]
:00431728
50
push eax
:00431729
51
push ecx
:0043172A
E811000000
call 00431740
:0043172F
83C408
add esp, 00000008
:00431732
C3
ret
Pourquoi ne pas fixer la valeur d'eax ici ?
*
Referenced by a CALL at Addresses:
|:00431979
, :00431C34
|
:00431720
8B442408
mov eax, dword ptr [esp+08] <==
on remplace par mov eax, 01 et ret
:00431724
8B4C2404
mov ecx, dword ptr [esp+04]
:00431728
50
push eax
:00431729
51
push ecx
:0043172A
E811000000
call 00431740
:0043172F
83C408
add esp, 00000008
:00431732
C3
ret
Donc on remplace 8B442408
par B001C3 + le byte restant de l'instruction patché (
ici 08 )
Si on désassemble
le programme cracké de cette façon, on la chose suivante
:
*
Referenced by a CALL at Addresses:
|:00431979
, :00431C34
|
:00431720
B001
mov al, 01
:00431722
C3
ret
:00431723
088B4C240450
or byte ptr [ebx+5004244C], cl
:00431729
51
push ecx
:0043172A
E811000000
call 00431740
:0043172F
83C408
add esp, 00000008
:00431732
C3
ret
Parfait !
Pour le reste du code suivant
notre nouveau ret, il ne sera jamais exécuté... donc pas
besoin de faire des NOP de 431723 à 431733.
On relance le programme, plus de problèmes ! On avance son horloge Windows d'un an pour voir si le trial de 30 jours est aussi mort... C'est le cas. On vient "d'émuler" le mode enregistré.
Chose importante
*********************
La chose à ne pas
oublier est que le logiciel met des clés dans la base de registre
avec notre nom + serial !
Lancez Regedit et allez
voir en :
HKEY_CURRENT_USER\Software\gamani\GIFMovieGear\2.0
Vous retrouvez le chemin
( Software\gamani\GIFMovieGear\2.0 ) donné dans W32Dasm et les noms de clé ( RegCode3
et RegName3 ) que nous avons vu dans le code précédemment.
Et celles-ci contiennent évidemment nos informations.
Si vous effacez la clé
HKEY_CURRENT_USER\Software\gamani\GIFMovieGear\2.0 et que vous relancez
le logiciel, vous retomberez en version non enregistrée. Evidemment,
il vous suffira de rentrer de nouveau un nom+serial pour que ça
marche, mais la chose importante n'est pas là.
Quand le logiciel vient
d'être installé, il n'y a pas d'informations d'enregistrement
( RegCode3 et RegName3 ) et donc cracker le logiciel implique qu'un nom
et un serial soient entrés obligatoirement une fois pour toute.
Voilà, voilà,
un logiciel commercial dont la protection se cracke très facilement...
Vous avez donc un exemple quand la protection n'a pas été
traitée avec sérieux. ; )