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.3 fr

 

INFOS SUR LE CRACK

 

Nom du progUltralingua 5.0.3
Editeur

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

Téléchargeablehttp://highspeed1.movedigital.com
Date du prog Vendredi 18 février 2005
Date du crack Mardi 22 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

0043C582

3C582

0F90Forçage du saut vers l'enregistrement
2

0043C583

3C583

85E9Forçage du saut vers l'enregistrement

3

0043C6A6

3C6A6

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:
|:004144F9 , :00414511 , :00414529 , :00414541 , :00414556
:0041456D , :00414584 , :0041459B , :00414FF3 , :0041F425
|:0041F930 , :00420BD1
 
*Exported fn(): ?isRegistered@ULDataManager@@QBE_NW4ULLanguage@@0K@Z - Ord:0114h
 
:004378C055 push ebp
...
:004378E6E8154C0000 call 0043C500
...
:004378EEC20C00 ret 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 004378E6 puis appuyez sur la flèche droite du clavier pour aller à l'intérieur du call 0043C500.On arrive ici

 

* Referenced by a CALL at Addresses:
|:004378E6 , :00438102 , :0043C6FC
 
:0043C50055 push ebp
 

            On voit alors que la vérification du statut enregistré se fait depuis 3 adresses dans le code à savoir les adresses 004378E6 , 00438102 , 0043C6FC (elles appellent toutes les 3 l'adresse 0043C500).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 0043C500.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 0043C500 (séléctionnez la ligne d'adresse 0043C500 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 0043C500.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.

            0043C6D5    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 0043C6D5) vers le début de la fonction (situé à l'adresse 0043C500).

 

* Reference To: ultralingua.??1ulstring@@QAE@XZ
 
:0043C67FE85C15FFFF call 0042DBE0
:0043C684C745FCFFFFFFFF mov [ebp-04], FFFFFFFF
:0043C68B8D4D98 lea ecx, dword ptr [ebp-68]
:0043C68EE8FD97FCFF call 00405E90
:0043C6938A857EFFFFFF mov al, byte ptr [ebp+FFFFFF7E]
:0043C699EB2D jmp 0043C6C8
 
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0043C5C2(C), :0043C5DE(C), :0043C5EA(C), :0043C5F6(C), :0043C602(C)
 
:0043C69BE9CDFEFFFF jmp 0043C56D
 
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043C582(C)
 
:0043C6A0C6857DFFFFFF00 mov byte ptr [ebp+FFFFFF7D], 00
:0043C6A7C645FC00 mov [ebp-04], 00
:0043C6AB8D4DCC lea ecx, dword ptr [ebp-34]
 
* Reference To: ultralingua.??1ulstring@@QAE@XZ
 
:0043C6AEE82D15FFFF call 0042DBE0
:0043C6B3C745FCFFFFFFFF mov [ebp-04], FFFFFFFF
:0043C6BA8D4D98 lea ecx, dword ptr [ebp-68]
:0043C6BDE8CE97FCFF call 00405E90
:0043C6C28A857DFFFFFF mov al, byte ptr [ebp+FFFFFF7D]
 
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0043C66F(U), :0043C699(U)
 
:0043C6C88B4DF4 mov ecx, dword ptr [ebp-0C]
:0043C6CB64890D00000000 mov dword ptr fs:[00000000], ecx
:0043C6D28BE5 mov esp, ebp
:0043C6D45D pop ebp
:0043C6D5C21000 ret 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 0043C67F à 0043C699 puis a sauté vers 0043C6C8 pour exécuter les adresses de 0043C6C8 à 0043C6D5. Et le bloc d'adresses 0043C69B -> 0043C6C2 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:
|:0043C582(C)
 
:0043C6A0C6857DFFFFFF00 mov byte ptr [ebp+FFFFFF7D], 00
:0043C6A7C645FC00 mov [ebp-04], 00
:0043C6AB8D4DCC lea ecx, dword ptr [ebp-34]

 

             Le programme à l'adresse 0043C6A0 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 :

             :0043C6C2   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

             :0043C6A0   C6857DFFFFFF00       mov byte ptr [ebp+FFFFFF7D],00
             par
             :0043C6A0   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 3C6A0 (pour obtenir 3C6A0 sélectionnez la ligne d'adresse 0043C6A0 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 0043C6A0 ce qui n'est pas le cas actuellement.

 

:0043C578E8A3C6FCFF call 00408C20
:0043C57D0FB6C8 movzx ecx, al
:0043C58085C9 test ecx, ecx
:0043C5820F8518010000 jne 0043C6A0
...
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043C582(C)
 
:0043C6A0C6857DFFFFFF00 mov byte ptr [ebp+FFFFFF7D], 00
:0043C6A7C645FC00 mov [ebp-04], 00
:0043C6AB8D4DCC lea ecx, dword ptr [ebp-34]

 

             Il suffit de forcer le saut en 0043C582 en rempalçant dans winhex (offset 3C582) le code hexadécimal (en rouge) :

             :0043C582   0F8518010000   jne 0043C6A0
             
par
             :0043C582   90                       nop
             :0043C583   E918010000       jmp 0043C6A0

 

 

            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 12 adresses 004144F9 , 00414511 , 00414529 , 00414541 , 00414556, 0041456D , 00414584 , 0041459B , 00414FF3 , 0041F425, 0041F930 , 00420BD1 dans la fonction ?isRegistered@ULDataManager@@QBE_NW4ULLanguage@@0K@Z. Prenez l'adresse 0041F425

 

* Reference To: ultralingua.?isRegistered@ULDataManager@@QBE_NW4ULLanguage@@0K@Z
 
:0041F425E896840100 call 004378C0
:0041F42A0FB6C0 movzx eax, al
:0041F42D85C0 test eax, eax
:0041F42F744F je 0041F480
...
:0041F47BE9B1000000 jmp 0041F531
 
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041F42F(C)
 
:0041F4806A00 push 00000000
 
* Possible Reference to String Resource ID=12310: "<DAYSREMAINING> days remaining"
 
:0041F4826816300000 push 00003016
 

             On voit que l'instruction (qui suit le call 004378C0 = appel à la fonction isRegistered) met dans eax la valeur de al ( movzx eax,al ) et qu'ensuite un test (un et logique) sur cette variable conditionne le saut ou non vers "<DAYSREMAINING> days remaining" ( je 0041F480 ). 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 eax=00000001 pour que le test eax, eax qui est en fait un and 00000001, 00000001 rende 1 (ZF=0).Dans ce cas le saut je 0041F480 (jump if equal to zero dans la dernière instruction exécutée ie test eax, eax) 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

 

         Ce cours est une refonte du cours sur de cracking sur ultralingua 5.0.2.Le mécanisme de protection est le même que dans la version 5.0.2 et pour tous les dictionnaires d'ultralingua (français anglais, français italien, français espagnol, français anglais médical, français définitions, français allemand) car l'exécutable est le même.Seules les adresses dans le listing de désassemblage changent.

         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 26/02/2005