[ - Intro - Explications - L'outil expliqué - Liens - Notes de fin - ]
 
[ - Tutoriaux : Bases ~ Jnz / Jz ~ Jmp ~ La fonction d'enregistrement ~ Crack GifMovieGear 3.0 - ]

On garde les mêmes et on recommence mais avec une fonction d'enregistrement.
La fonction d'enregistrement à l'avantage pour l'auteur de logiciel de pouvoir être appellée plusieurs fois dans le programme pour tester l'enregistrement de l'utilisateur sans avoir à réecrire la routine de protection à chaque fois.
Presque tous les logiciels avec serial teste dans un premier temps que le serial, que vous avez tapé, est bon puis reteste juste après et/ou au relancement du programme.

Cela conclura la partie "théorique" de ces cours avant de mettre nos connaissances en pratique sur un logiciel commercial.

Emplacement : dans le package fourni
Outils : W32Dasm 8.93, Hexworkshop 2.54
 

Le Crack

Le désassemblage nous donne la chose suivante :

//******************** Program Entry Point ********
:00401000 E83C000000              call 00401041
:00401005 85C0                    test eax, eax
:00401007 7515                    jne 0040101E

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401025(C)
|
:00401009 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"VILAIN NAG-SCREEN"
                                  |
:0040100B 6804304000              push 00403004

* Possible StringData Ref from Data Obj ->"ENREGISTRE-MOI SINON JE ME FACHE "
                                        ->"!!!"
                                  |
:00401010 6816304000              push 00403016
:00401015 6A00                    push 00000000

* Reference To: USER32.MessageBoxA, Ord:01BBh
                                  |
:00401017 E828000000              Call 00401044
:0040101C EB09                    jmp 00401027

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401007(C)
|
:0040101E E81E000000              call 00401041
:00401023 85C0                    test eax, eax
:00401025 74E2                    je 00401009

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040101C(U)
|
:00401027 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"Cour n"
                                  |
:00401029 683B304000              push 0040303B

* Possible StringData Ref from Data Obj ->"Mon premier Crack : La fonction "
                                        ->"d'enregistrement."
                                  |
:0040102E 6854304000              push 00403054

Ouhlala !!!! Ca a l'air moins clair qu'avant, non : ) ?

On retrouve toujours notre routine de génération du Nag-screen, du programme mais avec des ajouts de lignes d'instruction avec des call.

Resumons le programme :

:00401000 E83C000000              call 00401041
:00401005 85C0                    test eax, eax
:00401007 7515                    jne 0040101E
:00401009 6A00                    push 00000000 <=== Début Nag-screen
:.............                    ............
:00401017 E828000000              Call 00401044 <=== Affichage du Nag-screen
:0040101C EB09                    jmp 00401027
:0040101E E81E000000              call 00401041
:00401023 85C0                    test eax, eax
:00401025 74E2                    je 00401009
:00401027 6A00                    push 00000000 <=== Début programme

Bon on peut appliquer la solution du jump sans conditions de 401000 à 401027 et ça marche.
Mais ce crackme est simple et ne croyiez pas que dans un programme, la routine de protection se trouve avant le programme...
Prenons une autre solution de celles que nous connaissons.
Renversons le saut en 401007.

:00401007 7515                    jne 0040101E
devient
:00401007 7415                    je 0040101E

On relance et ... ça marche pas, le Nag-screen apparait !
Regardons le désassemblage.
On retrouve 2 fois la même chose :
:00401000 E83C000000              call 00401041
:00401005 85C0                    test eax, eax
et
:0040101E E81E000000              call 00401041
:00401023 85C0                    test eax, eax
Etrange non ?
On appelle une fonction et on teste la valeur d'eax juste après...
Revenons à notre listing.

:00401000 E83C000000              call 00401041 <=== Mystérieux call
:00401005 85C0                    test eax, eax <=== eax =0 ?
:00401007 7515                    jne 0040101E <=== non, va en 40101E sinon Nag-screen
:00401009 6A00                    push 00000000 <=== Début Nag-screen
:.............                    ............
:00401017 E828000000              Call 00401044 <=== Affichage du Nag-screen
:0040101C EB09                    jmp 00401027 <=== va au programme
:0040101E E81E000000              call 00401041 <=== Mystérieux call
:00401023 85C0                    test eax, eax <=== eax =0 ?
:00401025 74E2                    je 00401009 <=== oui, va en 401009 : le Nag-screen
:00401027 6A00                    push 00000000 <=== Début programme

Ok donc je résume l'éxécution de façon très schématique :

Début du programme
1- call 
2 - eax = 0 ?
3 - non, va à "Hello"

Affichage Nag-screen
1 - affiche Nag-screen
2 - va à "Programme"

Hello
1 - call
2 - eax = 0 ?
3 - oui : va à "Affichage Nag-screen"

Programme
1 - affiche "Cours n°1-3"...

Donc tout se base sur la valeur d'eax.

Regardons le cheminement avec le schéma en fixant la valeur d'eax  au lancement du programme. Cette valeurest considérée comme fixe tout le long du programme.

eax = 0

Début du programme
1- call 
2 - eax = 0 : pas de saut

Affichage Nag-screen
1 - affiche Nag-screen
2 - va à "Programme"

Programme
1 - affiche "Cours n°1-3"...

Maintenant prenons l'autres cas

eax = 1

Début du programme
1- call 
2 - eax = 0 : non donc au saute à "Hello"

Hello
1 - call
2 - eax = 0 ?
3 - non : pas de saut

Programme
1 - affiche "Cours n°1-3"...

Ok ! Voilà l'affaire. Si eax est fixé à 1 tout le long de l'éxécution du programme, on n'a pas normalement le Nag-screen.
Il faut donc trouver le moyen de fixer cette valeur comme on a fait dans une des solutions du premier tut et voir si cette valeur n'est pas changée au cours du programme.

On rentre au début dans un call... 
:00401000 E83C000000              call 00401041
et bien regardons dedans pour voir ce qu'il y a :

* Referenced by a CALL at Addresses:
|:00401000   , :0040101E 
|
:00401041 33C0                    xor eax, eax
:00401043 C3                      ret

On y est !
Ce call est appellé 2 fois et renvoit eax = 0 !
Il est appellé au début du programme et dans "Hello".
Changeons cette valeur :
 

:00401041 33C0                    xor eax, eax
devient
:00401041 B001                    mov al,01

Ca marche, le Nag-screen n'apparait plus !
Si vous reprennez le schéma d'éxécution, vous verrez pourquoi.
La solution que vous pouvez aussi faire est de renverser les 2 conditions des sauts après ce call.

1 ]
:00401007 7515                    jne 0040101E
devient 
:00401007 7415                    je 0040101E

2 ]
:00401025 74E2                    je 00401009
devient
:00401025 75E2                    jne 00401009

Ca marche aussi.
 

Je préfére nettement la première solution car elle s'avére très avantageuse sur de nombreux points.
- vous modifiez une ou quelques instructions au lieu de renverser tous les sauts...
Ici, on a juste 2 sauts mais certains programmes n'hésitent pas à tester plus de 2 fois et cela représente autant de sauts à changer.
- je suis une adepte du "donnes au programme ce qu'il veut". Le prog veut un eax =1 pour marcher ?! eh bien soit, donnons le lui !
Rien n'empêche que la valeur d'eax soit testée autrement qu'avec un test eax, eax et donc renverser les sauts ne changent pas la valeur d'eax.

Voilà on vient de voir la fonction d'enregistrement qui constitue une protection très utilisée par beaucoup de programmeurs... 
N'hésitez pas à mettre en pratique ces fraiches connaissances car vous verrez que vous trouverez beaucoup de programmes avec cette protection ultra-simpliste.

La seconde, que nous verrons dans la 2ème édition, est la variable d'enregistrement, utilisée notamment dans Winrar et compagnie.
 

Lise Grim 2002 / WiA