Le reverse engineering comme un nul(l) 2/?

La théorie, c’est bien. Mais vous devez commencer à me connaître : la pratique c’est mieux !

Au cours de cet article, vous apprendrez comment :

  • utiliser Resources Hacker.
  • casser la protection d’un logiciel simple.
  • créer un générateur de clefs valides pour ce même logiciel.

Je vous préviens tout de suite : il y aura de l’assembleur, la barbe est donc de mise !

Parce que le cracking consiste à "ouvrir" une application, il peut s'apparenter au crochetage d'une serrure (lockpicking)

Parce que le cracking consiste à « ouvrir » une application, il peut s’apparenter au crochetage d’une serrure (lockpicking)

Introduction

Attention ! L’exemple cité dans cet article est là à titre éducatif. Si vous souhaitez utiliser un logiciel payant, pensez aux développeurs, achetez le. Casser les protections d’un logiciel est le plus souvent interdit.

N’arrivant pas à trouver un logiciel avec un niveau de sécurité suffisamment faible, j’ai choisi celui présenté dans ce tutoriel vidéo : http://www.youtube.com/watch?v=0nz_v3vsTlg

Ne vous inquiétez pas, seule une petite partie de mon article reprend ce qui est présenté dans la vidéo 🙂

Que fait ce logiciel ?

Après avoir téléchargé ce keylogger, nous l’exécutons une première fois.

Une interface standard pour une licence limitée.

Une interface standard pour une licence limitée.

Nous avons 5 jours pour essayer ce logiciel. Nous pouvons entrer un nom d’utilisateur et une clef d’enregistrement dans quatre champs de saisie de quatre caractères chacun.

Je saisis les données suivantes :

  • test
  • 1234 2345 3456 4567

Après validation du formulaire, j’obtiens le message : « Registration code or user name is invalid. Please check all fields and try again! »

Rien d’anormal. Notons cependant ce message sur un bout de papier : il nous sera utile.

Utiliser resource hacker comme un nul(l)

Resource hacker est un petit logiciel disponible ici : http://www.angusj.com/resourcehacker/

Il est simple d’utilisation, ouvrons bpk.exe :

  • File > Open…

Pas trop dur, jusque là 🙂

On peut par exemple modifier le texte affiché dans la fenêtre montrée plus haut.

  • View > Find text…
  • On saisit « This software may be installed »

Nous arrivons tout de suite sur les données de la bonne fenêtre.

Resource hacker nous affiche même une fenêtre d'édition graphique !

Resource hacker nous affiche même une fenêtre d’édition graphique !

Ensuite, rien de plus simple :

  1. On modifie les libellés que l’on veut
  2. On clique sur Compile Script
  3. File > Save As…

Il ne nous reste qu’à lancer la version modifiée du logiciel !

Résultat avec resource hacker

On peut ainsi modifier la plupart des éléments statiques et standards d’une application :

  • Texte
  • Icônes
  • Images
  • Positionnement des boutons et des libellés
  • Couleurs
  • Etc.

Casser une protection simple

Pour casser la protection de ce logiciel, nous utiliserons OllyDbg, un outil très simple d’utilisation et plutôt convivial… si on admet que l’assembleur peut être convivial :-p

C’est un outil gratuit servant à déboguer des exécutables. Il permet ainsi de visualiser le code assembleur de l’application, de placer des points d’arrêt, d’exécuter l’application pas à pas, etc.

Commençons par charger l’exécutable dans OllyDbg :

  • File > Open…

Situer la portion de code validant la clef

La première étape consiste à déterminer quelle portion de code on modifiera. Pour ce faire, nous pouvons, dans la mesure du possible, nous aider des réactions de l’application lorsque nous entrons une mauvaise clef d’enregistrement.

Cherchons dans l’exécutable la chaîne de caractères « Registration code or user name is invalid. Please check all fields and try again! ».

C’est enfantin :

  1. Clic droit > Search for > All referenced strings
  2. Une nouvelle fenêtre s’ouvre avec toutes les chaînes de caractères enregistrées dans l’application
  3. Clic droit > Search for text
  4. On saisit le texte voulu, on valide, puis on double clique sur la ligne de résultat

Chercher une chaîne de caractères dans ollybdg

Chercher une chaîne de caractères dans ollybdg

