====== Exercice de découverte de désassemblage avec radare2 ====== Nous allons dans cette note d'exercice essayer de découvrir l'usage du logiciel de débogage et désassemblage [[https://www.radare.org/n/|Radare2]]. Pour cela : * utilisation d'un petit logiciel en C (//codé avec les pieds//) fourni * Nous allons utiliser radare2 pas à pas * Désassembler le logiciel en C * découvrir quelques notions et manipulations basiques * Récupérer le //phrase de passe// qui //verrouille// se logiciel * **Niveau prérequis** : * débutant⋅e avec curiosité * usage rudimentaire de linux * **Matériel requis** : une machine avec un système unix/linux * **Temps à dédier** : 30 minutes à 1 heure grand max Cette note concerne un exercice pédagogique de découverte et absolument pas une pratique professionnelle. Elle n'est pas applicable dans l'état à un manipulation de désassemblage sur un logiciel potentiellement malveillant − ce qui nécessiterait bien d'autres considérations et mise en place de sécurité. ===== Installation des logiciels nécessaires ===== ==== gcc ==== [[https://gcc.gnu.org/|GCC]], //the GNU Compiler Collection// Cette étape est uniquement prévue pour vous fournir un petit logiciel non compromettant à analyser afin permettre de découvrir radare2. Elle ne vise pas d'objectif d'apprentissage − nous ne nous y attarderons pas ici Ce logiciel vous permettra de compiler le logiciel en langage C que vous allez désassembler. > « //GCC (GNU Compiler Collection) est une suite de logiciels libres de compilation. On l'utilise dans le monde Linux dès que l'on veut transcrire du code source en langage machine, c'est le plus répandu des compilateurs. La suite gère le C et ses dérivés mais aussi le Java ou encore le Fortran.// » [[https://doc.ubuntu-fr.org/gcc|Doc Ubuntu]] À votre charge d'installer GCC avec votre gestionnaire paquet dans votre distribution (pacman, apt, yay, etc.) === logiciel en C pour désassemblage === Ce petit bout de logiciel //écrit avec les pieds// n'a pas d'autre vocation que d'être compilé pour fournir un exécutable ([[wp>fr:Executable_and_Linkable_Format|ELF]]. Ceci afin de vous fournir un //jouet// de découverte et d'entraînement. Ne soyez pas trop attentive, attentive à son écriture et son contenu Le code source que vous devez copier dans un éditeur de texte (note, gdit…) ou de code (VScodium par exemple). Placez vous dans le répertoire puis dossier qui vous convient et créez un fichier ''1st_reverse.c'' pour y écrire : #include #include #include int main (int argc, char **argv) { int valeur; if (argc < 2) //Si mdp correct, le proramme se termine avec succès { fprintf (stderr, "Erreur manque un argument pour %s de type chaine de caractère \n (#>_<)\n", argv[0]); //Si programme excuté sans argument, affichage d'un message d'erreur return EXIT_FAILURE; //On sort du programme. } valeur = strcmp (argv[1],"FrenchCuisine"); //le `strcmp` effectue une opération de comparaison entre l'argument passée et le mot de passe codé en clair if (valeur == 0) // Si valeur = 0, signifie que le mdp rentré est correct printf ("Bravo ! \n Vous avez le bon mot de passe ! elf (fichier exécutable) cracké \n ⊂(“◉‿◉)つ \n '%s' est ton sésame\n", argv[1]); // affiche le texte signifiant "Réussite" else printf ("Pas le bon mot de passe, essaye encore ! '%s' est incorrect \n <(°_0)…>\n", argv[1]); // Affiche du texte "Échec" return EXIT_SUCCESS; //Fin du programme, sortie. } Si vous souhaitez approfondir cette partie : * [[pages:norae:si:dev_note-form_4|les rudiments de la programmation en C en 28 courtes sessions.]] * [[pages:norae:si:dev_note-form-2|Note de préparation d'atelier pour débuter en langage C/C++]] **Compilation du fichier source** Nous allons maintenant compiler ''1st_reverse'' pour obtenir un exécutable. - Ouvrez un [[wp>fr:Terminal_(informatique)|terminal]] depuis votre menu de bureau ou en faisant ''ctrl''+''alt''+''t''. - Placez dans le dossier du répertoire contenant votre fichier ''1st_reverse.c'' - Taper ''ls'' comme commande dans votre terminal vous vérifier la présence de ''1st_reverse.c'' - Entrez la commande ''gcc --help'' pour vérifier la disponibilité de GCC et avoir un aperçu des commande disponible − ''q'' pour sortir - Entrez la commande ''gcc -o 1st_reverse 1st_reverse.c'' - ''-o'' signifie à GCC que l'exécutable compilé se nommera ''1s_reverse'' - Si tout se passe passe (y'a pas de raison que ça plante, normalement…) n'aurez pas d'affichage de message informatif à la fin du processus - Entrer ''ls'' pour obtenir la liste des fichiers dans l'emplacement où vous êtes situé⋅e dans votre terminal - ''1st_reverse'' devrait maintenant être disponible. ==== radare2 ==== [[wp>fr:Radare2]] //est un lociel libre destiné à la rétro-ingénierie et à l'analyse de fichiers binaires ; composé d'un jeu d'outils pouvant être utilisés ensemble, ou séparément depuis l'invite de commande.// Dans une démarche similaire à l'installation de GCC, installez Radare2 dans votre ordinateur. Ou si vous êtes motivé⋅e⋅s, installation aussi possible ainsi : > git clone https://github.com/radare/radare2.git > cd radare2 > ./sys/install.sh === Config de radare2 === Pour une utilisation moins abrupte et quelques facilités d'usage, nous vous proposons après installation de créer un fichier de configuration pour radare2 nommé ''radare2rc'' et placé ainsi dans son chemin ''~/.config/radare2/radare2rc'' {{radare2-illustration.png}} Nous proposons de lui donner les paramètres de configuration suivants # Show comments at right of disassembly e asm.cmt.right=true # Shows pseudocode in disassembly. Eg mov eax, str.ok = > eax = str.ok e asm.pseudo=false #ESIL EMU #e asm.emu=true #e asm.esil=true # Display stack and register values on top of disasembly view (visual mode) e cmd.stack=true # selected theme ; see https://r2wiki.readthedocs.io/en/latest/home/themes/ eco basic # Set color e scr.color=3 # Use UTF-8 to show cool arrows that do not look like crap :) e scr.utf8=true # to make the outlines beautiful e asm.describe=true # to enable command autocompletion e cfg.newtab=1 # Sanbox settings e cfg.sandbox=false # so on finest settings e asm.bits=64 e asm.lines.call=true e asm.lines.out=true # enable fortune in the starter e cfg.fortunes=true e cfg.fortunes.type=fun,tips,nsfw # enable the pager e scr.pager=less -R # Show tiny graph # e cmd.gprompt=aga # e cmd.vprompt= e graph.scroll=10 e graph.bubble=false e graph.dummy=true Et pour activer ceux-ci tapez ''source ~/.bashrc'' ou ''source ~/.zshrc'' dans votre terminal pour les activer. ==== gdb + peda ==== Supplément optionnel à votre découverte, pour cela voir [[pages:norae:si:note_reverse-embarquee#gdb_peda_voltron|gdb+peda]] ===== Manipulations ===== **Commençons enfin à manipuler ce que nous avons mis en place** Comme indiqué dans [[norae:si:note_reverse-embarquee|Astuces dans la pratique de Reverse avec outils embarqués pour OSINT]], partons d'une petite mise en bouche rapide. Essayez dans votre terminal : > ./1st_reverse Puis ''Enter'' pour lancer. Qui est ce qui semble le plus probable pour lance l'exécutable ''1st_reverse''. Puis suivez votre intuition, répétez la commande et/ou ajoutez y ce qui vous semblera opportun après ''./1st_reverse'' dans votre terminal avant d'appuyer sur entrée. ==== Prise d'informations avant désassemblage ==== Utilisons ''[[pages:norae:si:note_reverse-embarquee#file|file]]'' pour observer ce qu'est ''1st-reverse'' La commande dans le terminal : > file 1st_reverse 1st_reverse: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=7b20020d4fb2915355e8822387c7976d696822d6, for GNU/Linux 3.2.0, not stripped Ce qui nous importe un premier est ''ELF'' : notre fichier est un exécutable. Notons également les infos complémentaires ''64-bit'' qui nous indique que cet exécutable à été par et pour un [[wp>fr:Processeur_64_bits]] à partir d'une distribution Linux architecturée en [[wp>fr:X64|x86-64]] avec un noyau ''GNU/Linux 3.2.0'' Pour de prochaines aventures * La signature pas hashage [[wp>fr:SHA-1]] nous intéressera * Empreinte du //hash// : ''7b20020d4fb2915355e8822387c7976d696822d6'' Utilisons maintenant ''[[pages:norae:si:note_reverse-embarquee#strings|strings]]'' > strings 1st_reverse strings 1st_reverse /lib64/ld-linux-x86-64.so.2 mih" libc.so.6 stderr fprintf __cxa_finalize strcmp __libc_start_main GLIBC_2.2.5 _ITM_deregisterTMCloneTable __gmon_start__ _ITM_registerTMCloneTable u3UH []A\A]A^A_ Erreur manque un argument pour %s de type chaine de caract (#>_<) FrenchCuisine Bravo ! Vous avez le bon mot de passe ! elf (fichier executable) crack '%s' est ton s […] Vous noterez peut-être des premières informations intéressantes telles qu'une erreur potentielle dans le code, voir bien plus grave infos… Passons maintenant à [[pages:norae:si:note_reverse-embarquee#diff|xxd]] > xxd 1st_reverse | less 00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............ 00000010: 0300 3e00 0100 0000 6010 0000 0000 0000 ..>.....`....... 00000020: 4000 0000 0000 0000 e039 0000 0000 0000 @........9...... 00000030: 0000 0000 4000 3800 0b00 4000 1d00 1c00 ....@.8...@..... 00000040: 0600 0000 0400 0000 4000 0000 0000 0000 ........@....... 00000050: 4000 0000 0000 0000 4000 0000 0000 0000 @.......@....... […] 00000290: 1802 0000 0000 0000 1802 0000 0000 0000 ................ 000002a0: 0100 0000 0000 0000 2f6c 6962 3634 2f6c ......../lib64/l 000002b0: 642d 6c69 6e75 782d 7838 362d 3634 2e73 d-linux-x86-64.s […] 00002050: 0046 7265 6e63 6843 7569 7369 6e65 0000 .FrenchCuisine.. […] Nous obtenons confirmation d'informations précédentes ainsi que des compléments avec la vue hexadécimale (//hexdump//) de notre fichier * Indexation du nombre de lignes. (ex : ''00000000, 00000010, 00000020...................00000220'') * Le nombre d'octets par défaut par groupe est de 2 (-e : 4 little-endian hexdump), ce qui correspond à une taille de groupe de 4 octets. (ex : ''7f45 4c46....................0000'') * La longueur standard de la colonne est égale à 16 [[wp>fr:Byte|bytes]] avec les espaces. (ex : pour la ligne terminant par''.ELF'') * ''7f 45 4c 46 02 01 01 00'' Ces numéros aident le système à identifier le type de fichier utilisé. Certains fichiers qui ne sont pas écrits avec leur extension, sont identifiés à l'aide de ces //[[wp>fr:Nombre_magique_(programmation)|nombres magiques]]//. ''7F 45 4C 46'' pour les ELF (notre fichier de code source avant compilation avait pour extension ''.c'') * Pour //revenir// à l'état de notre fichier avant le //hexdump// avec la commande ''xxd'', faisons : > xxd 1st_reverse > 1st_reverse.txt # Pour sauvegarder notre dump dans un fichier texte Puis > xxd -r 1st_reverse.txt […] Erreur manque un argument pour %s de type chaine de caractère (#>_<) FrenchCuisineBravo ! Vous avez le bon mot de passe ! elf (fichier executable) cracké ⊂(“◉‿◉)つ '%s' est ton sésame […] ==== Désassemblage avec radare2 ==== === Premier pas === Première étape, lancer radare2 visant notre fichier cible > r2 1st_reverse -- This is just an existentialist experiment. [0x00001060]> Rappel > r2 /bin/ls aaa # analyze all the things is # list symbols afl # list functions found pdf # disassemble function s # seek to address v # enter visual panels mode Maintenant commençons par lancer une analyse de tout notre « programme » du fichier cible > r2 1st_reverse -- This is just an existentialist experiment. [0x00001060]> aaa [x] Analyze all flags starting with sym. and entry0 (aa) [x] Analyze function calls (aac) [x] Analyze len bytes of instructions for references (aar) [x] Check for objc references [x] Check for vtables [x] Type matching analysis for all functions (aaft) [x] Propagate noreturn information [x] Use -AA or aaaa to perform additional experimental analysis. [0x00001060]> Avec la commande ''aaa'' radare2 indique les étapes à suivre. Chaque étape a la commande qui en est responsable entre parenthèses. ''aaa'' est une commande qui exécute d'autres commandes. Elle affiche également une brève description de l'action de chaque commande. Vous trouverez des informations un peu plus détaillées sous ''aa?'' === Analyse des fonctions === Passons maintenant à l'étape suivante d'analyse de fonction avec la commande ''afl'' [0x00001060]> afl 0x00001060 1 46 entry0 0x00001090 4 41 -> 34 sym.deregister_tm_clones 0x000010c0 4 57 -> 51 sym.register_tm_clones 0x00001100 5 65 -> 55 sym.__do_global_dtors_aux 0x00001150 1 9 entry.init0 0x00001000 3 27 sym._init 0x00001280 1 5 sym.__libc_csu_fini 0x00001288 1 13 sym._fini 0x00001210 4 101 sym.__libc_csu_init 0x00001159 7 168 main 0x00001030 1 6 sym.imp.printf 0x00001040 1 6 sym.imp.strcmp 0x00001050 1 6 sym.imp.fprintf Nous avons ici : * L'adresse de chaque fonction de notre fichier cible ''1st_reverse'' figure dans la première colonne et le symbole dans la dernière * 2ème colonne : Le nombre de blocs de base dans la fonction * 3ème colonne : La taille de la fonction (en octets) * 4ème colonne : Nom de la fonction le numéro qui vient après le "->". Si c'est le cas, lorsqu'il y a un "->", le nombre de gauche est la plage de la fonction, tandis que celui de droite indique la taille de la fonction. Cela ne se produit que lorsque la plage et la taille sont différentes. Dans notre cas d'exemple ''sym.imp.strcmp'' qui nous interpelle. Cette fonction compare des chaînes de caractères, comme des phrases de passe entrées et celle correcte désirée, ''strcmp'' retourne 0 si les chaînes comparer sont identiques. ''> man strcmp'' dans votre terminal vous donnera plus d'indications. Utiliser une sortie en ''JSON'' La plupart des commandes informatives de radare2 peuvent être accompagnées d'un ''j'' pour formater la sortie en JSON. Ajoutons ''~{}'' pour formater la sortie avec une indentation JSON pour une autre lisibilité et lecture : Exemple : >[0x00001060]> aflj~{} Nous donne {{norae:si:set1_radare2_test.png}} === Vue d'ensemble des fonctions et cartographie === la commande ''main''((Documentation officielle de ''main'' pour radare2 https://radare.gitbooks.io/radare2book/content/crackmes/avatao/01-reverse4/main.html)) Nous utilisons cette commande avec l'option de visualisation graphique fournie par radare2 avec ''VV''. Ainsi [0x00001060]> VV @main Nous donne {{set2_radare2_test.png}} === Naviguer dans les fonctions du fichier === Depuis le graphique ascii de radare2 vous pouvez naviguer en utilisant les touches fléchées et pour zoomer ''+'' et dézoomer ''-''. Si vous regardez le premier bloc du graphique en bleu, vous pouvez voir * ''%%; arg char **arg @ rsi%%'' qui correspond à une instruction de requête de de chaîne de caractères. * Puis ''push word, doubleword or quadword onto the stack'' qui signifie qu'un chaîne de caractère, très probablement équivalente à une phrase de passe, est attendue dans la pile d'instruction de fonctionnement de notre fichier. * ''; compare two operands'' signifie qu'il y une opération qui compare aux données saisies par la personne à l'aide de la fonction strcmp. Ensuite, il y a vérification de la condition si les chaînes sont égales ou non. Si elles ne sont pas égales, nous suivons la ligne verte T (qui signifie "true") jusqu'à ces blocs de code : {{set3_radare2_test.png}} Zoomons avec ''+'' sur le bloc entouré en blanc {{set4_radare2_test.png}} Que pouvons nous voir ? {{set4-1_radare2_test.png.png}} La chaîne de caractère inscrite //en clair// telle que ''“FrenchCuisine”'' nous interpelle. Ensuite vous pouvez vous lancer à la recherche de notre premier mot de passe. === Avançons === Pour vérifier notre piste de ''FrenchCusine'' comme phrase de valide suivons les fils de notre graphique ascii qui représente le comportement de la fonction ''main'' de notre fichier cible Lorsque nous tentons de faire fonctionner ''./1st_reverse'' sans aucun argument ou chaîne de caractères : > ./1st_reverse Erreur manque un argument pour ./1st_reverse de type chaine de caractère (#>_<) Repartons de notre 1er bloc (bleu) en haut de notre graphique **Rouge** (f = false) {{set5-1_radare2_test.png}} Si nous donnons un argument en chaîne de caractère, exemple : > ./1st_reverse password Pas le bon mot de passe, essaye encore ! 'password' est incorrect <(°_0)…> {{set6-1radare2_test.png}} Si nous donnons un argument en chaîne de caractères avec ''FrenchCuisine'' > ./1st_reverse FrenchCuisine Bravo ! Vous avez le bon mot de passe ! elf (fichier executable) cracké ⊂(“◉‿◉)つ 'FrenchCuisine' est ton sésame {{set6-2_radare2_test.png}} Vous avez percez le secret de votre fichier qui était jusqu'à présent quasi totalement illisible et inexécutable correctement. ===== Ouvrons plus loin ===== Le fait de parcourir les fonctions et leurs comportements dans la pile d'instruction de notre fichier cible n'est pas encore à proprement parler du désassemblage. Nous allons maintenant passer à un exercice de modification du code binaire fichier cible, notamment pour utiliser des commande de désassemblage dans radare2 telles que ''pdf'' ou ''pd'' −−> [[pages:norae:si:exercice_1er_desassemblage_avec_radare2|1er désassemblage avec radare2]] ===== Listes de ressources ===== ==== Documentation générale ==== * Official book https://radare.gitbooks.io/radare2book/content/configuration/evars.html * radare2 wiki https://r2wiki.readthedocs.io/en/latest/tools/radare2/ * Github doc intro https://github.com/radareorg/radare2/blob/master/doc/intro.md ==== radare2 writtings for practices === * 4 blog posts with clear approach https://insinuator.net/tag/radare2/ * Reverse Engineering With Radare2 — Part 2 https://archive.is/NQlKD * CMU Bomb Lab with Radare2 — Phase 1 https://archive.is/wip/LfpIr **Tools included** * rax2-> base converter * rabin2-> extract binary * inforasm2-> (dis)assembler * rahash2-> crypto/hashing utility * radiff2-> binary diffing * ragg2-> compile tiny bins * rarun2->run with different env * rafind2->find byte patterns * r2pm-> r2 package manager * r2/radare2-> main tool * Understanding buffer overflows using Radare2 https://rderik.com/blog/understanding-buffer-overflows-using-radare2/ === Sub notes === **For radare2rc** * cmd.stack -> Command to display the stack in visual debug mode * cmd.cprompt -> Column visual prompt command * cmd.gprompt -> Graph visual prompt commands * cmd.vprompt -> Visual prompt commands