Crack in France
par pifoman

 
 

Ce cours est un reflet fidèle du cours intégré au crack de ma création de Ultralingua 5.0.2 fr

 

INFOS SUR LE CRACK

 

Nom du progUltralingua 5.0.2
Editeur

http://www.ultralingua.com/fr/

Téléchargeablehttp://highspeed1.movedigital.com
Date du prog Dimanche 23 janvier 2005
Date du crack Jeudi 10 février 2005
Réalisé parPifoman
Url sitehttp://pifoman.free.fr/pif.php
Url redirectionhttp://www.geocities.com/mitonnes/pif.htm

 

COMMENTAIRES SUR LE PROGRAMME

 

    Ultralingua est une série de dictionnaires de traduction mulitlingue.Il permettent de traduire des mots ou expressions venant de l'anglais, de l'espagnol,de l'italien,du portugais, de l'allemand ,du latin et de l'espéranto.Il est composé de modules bilingues et monolingues,de conjuguateurs automatiques. Il est disponible en version Mac, Windows, Palm, Pocket PC avec des centaines de milliers d'entrées et effectue la traduction de blocs de texte.Il dispose également d'un module de grammaire et orthographe pour chacune des langues.

 

 

LIMITATIONS

 

    1 - Nag-screen au démarrage.

    2 - Time-limit de 20 jours (20 jours n'est pas une durée mais le nombre de jours différents pendant lesquels vous pouvez lancer le programme).

    3- Désactivation de la recherche dans le dictionnaire au dela de 20 jours.

 

LES OUTILS

 

Windasm 8.9
Pour désassembler le progamme (transformation en langage d'assemblage) et pour trouver les string data references nécessaires pour élaborer le crack.

WinHex 10.2
Pour éditer l'exécutable et modifier certains octets dans le but de la cracker. On cherche l'offset trouvé dans Windasm 8.9 impliqué dans la protection et on utilise ce même offset dans WinHex pour effectuer physiquement la modification.

 

 

ASSEMBLEUR

 

Offset
 Déplacement depuis le début de la zone de code d'un programme.

EB
      Code hexadécimal correspondant en assembleur à un saut inconditionnel (jmp).
             On saute tout le temps vers un endroit du code.

90
      Code hexadécimal correspondant en assembleur à une instruction à rien (= nop = No OPeration). 

 

LE CRACK

 

         Détail des modifications ultralingua.exe

OctetAdresse OffsetOriginalCrackéEffet
1

00437FD2

37FD2

0F90Forçage du saut vers l'enregistrement
2

00437FD3

37FD3

85E9Forçage du saut vers l'enregistrement

3

004380F6

380F6

0001Statut enregistré

 

ANALYSE  DU  PROGRAMME

 

        Ultralingua.exe

 

         Avant propos

           On va s'attaquer aujourd'hui au dictionnaire français anglais de la société ultralingua. Avant de commencer je voudrais faire un petit rappel sur le désassemblage de ultralingua par w32dasm. Lorsque l'on désassemble le programme par la commande Disassembler -> Open File to disassemble -> ultralingua.exe et qu'on regarde les string data référence (clic sur le bouton StrnRef de la barre de bouton de w32dasm) on voit qu'une chaîne "Thank you for registeringUltralingua <MODULE>." est présente. Le programme peut donc être passé de la version "non enregistrée" à la version "enregistrée". On s'en saurait douté car il y a possibilité de saisir une clef d'enregistrementdans le menu Aide -> Saisirla clef d'enregistrement.

 

         Recherche du statut enregistré

           Pour enlever toutes les limitations du programme j'ai choisi de ne pas m'attaquer à la String Data Référence "Thank you for registeringUltralingua <MODULE>.". En effet il y a plus simple.Si on clique sur le bouton Exp Fn dans la barre de bouton de w32dasm on observe dans la liste des fonctions exportées par le programme une particulièrement intéressante au nom très significatif :

           ?isRegistered@ULDataManager@@QBE_NW4ULLanguage@@0K@Z.

           Cette fonction permet de connaître le statut du logiciel (enregistré ou non).Cliquons sur cette fonction pour voir où elle est définie dans le code.

 

* Referenced by a CALL at Addresses:
|:00412EA8  , :0041CECC   , :0041D220   ,:0041E4D1   

 

Exported fn(): ?isRegistered@ULDataManager@@QBE_NW4ULLanguage@@0K@Z - Ord:0111h
 
:00434AA055push ebp
...
:00434AC6E885340000call 00437F50
...
:00434ACEC20C00ret 000C

 

            Dans le code de la fonction nous n'avons qu'un seul call.C'est dans celui-ci que se fait la vérification du statut enregistré ou non.Dans w32dasm sélectionnez la ligne d'adresse 00434AC6 puis appuyez sur la flèche droite du clavier pour aller à l'intérieur du call 00437F50.On arrive ici

 

* Referenced by a CALL at Addresses: |:00434AC6 , :004352E2 , :0043814C
 
:00437F5055push ebp
 

            On voit alors que la vérification du statut enregistré se fait depuis 3 adresses dans le code à savoir les adresses 00434AC6, 004352E2 , 0043814C (elles appellent toutes les 3 l'adresse 00437F50).Voici ce qu'on va faire.Au lieu de remonter aux 3 adresses et faire un peu de bricolage sur les registres pour modifier le résultat de la fonction d'enregistrement on va carrément modifier la fonction d'enregistrement pour la forcer à chaque fois à rendre la valeur enregistré.Pour cela on va analyser ligne par ligne le code exécuté par le programme dès que celui-ci passe sur l'adresse 00437F50.On charge le programme en mémoire avec la commande CTRL L de w32dasm.Puis on pose un bp (breakpoint ou point d'arrêt) sur l'adresse 00437F50 (séléctionnez la ligne d'adresse 00437F50 puis F2).Démarrez le débugging d'ultralingua par F9.

            Ensuite vous entendez un bing. w32dasm s'est arrêté sur le bp qu'on a posé en 00437F50.A partir de là on débuggue en mode pas à pas ultralingua.exe en appuyant plusieurs fois sur F8 (une pression sur F8 exécute une ligne de code).On arrête les F8 dès que l'on est arrivé à la fin de la fonction c'est à dire dès que l'on arrive sur l'instruction assembleur ret.

           :00438125     C21000                  ret 0010

            A ce moment là on regarde les lignes de code exécutées par le programme (ces lignes ont leur adresse en rouge) en remontant du ret (situé à l'adresse 00438125) vers le début de la fonction (situé à l'adresse 00437F50).

 

 
* Reference To: ultralingua.??1ulstring@@QAE@XZ
 
:004380CFE84C2FFFFFcall 0042B020
:004380D4C745FCFFFFFFFFmov [ebp-04], FFFFFFFF
:004380DB8D4D98lea ecx, dword ptr [ebp-68]
:004380DEE86DD9FFFFcall 00435A50
:004380E38A857EFFFFFFmov al, byte ptr [ebp+FFFFFF7E]
:004380E9EB2Djmp 00438118
 
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00438012(C), :0043802E(C), :0043803A(C), :00438046(C), :00438052(C)
 
:004380EBE9CDFEFFFFjmp 00437FBD
 
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00437FD2(C)
 
:004380F0C6857DFFFFFF00mov byte ptr [ebp+FFFFFF7D], 00
:004380F7C645FC00mov [ebp-04], 00
:004380FB8D4DCClea ecx, dword ptr [ebp-34]
 
* Reference To: ultralingua.??1ulstring@@QAE@XZ
 
:004380FEE81D2FFFFFcall 0042B020
:00438103C745FCFFFFFFFFmov [ebp-04], FFFFFFFF
:0043810A8D4D98lea ecx, dword ptr [ebp-68]
:0043810DE83ED9FFFFcall 00435A50
:004381128A857DFFFFFFmov al, byte ptr [ebp+FFFFFF7D]
 
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004380BF(U), :004380E9(U)
 
:004381188B4DF4mov ecx, dword ptr [ebp-0C]
:0043811B64890D00000000mov dword ptr fs:[00000000], ecx
:004381228BE5mov esp, ebp
:004381245Dpop ebp
:00438125C21000ret 0010
 

             En regardant les adresses qui ont été exécutées (de couleur rouge dans w32dasm) et celles qui ne le sont pas on voit que le programme a exécuté les adresses de 004380CF à 004380E9 puis a sauté vers 00438118 pour exécuter les adresses de 00438118 à 00438125.Et le bloc d'adresses 004380EB -> 00438112 pourquoi ne l'a t'il pas été exécuté ? Voyons ce qu'il y a à l'intérieur :

 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00437FD2(C)
 
:004380F0C6857DFFFFFF00mov byte ptr [ebp+FFFFFF7D], 00
:004380F7C645FC00mov [ebp-04], 00
:004380FB8D4DCClea ecx, dword ptr [ebp-34]

 

             Le programme à l'adresse 004380F0 met le byte 00 dans le contenu de l'adresse ebp+FFFFFF7D (les crochets en assembleur ça veut dire "contenu de" ce qu'il a entre crochets). Intéressant ça ! Quand le programme met le byte 00 ou 01 dans une adresse en général cela signifie en français enregistré=true ou enregistré=false suivant la valeur donnée à 00ou 01 (ie false ou true).Pourquoi ai-je choisi :

             mov byte ptr [ebp+FFFFFF7D], 00
             plutôt que
             mov [ebp-04], 00

             Eh bien cela vient du fait que la valeur rendue par la fonction à savoir enregistré ou non enregistré est stockée dans le registre al et que c'est dans cette variable qu'est mis le contenu de ebp+FFFFFF7D.En effet plus bas dans le code vous avez la ligne de code suivante (voir plus haut le listing) qui traduit cette affectation :

             :00438112    8A857DFFFFFF      mov al, byte ptr[ebp+FFFFFF7D]

             Conclusion c'est bien le contenu de l'adresse ebp+FFFFFF7D et non pas celui de l'adresse ebp-04 qui est impliqué dans l'enregistrement.C'est dans celle-ci que nous allons mettre la valeur 01 pour enregistrer le programme en remplaçant la ligne de code

             :004380F0   C6857DFFFFFF00   mov byte ptr [ebp+FFFFFF7D],00
             par
             :004380F0   C6857DFFFFFF01   mov byte ptr [ebp+FFFFFF7D],01

             Pour effectuer physiquement la modification on ouvre dans winhex une copie de ultralingua.exe et par la commande ALT G on se positionne sur l'offset 380F0 (pour obtenir 380F0 sélectionnez la ligne d'adresse004380F0 dans w32dasm et regardez dans la barre de statut en bas à droite de @Offset).Ensuite dans winhex remplacez le code hexadécimal en rouge (C6857DFFFFFF00 devient C6857DFFFFFF01).

 

             Ce n'est pas fini ! Pour que le programme puisse mettre 01 dans [ebp+FFFFFF7D] il faut obliger le programme à venir en 004380F0 ce qui n'est pas le cas actuellement.

 

:00437FC8E8F3040100call 004484C0
:00437FCD0FB6C8movzx ecx, al
:00437FD085C9test ecx, ecx
:00437FD20F8518010000jne 004380F0
...
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00437FD2(C)
 
:004380F0C6857DFFFFFF00mov byte ptr [ebp+FFFFFF7D], 00
:004380F7C645FC00mov [ebp-04], 00
:004380FB8D4DCClea ecx, dword ptr [ebp-34]

 

             Il suffit de forcer le saut en 00437FD2 en rempalçant dans winhex (offset 37FD2) le code hexadécimal (en rouge) :

             :00437FD2   0F8518010000   jne 004380F0
             
par
             :00437FD2   90                       nop
             :00437FD3   E918010000       jmp004380F0

 

 

            2 questions / réponses pour bien comprendre comment fonctionne la routine d'enregistrement

          ->Comment est-ce que je sais que c'est dans al que le résultat de la fonction est mis ?
            Regardez le premier listing de cette page.On arrive depuis 4 adresses :00412EA8,:0041CECC, :0041D220 ,:0041E4D1 dans la fonction ?isRegistered@ULDataManager@@QBE_NW4ULLanguage@@0K@Z. Prenez l'adresse 0041CECC

* Reference To: ultralingua.?isRegistered@ULDataManager@@QBE_NW4ULLanguage@@0K@Z
 
:0041CECCE8CF7B0100call 00434AA0
:0041CED10FB6C8movzx ecx, al
:0041CED485C9test ecx, ecx
:0041CED6744Fje 0041CF27
...
:0041CF22E9B1000000jmp 0041CFD8
 
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041CED6(C)
 
:0041CF276A00push 00000000
 
* Possible Reference to String Resource ID=12310: "<DAYSREMAINING> days remaining"
 

             On voit que l'instruction (qui suit le call 00434AA0 = appel à la fonction isRegistered) met dans ecx la valeur de al ( movzx ecx,al ) et qu'ensuite un test (un et logique) sur cette variable conditionne le saut ou non vers "<DAYSREMAINING> days remaining" ( je 0041CF27 ). C'est donc bien la variable al qui détermine si on est enregistré on non.

          ->Comment est ce que je sais que la valeur de al doit être égale à 1 ?
            Regardez le listing de la question précédente.Pour éviter le "<DAYSREMAINING> days remaining" il faut que al=01 ie ecx=00000001 pour que le test ecx, ecx qui est en fait un and 00000001, 00000001 rende 1 (ZF=0).Dans ce cas le saut je 0041CF27 (jump if equal to zero dans la dernière instruction exécutée ie test ecx, ecx) ne s'exécute pas et donc le programme ne saute pas vers <DAYSREMAINING> days remaining (dans la dernière instruction exécutée on a obtenu 1).

 

CONCLUSION

 

         Dans ce cours vous avez appris la localiser rapidement la fonction d'enregistrement grâce au nom explicite donné à certaines fonctions exportées par le programme.De plus vous avez appris à trouver l'endroit dans le code où est situé la protection (la variable impliquée et la valeur qu'elle doit recevoir pour enregistrer le programme) en remontant dans le code depuis la fin de la fonction d'enregistrement.Cette analyse vous a conduit à utiliser les jump références et à comprendre certaines instructions d'assembleur comme les test les sauts conditionnels (je).

 

Bonne soirée à tous.
Et à bientôt pour de nouveaux cours.
Pifoman

 



pifoman




Nombre de visites depuis le 10/02/2005