Logiciel protégé par dongle de rétro-ingénierie
J’étais jeune, Internet ne faisait que commencer et nous pouvions obtenir des tonnes de logiciels gratuitement. C’était gratuit parce que quelqu’un là-bas était assez « gentil » pour casser / réparer le.EXE.
J’ai mis « gentil » entre les guillemets, car c’était le point de vue que j’avais quand j’étais enfant. Maintenant, je suis ingénieur logiciel et je sais combien d’efforts il faut pour créer un logiciel. Alors, ne téléchargez pas de logiciel fissuré. Soutenez le développeur et achetez une licence !
En appliquant une telle fissure, en corrigeant l’exe, j’ai toujours voulu savoir comment faire une telle chose. Il s’avère que vous devez comprendre l’assembleur, un langage machine que seul votre processeur comprend (et d’autres nerds là-bas). Comme c’était trop difficile, je n’ai jamais pu l’apprendre. Jusqu’à récemment (comme 20 ans plus tard 😊).
Il y a un an, j’ai acheté un logiciel (avec une licence !) qui a besoin d’un dongle USB pour fonctionner. C’est vraiment lourd d’avoir ce dongle avec vous à tout moment. Surtout quand vous êtes sur la route. J’ai donc cherché des moyens de le contourner. La première chose que j’ai rencontrée était cet émulateur de clé appelé MultiKey. Il décharge la mémoire de votre dongle dans votre registre, puis émule votre dongle en lisant à partir de votre registre. Cela a bien fonctionné, jusqu’à ce que je veuille l’exécuter sur Windows 10. Apparemment, Microsoft n’est pas un si grand fan de MultiKey. En réalité, ce n’est pas un grand fan des pilotes non signés et MultiKey utilise un pilote non signé. J’avais donc besoin d’une autre solution. Il est temps de plonger dans cette chose appelée code d’assemblage!
J’ai toujours su qu’il existait un outil de rétro-ingénierie, appelé IDA. Il est capable de décompiler votre.fichier exe et montrez ce qui se passe. Malheureusement, l’interface est vraiment difficile à comprendre. Je connaissais aussi OllyDbg. C’est un débogueur. Un débogueur vous permet de parcourir le code assembleur pendant l’exécution du programme ! Ce qui signifie, par exemple, si vous déboguez l’application de calculatrice, vous pouvez la voir gérer une pression sur un bouton, effectuer le calcul et afficher le résultat à l’écran. Enfer, vous pouvez même pauze et changer sa mémoire faisant que la calculatrice retourne 5 en demandant ce qu’est 2 + 2!
Mais je ne suis pas là pour changer de calcul (bien que ce soit cool). Je veux être libre du dongle. J’ai donc ouvert mon application avec OllyDbg.
C’était vraiment écrasant. Je n’avais aucune idée de ce que tous ces codes signifiaient. Encore moins de savoir par où commencer. Je suis donc retourné à la planche à dessin. Il s’avère qu’il y a quelque chose appelé RetDec, un décompilateur qui essaie de faire sortir le code C du code machine. Il m’a fallu du temps pour le mettre en place et exécuter la décompilation, mais l’effort a payé. Le résultat a été énorme.fichier c, plus de 2 millions de lignes de code avec un code semi-lisible.
En fait, j’ai pu trouver le code lisant les octets du dongle assez facile:
Avec ces informations, je suis retourné à mon débogueur. En attendant, j’ai découvert qu’OllyDbg est vraiment vieux (de l’an 2000) et n’a pas été mis à jour depuis 2013. J’ai donc trouvé ce nouveau débogueur amélioré, appelé x64dbg. C’est open source et une grande communauté de développeurs y travaille.
Langage machine de lecture
En langage machine, chaque instruction a une adresse mémoire. Donc, avec les adresses trouvées dans le code RetDec, je me suis tourné vers x64dbg et voici, le code qui lit le dongle:
Dans le code assembleur, les arguments de la fonction sont chargés en mémoire à l’aide du pointeur de pile esp. Dans notre code, cela se produit juste avant l’appel à la fonction. (les 3 instructions mov indiquent que l’appel prend 3 arguments). Après l’appel, notre pointeur de pile est réinitialisé et une vérification (test) est effectuée si l’appel à la fonction a réussi. Sinon, nous voyons le code faire un saut (jne). Ce saut pointe vers un morceau de code indiquant que le dongle n’est pas présent.
Comme vous pouvez le voir, il y a un appel à une fonction spécifique pour lire le dongle. J’ai consulté le guide de référence pour savoir ce que fait cette fonction:
La fonction lit 2 octets de mémoire (un mot) à partir du dongle. Comme on l’a deviné, la fonction prend 3 arguments où le dernier argument est un pointeur sur 2 octets qui contiendra des données du dongle.
Dans le code assembleur, les arguments sont chargés dans l’ordre inverse. Passer le dernier argument est celui-ci:
Le dernier argument pointe vers esi, ce qui signifie que les données du dongle seront stockées à l’adresse mémoire vers laquelle pointe esi.
En effet, en faisant une pause juste après l’appel, nous pouvons voir le résultat en mémoire:
0x74. C’est ce qui est lu à partir du dongle et stocké dans la mémoire du programme principal.
Pour ignorer cet appel, j’ai juste besoin d’écrire 0x74 en mémoire où esi pointe. C’est aussi simple que de remplacer les 7 lignes ci-dessus par:
Comme vous pouvez le voir, je n’ai pas non plus modifié le reste des instructions de l’assembleur, y compris le test si l’appel à la fonction était valide. Cela signifie que le saut ne sera pas effectué et que le programme continuera à fonctionner sans le contrôle.
Après avoir corrigé tous les appels impliquant le dongle, j’ai enregistré le nouveau.EXE. J’ai sorti le dongle, j’ai exécuté ma coutume.exe et à mon grand étonnement, cela a fonctionné! J’avais réussi à casser un logiciel.
Une autre chose que je croise dans ma liste de seau
Ps: la plupart des choses ont été obscurcies, comme 0x74 et le nom de l’application. Cela ne doit en aucun cas nuire aux développeurs qui ont créé ce logiciel. De plus, j’ai eu beaucoup de chance que le dongle ne renvoie que des octets et ne fasse aucun cryptage seul.