Le programme nous renvoie là où est utilisée cette chaîne de caractères.

Il s’agit de l’appel servant à créer une fenêtre popup. L’appel à cette fonction est situé quelques lignes sous l’utilisation de la chaîne de caractères, exactement à l’adresse 0041AF86.

Etudier le code environnant

Si l’on n’est pas habitué à lire de l’assembleur, ça peut prendre du temps. Heureusement OllyDbg est là pour nous aider !

Il faut remarquer que l’on arrive à l’utilisation de cette chaîne de caractères par un saut conditionnel qui part de l’adresse 0041AF05 vers 0041AF78.

Le second point à voir est le suivant : si l’on ne saute pas à l’adresse 0041AF78, le programme ignorera la création de la popup ainsi que l’appel à une méthode.

En effet, nous trouvons à l’adresse 0041AF76 un saut inconditionnel (tout le temps exécuté), donc il n’y aura pas d’erreur d’enregistrement.

Etude du code avec OllyDbg

On remarque le saut inconditionnel et le saut conditionnel.

Modifier le code

La solution la plus simple pour faire en sorte que le programme accepte n’importe quelle clef est de supprimer le saut conditionnel. L’application n’entrera jamais dans la portion de code affichant une erreur et validera la clef.

OllyDbg est équipé d’un outil très simple d’utilisation pour supprimer des portions de code. Il vous suffit de sélectionner les lignes à supprimer (en l’occurrence les lignes aux adresses 0041AF03 et 0041AF05), de faire un clic droit et d’utiliser la fonction Edit > Fill with NOPs.

Edition avec OllyDbg

Il ne nous reste qu’à répercuter les modifications dans notre exécutable :

  1. Sélectionner les lignes où l’on a placé les NOPs
  2. Clic droit > Edit > Copy to executable
  3. Une nouvelle fenêtre s’ouvre
  4. Clic droit > Save As… (ou quelque chose dans le genre)

Si vous exécutez votre application modifiée, vous pourrez entrer le nom d’utilisateur que vous souhaitez et n’importe quelle clef, vous serez alors enregistré !

Vous pourrez trouver une vidéo de cette méthode, où l’auteur utilise un autre outil : http://www.youtube.com/watch?v=0nz_v3vsTlg

Créer un générateur de clefs (KeyGen)

Soyons maintenant créatif ! Casser une protection peut engendrer des effets de bord et une instabilité de l’application.

Si nous parvenons à générer des clefs valides, nous n’aurons alors pas à modifier le programme original, et il n’y aura aucun effet indésirable.

Le saut à l’adresse 0041AF05 est conditionné par la vérification de la clef d’enregistrement. Si l’on est capable d’inverser l’algorithme de vérification de la clef, on sera capable de générer des clefs !

Situer la portion de code validant la clef

On remarque une portion de code intéressante et une comparaison de chaîne de caractères conditionnant le saut

On remarque une portion de code intéressante et une comparaison de chaîne de caractères conditionnant le saut

Il faut comprendre à quoi correspond le code assembleur. On peut facilement délimiter une portion de code intéressante, indiquée par un trait rouge sur la capture d’écran.

Voici son analyse :

