|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ce cours est un reflet fidèle du cours intégré au crack de ma création de Ultralingua 5.0.2 fr
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
Offset Déplacement depuis le début de la zone de code d'un programme. EB 90
Détail des modifications ultralingua.exe
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.
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
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).
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 :
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 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 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.
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
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 ?
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 ?
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.
![]()
|