Hello World à tous !
Voici quelques mois que je n’ai pas écrit d’article. Aujourd’hui nous allons voir comment désassembler, modifier et recompiler un EXE ou une DLL précédemment compilé en .Net ou en WinRT.
Avant toute chose, une petite mise en garde au cas où : désassembler un programme peut s’avérer être illégal selon la licence associée au composant que vous allez exploiter.
Voilà, je me sens beaucoup mieux. :) Qu’allons-nous voir plus précisément ?
ILDASM et ILASM
Je m’attaque à un cas de figure particulier. Généralement nous désassemblons un Assembly grâce à des outils comme JustDecompile ou .Net Reflector. Ces deux outils ont l’avantage de nous afficher du code C# compréhensible de tous, et même de l’exporter sous forme de projet pour Visual Studio. Seulement quelquefois, ça ne fonctionne pas très bien. Et c’est pire quand l’Assembly a été obfusqué auparavant (là en général c’est un désassemblage totalement illégal…) car ça ne compile même pas et il faudrait des jours voir des semaines pour obtenir un code qui compile correctement sans avoir changé le comportement du programme.
Du coup, la solution que je propose est de mettre la main dans le MSIL (Microsoft Intermediate Language). C’est un langage intermédiaire généré lors de la compilation et qui est converti par la suite en code natif. L’avantage est que même obfusqué, il est compilable.
On peut facilement récupérer ce fameux IL (qui ressemble à de l’Assembleur) et le recompiler par la suite grâce à deux outils que vous avez déjà probablement sur votre PC :
- ILDASM : outil fournit dans le SDK de Windows et qui permet d’extraire l’IL.
- ILASM : outil fournit dans le .Net Framework de Windows (pas au même endroit qu’ILDASM donc) et qui permet de compiler un IL.
Exemple
Partons dans un cas extrêmement simple : j’ai récupéré quelque par un exécutable .Net « ConsoleApplication1.exe » qui affiche « Hello » à l’écran. Mon but est de faire en sorte que le programme affiche « Hello World :D » à la place.
Oui ça n’a aucun intérêt de se faire chier à lire du MSIL alors que l’application ne fait que 10 lignes de code à tout casser et qu’il n’est pas obfusqué, mais c’est pour l’exemple. Donc, en temps normal, avec un Assembly qui fait des milliers et des milliers de lignes, avant de commencer à récupérer le MSIL, on aurait regardé le code C# affiché par JustDecompile par exemple, et on aurait repéré la partie (le nom d’une méthode, d’une classe…) que l’on veut modifier une fois désassemblé.
Une fois que vous savez quoi chercher dans le MSIL, vous êtes prêt à désassembler pour « hacker » ce qui vous intéresse.
Utilisez la ligne de commande suivante dans une invite de commande (CMD) :
"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\ildasm.exe" ConsoleApplication1.exe /out:ConsoleApplication1.il
Une fois la commande exécutée, vous trouverez les fichiers suivants :
- ConsoleApplication1.exe : c’est l’Assembly que vous avez désassemblé.
- ConsoleApplication1.il : c’est le fichier dans lequel vous avez sauvegardé le MSIL. C’est un simple fichier texte en fait.
- ConsoleApplication1.res : ce sont les ressources de l’Assembly (les images par exemple, qui ne peuvent pas être traduites sous forme de code).
A présent, ouvrez donc le fichier « ConsoleApplication1.il » dans votre éditeur de code préféré (il y a une extension pour Visual Studio qui propose une coloration de syntaxe pour l’IL). Vous trouverez au début les informations sur l’Assembly (auteur, version, nom…etc), et juste en dessous le code qui représente les classes et les méthodes.
Voici à quoi ressemble le code de notre application console :
Pas « si » compliqué que ça non ?
Remplacez le « Hello » par « Hello World :D » :
Enregistrez, et nous allons recompiler. Toujours dans une invite de commande, exécutez la commande suivante :
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe" ConsoleApplication1.il /resource:ConsoleApplication1.res /exe /output:ConsoleApplication1_edited.exe
- « ConsoleApplication1.il » : le code IL à compiler.
- « /resource:ConsoleApplication1.res » : le fichier de ressources (ça serait bête de ne plus avoir les images dans le programme).
- « /exe » : on précise que l’on souhaite compiler un exécutable et non une librairie.
- « /output:ConsoleApplication1_edited.exe » : le nom du fichier une fois compilé.
Note : conformément à la documentation, s’il s’agit d’un Assembly WinRT, ajoutez le paramètre « /appcontainer ».
Une fois terminé, si tout va bien, vous devriez pouvoir voir « Hello World :D » lorsque vous lancez « ConsoleApplication1_edited.exe ».
Signature
Un dernier point à aborder je pense, c’est celui du certificat. En effet, si l’Assembly que vous avez désassemblé était signé, vous ferez face à un « FileLoadException » ou bien un « AccessViolationException » si vous tentez de le charger dans un projet (si cet Assembly est une DLL par exemple).
Deux actions à faire pour être sûr de ne pas avoir de problème :
- Avant de désassembler, supprimer le Strong Name Key de l’Assembly d’origine. Ce petit programme fait très bien le boulot : http://www.nirsoft.net/dot_net_tools/strong_name_remove.html
- Lors de la recompilation, générer un SNK et le fournir à ILASM : http://www.geekzilla.co.uk/ViewCE64BEF3-51A6-4F1C-90C9-6A76B015C9FB.htm
Conclusion
A moins que vous ne soyez allergique à tout ce qui peut ressembler de loin ou de près à du code bas niveau, éditer un code MSIL n’est pas très compliqué. Le plus dur peut-être est de modifier les numéros de jeux d’instruction (les « IL_0000 »…) quand on modifie ce qui correspond à des for, while, try, catch, if.
Au final les étapes à suivre sont les suivantes :
- Essayer d’abord de désassembler avec JustDecompile ou .Net Reflector ou autre.
- S’il est impossible de recompiler le C#, identifier ce que l’on souhaite modifier dedans (chercher le nom d’une classe et le nom d’une méthode précise).
- Désassembler avec ILDASM.
- Rechercher dans l’IL la classe/méthode à modifier. Appliquer les modifications sans tout casser (c’est le plus difficile).
- Recompiler avec ILASM.