0041AEAD |. FF15 4C414400 CALL DWORD PTR DS:[<&KERNEL32.lstrcpyA>] // On copie une chaîne de caractères
0041AEB3 |. 8B3D 98414400 MOV EDI,DWORD PTR DS:[<&KERNEL32.lstrcat // On se prépare à concaténer des chaînes de caractères
0041AEB9 |. 8D45 D8 LEA EAX,[EBP-28]
0041AEBC |. 50 PUSH EAX
0041AEBD |. 8D45 80 LEA EAX,[EBP-80]
0041AEC0 |. 50 PUSH EAX
0041AEC1 |. FFD7 CALL EDI // Fusionne la première et la seconde cellule de la clef
0041AEC3 |. 8D45 C0 LEA EAX,[EBP-40]
0041AEC6 |. 50 PUSH EAX
0041AEC7 |. 8D45 80 LEA EAX,[EBP-80]
0041AECA |. 50 PUSH EAX
0041AECB |. FFD7 CALL EDI // Fusionne le résultat avec la troisième cellule de la clef
0041AECD |. 8D45 CC LEA EAX,[EBP-34]
0041AED0 |. 50 PUSH EAX
0041AED1 |. 8D45 80 LEA EAX,[EBP-80]
0041AED4 |. 50 PUSH EAX
0041AED5 |. FFD7 CALL EDI // Fusionne le résultat avec la dernière cellule de la clef
0041AED7 |. 8D85 18FFFFFF LEA EAX,[EBP-0E8]
0041AEDD |. 50 PUSH EAX ; /Arg3 => ARG.EBP-0E8 // Le dernier argument de la méthode qui sera appelée est la clef
0041AEDE |. 8D85 4CFFFFFF LEA EAX,[EBP-0B4] ; |
0041AEE4 |. 68 40814400 PUSH OFFSET 00448140 ; |Arg2 = ASCII "_r <()<1-Z2[l5,^" // Le second argument de la méthode qui sera appelée est un masque statique
0041AEE9 |. 50 PUSH EAX ; |Arg1 => ARG.EBP-0B4 // Le premier argument de la méthode qui sera appelée est le nom d'utilisateur
0041AEEA |. E8 1FFEFFFF CALL 0041AD0E ; \bpk.0041AD0E // Méthode qui sert à générer la clef attendue
0041AEEF |. 83C4 0C ADD ESP,0C
0041AEF2 |. 8D45 80 LEA EAX,[EBP-80]
0041AEF5 |. 50 PUSH EAX
0041AEF6 |. 8D85 18FFFFFF LEA EAX,[EBP-0E8]
0041AEFC |. 50 PUSH EAX
0041AEFD |. FF15 58414400 CALL DWORD PTR DS:[<&KERNEL32.lstrcmpiA> // On vérifie si la clef saisie est la clef attendue
0041AF03 85C0 TEST EAX,EAX // Si le résultat de l'appel à strcmp est différent de 0 (chaînes différentes), on effectue le saut
0041AF05 75 71 JNE SHORT 0041AF78

C’est un petit peu dur, je sais… en gros, voici ce qui est fait :

  1. Les quatre champs de saisie correspondant à la clef sont fusionnés en une seule chaîne de 16 caractères.
  2. Le nom d’utilisateur, un masque statique, ainsi que la clef, sont passés à une méthode servant à générer la clef attendue
  3. La clef attendue est comparée avec la clef réelle pour validation

Dans mon cas, j’ai saisi la clef 1234 2345 3456 4567 et le nom d’utilisateur test.

Situer la portion de code générant la clef attendue

Bien évidemment, la méthode qui nous intéresse est bpk.0041AD0E. Il faut mettre un point d’arrêt (Clic droit > Breakpoints > toggle) à l’adresse 0041AEEA et lancer le programme en mode debug (le triangle bleu dans la barre d’outils).

L’exécution de l’application sera alors suspendue lorsque vous tenterez de valider une clef d’enregistrement. Vous devrez cliquer sur le bouton avec une petite flèche en angle droit (Step into) pour entrer dans la méthode.

Vous pouvez continuer l’exécution du code en mode pas-à-pas à l’aide des boutons Step into et Step over pour essayer de comprendre le fonctionnement de l’application.

Il faut remarquer une boucle où entrent en jeu le nom de notre utilisateur et le masque statique.

J'ai indiqué le code de la boucle par un trait rouge.

J’ai indiqué le code de la boucle par un trait rouge.

Analyse du code et récupération de l’algorithme

A chaque occurrence, un caractère du masque statique est modifié selon l’algorithme suivant :

0041AD5A |> /8BC6 /MOV EAX,ESI
0041AD5C |. |6A 19 |PUSH 19 // Stocke 19h = 25 pour le récupérer quelques lignes plus bas
0041AD5E |. |99 |CDQ
0041AD5F |. |F77D FC |IDIV DWORD PTR SS:[LOCAL.1]
0041AD62 |. |8BC6 |MOV EAX,ESI
0041AD64 |. |5B |POP EBX // Récupère le diviseur pour le calcul de la lettre (19h = 25)
0041AD65 |. |8D0C3A |LEA ECX,[EDI+EDX] // Récupère le caractère du masque à l'index 0 + X
0041AD68 |. |99 |CDQ
0041AD69 |. |F77D F8 |IDIV DWORD PTR SS:[LOCAL.2] // Calcule le modulo de l'index avec la longueur du nom
0041AD6C |. |8B45 08 |MOV EAX,DWORD PTR SS:[ARG.1] // Récupère le nom d'utilisateur
0041AD6F |. |0FB60402 |MOVZX EAX,BYTE PTR DS:[EAX+EDX] // Récupère la valeur ASCII du caractère du nom à la position X modulo la longueur du nom
0041AD73 |. |0FB611 |MOVZX EDX,BYTE PTR DS:[ECX] // Récupère la valeur ASCII du caractère du masque à la position X
0041AD76 |. |33C2 |XOR EAX,EDX // Fait un XOR des deux codes ASCII
0041AD78 |. |99 |CDQ
0041AD79 |. |F7FB |IDIV EBX // Divise le résultat par 25
0041AD7B |. |80C2 41 |ADD DL,41 // Ajoute 41h = 65 au résultat
0041AD7E |. |46 |INC ESI // Incrémente l'index
0041AD7F |. |3B75 0C |CMP ESI,DWORD PTR SS:[ARG.2]
0041AD82 |. |8811 |MOV BYTE PTR DS:[ECX],DL // Modifie le caractère à la position X du masque avec la valeur calculée
0041AD84 |.^\7C D4 \JL SHORT 0041AD5A // Tant que l'index est inférieur à la longueur du masque, on continue

Encore une fois, c’est pour les barbus. Il est important de vous mettre à étudier l’assembleur si vous voulez casser vos propres applications.

Pour vous aider, vous avez accès, dans la partie en haut à droite de la fenêtre, à l’état des variables au moment de l’exécution de la ligne en cours. Toutes les valeurs sont indiquées en hexadécimales, n’oubliez pas de faire la conversion en décimales si besoin !

J'ai encadré la variable EAX contenant 19 (en hexadécimales), ESI contenant un indice (1) et le masque en cours de modification dans la variable EDI.

J’ai encadré la variable EAX contenant 19 (en hexadécimales), ESI contenant un indice (1) et le masque en cours de modification dans la variable EDI.

Remarquez que 65 (41 en hexadécimales) est le code ASCII de A et 25 + 65 = 90 est celui de Z (25 correspond à 19 en hexadécimales).

La clef attendue par le logiciel sera toujours composée de 16 lettres, de A à Z, en majuscules.

Pour l’utilisateur test, la clef attendue selon l’algorithme est SXIWRBETONPWYFUR.

Création du générateur de clefs

Une fois l’algorithme compris, il ne nous reste qu’à l’implémenter avec n’importe quel langage de programmation (JavaScript par exemple) :

<script language="javascript">
 function genere_clef(){
 var nom = document.getElementById("nom").value;
 var masque = "_r <()<1-Z2[l5,^";
 var clef = "";
 for(var i = 0;i<masque.length;i++){
 var ascii_nom = nom[i % nom.length].charCodeAt(0);
 var ascii_masque = masque[i].charCodeAt(0);
 var xor = ascii_nom ^ ascii_masque;
 clef += String.fromCharCode(65 + xor % 25);
 }
 document.getElementById("clef1").value = clef.substring(0,4);
 document.getElementById("clef2").value = clef.substring(4,8);
 document.getElementById("clef3").value = clef.substring(8,12);
 document.getElementById("clef4").value = clef.substring(12);
 }
</script>
Nom d'utilisateur : <input id="nom" onchange="genere_clef();" onkeyup="genere_clef();" /><br />
Clef : <input id="clef1" /><input id="clef2" /><input id="clef3" /><input id="clef4" />

Vous êtes l’heureux possesseur d’un générateur de clefs artisanal !

Conclusion

L’outil Resource Hacker est puissant. Il fait bien ce pourquoi il a été conçu. Mais concrètement, il ne pourra vous servir qu’à piéger vos amis, camoufler une application pour pour qu’elle ressemble à une autre avant de l’exécuter (propriétés, icône, etc.), etc. Cet outil porte bien son nom, il est conçu pour modifier les données de l’application, mais en aucun cas fonctionnalités de celle-ci.

OllyDbg est un outil gratuit et simple d’utilisation. Je le recommande vivement pour tous ceux qui voudraient se mettre à étudier l’assembleur, ou qui seraient curieux de comprendre le fonctionnement bas niveau d’un programme compilé.

Casser les protections d’un logiciel disposant de peu de sécurités est très simple. Cependant, casser une protection peut entraîner des instabilités lors de l’exécution de l’application. Pour casser une sécurité simple, la suppression ou l’ajout de sauts est souvent suffisant.

Créer un générateur de clefs demande plus de connaissances du langage assembleur. Le pirate devra étudier le code assembleur afin d’en retirer l’algorithme de vérification de la clef d’enregistrement, pour ensuite l’inverser et en déduire l’algorithme de génération de clefs valides. Dans notre cas, ce dernier algorithme nous est servi sur un plateau car l’application génère la clef attendue, donc nous n’avons pas eu besoin d’inverser cet algorithme.

J’ai eu beaucoup de mal à trouver une application pour rédiger cet article. La plupart des applications actuelles mettent en oeuvre de meilleurs moyens pour sécuriser la vérification des clefs, rendant le travail des pirates plus compliqué. C’est une course entre les développeurs et les pirates. Je reviendrai, dans un prochain article, sur les méthodes utilisées pour sécuriser une application.

Parce que je n’ai pas la science infuse : sources

Publicités
À propos

Un informaticien, qui tente de faire comprendre au public que l'informatique n'est pas si compliquée, malgré des acronymes et autres termes obscurs pour faire croire que c'est difficile (et que c'est de votre faute si "ça ne marche pas")

Tagged with: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
Publié dans Algorithmie, Cracking, Développement, Informatique, Piratage, Windows
2 comments on “Le reverse engineering comme un nul(l) 2/?
  1. Alexandre dit :

    Merci pour cet article plus qu’intéressant! Je l’ai lu, relu et encore relu.
    C’est un des premiers tuto aussi complet que j’ai eu l’occasion de lire sur le reverse engineering.

    Mes bases en assembleur laissent quelques instructions incomprises.
    IDIV DWORD PTR SS:[LOCAL.2]
    MOV EAX,DWORD PTR SS:[ARG.1]
    Dans les 2 cas, si j’ai bien compris, on a un double mot (DWORD) pointé (PTR) une l’adresse sur le segment mémoire de la pile (SS). Ce que j’ai du mal à assimiler c’est la valeur entre crochets, LOCAL.2 et ARG.1. Moi qui est toujours eu l’habitude de voir (en cours théorique en faite) des valeurs telles que EAX, EBP, ESP..
    Le nom d’utilisateur serait donc ARG.1 et sa longueur LOCAL.2 ?

    De plus, autre interrogation :
    Lors de l’analyse du code en mode pas à pas, il y a un très grand nombre d’instruction entre l’appel de la fonction où l’on a posé le breakpoint et l’entrée dans la boucle qui nous intéresse.
    Que se passe-t-il pendant ce (long) moment ? Comment savoir que l’ont doit poursuivre notre pas à pas jusque là ? (Le seul indice que j’ai pu voir c’était l’état des variables, est-ça, notre informateur?)

    • mystcaster dit :

      Bonjour,

      « LOCAL.2 » fait référence au second pointeur dans la pile (registre EBP). « LOCAL.1 » est donc le premier pointeur. A piori, « LOCAL.2 » correspond à « -8(%ebp) »
      « ARG.1 » fait référence au premier argument passé à la méthode (donc un pointeur vers le nom d’utilisateur)

      Pendant ce « long moment », on dépile les arguments passés à la méthode et on crée une copie du masque.
      On vérifie aussi la longueur des champs (la clef doit avoir la même taille que le masque par exemple).

      Pour savoir jusqu’où poursuivre le pas à pas, il faut imaginer le code : comment il a pu être conçu, quelles signes peuvent être révélateurs d’une vérification ou d’une génération (sauts conditionnels, boucles, etc.) et focaliser son attention dessus. Ensuite, l’état des variables est un bon indicateur pour inverser l’algorithme.

      Pour casser les protections d’un programme, il faut donc avoir de (très) bonnes compétences en algorithmie et réussir à s’imaginer comment le développeur a implémenté telle ou telle fonctionnalité.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

MystCaster
juillet 2013
L M M J V S D
« Juin   Août »
1234567
891011121314
15161718192021
22232425262728
293031  
Catégories
Archives
%d blogueurs aiment cette page :