Contenu

Introduction au reverse engineering avec Radare2 & compagnie - Partie 1

Introduction au reverse engineering avec Radare2 & compagnie - Partie 1

Objectif

Cet article est le premier d’une série traitant du reverse-engineering logiciel. L’objectif de cette première partie est simplement la découverte de quelques outils utiles dans ce domaine.

Dans une partie 2 à venir, nous traiterons la résolution d’un challenge du type capture the flag grâce à ces outils.

Introduction

La rétro-ingénierie (ou en moins franchouillard et plus courant reverse engineering) consiste à étudier le comportement d’un système afin d’en comprendre son fonctionnement interne. En informatique, les applications du reverse engineering de fichiers binaires sont multiples:

  • 🕵 analyser des programmes malveillants
  • 🕵 améliorer la sécurité / rechercher des failles
  • 🥷 contourner des protections logicielles
  • 🥷 altérer le comportement d’un programme

Un fichier binaire est généralement constitué de plusieurs choses :

  • des méta-données et un entête
  • des données
  • des instructions codées dans un langage compréhensible par un type de processeur, pour un système donné

Pour ce premier tutoriel, on posera les bases du reverse en se concentrant sur les fichiers ELF (Executable and Linkable Format) sous Linux.

Fichiers ELF

Sous Linux, ELF est le format le plus courant de fichiers binaires. Dans ce format, un binaire est constitué d’un entête fixe, de segments et de sections.

man elf permet d’obtenir des informations détaillées sur la structure ELF.

/reverse-engineering-intro-radare2/elf.png

Pour la suite du tutoriel, nous prendrons comme victime la commande ls, que l’on trouve sur n’importe quel poste Linux.

Outils disponibles par défaut sous Linux

Pour commencer à disséquer notre programme ls, plusieurs commandes doivent déjà être disponibles par défaut sous Linux. Si elles ne sont pas présentes, vous pouvez les installer via votre installeur préféré (apt, yum, etc.)

strings

strings permet d’extraire et afficher toutes les chaînes de caractères incluses dans un exécutable.

Lancez la commande suivante et observez le résultat :

strings /bin/ls

/reverse-engineering-intro-radare2/strings.png

ltrace

Permet de tracer les appels de fonctions de bibliothèques.

ltrace /bin/ls

/reverse-engineering-intro-radare2/ltrace.png

strace

Même chose que ltrace, mais pour les appels système.

strace /bin/ls

/reverse-engineering-intro-radare2/strace.png

file

file affiche les caractéristiques de l’exécutable passé en paramètre. On verra plus loin que rabin2, qui vient avec radare2, remplit aussi cette fonction.

1
2
└─$ file /bin/ls         
/bin/ls: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6461a544c35b9dc1d172d1a1c09043e487326966, for GNU/Linux 3.2.0, stripped

hexdump

hexdump affiche la représentation hexadécimale de l’exécutable.

Exemple : hexdump -C binary.bin | less

/reverse-engineering-intro-radare2/hexdump.png

Radare2

Passons aux choses sérieuses. Les petits tools présentés plus haut sont sympa, mais nous allons voir un outil beaucoup plus complet, et qui permet aussi bien l’analyse statique sans exécuter le programme) que l’analyse dynamique (en débugant/exécutant le programme, avec des points d’arrêts, etc.)

Radare2 est un framework opensource pour l’analyse de binaires. Il comprend énormément de formats différents, dont ELF. Sa CLI ergonomique permet de désassembler un binaire, analyser ses données, patcher, comparer, chercher, faire des remplacements, etc.

Installation

Clonez le repo, lancez le script d’install et allez chercher un ☕ le temps de l’installation.

1
2
3
git clone https://github.com/radare/radare2.git
cd radare2
./sys/install.sh

Les updates sont réguliers. Pour être à jour, il suffit de lancer ./sys/install.sh

Premières commandes pour découvrir

rabin2

Ok, commençons par extraire quelques informations de base grâce à la commande rabin2 :

rabin2 -I /bin/ls

-I équivaut à l’option Show binary info

r2

Analysons la commande ls : r2 /bin/ls. Une fois radare2 lancé, entrez la commande vpp. Vous affichez ainsi un des modes graphiques de radare2.

/reverse-engineering-intro-radare2/vpp.png

La touche p permet d’alterner entre les affichages graphiques. Pour quitter le mode graphique, appuyez sur q.

💡 Si vous ne comprenez rien aux symboles et au code obscure, pas de panique. L’objectif de ce premier article n’est pas de tout comprendre, mais simplement se familiariser avec l’outillage. Dans un prochain article, nous nous attarderons sur les aspects généraux du code assembleur, de son rapport avec le code machine, et les principes de fonctionnement d’un programme, des registres processeurs, de la pile d’exécution, etc.

Lancez la commande aaa, qui permet de lancer une analyse par défaut. L’analyse permet à Radare2 d’identifier des zones du programme intéressantes (ce qu’on appelle les flags), et les catégoriser en flagspaces. Autrement dit, un flag est une information intéressante, d’une certaine catégorie (section, fonction, symbol, chaine de caractère, etc.). Un flagspace correspond donc à un ensemble de flags de la même catégorie.

Par exemple

Pour afficher un résumé des flagspaces, entrez fs.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[0x00006160]> fs
    0 . classes
    5 . format
  126 * functions
  112 . imports
   18 . registers
  118 . relocs
   30 . sections
   12 . segments
  432 . strings
   19 . symbols

Choisissons le flagspace strings : fs strings.

Une fois un flagspace sélectionné, il suffit d’entrer f pour afficher les flags correspondants:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[0x00006160]> f
0x00019610 12 str.dev_ino_pop
0x00019688 11 str.sort_files
0x00019693 7 str.posix_
0x0001969a 5 str.main
0x00019750 11 str._pcdb_lswd
0x00019760 66 str._Configuration_file_for_dircolors__a_utility_to_help_you_set_the
0x000197a2 73 str._LS_COLORS_environment_variable_used_by_GNU_ls_with_the___color_option.
0x000197eb 57 str._Copyright__C__1996_2020_Free_Software_Foundation__Inc.
0x00019824 71 str._Copying_and_distribution_of_this_file__with_or_without_modification_
0x0001986b 77 str._are_permitted_provided_the_copyright_notice_and_this_notice_are_preserved.
0x000198b8 60 str._The_keywords_COLOR__OPTIONS__and_EIGHTBIT__honored_by_the
0x000198f4 62 str._slackware_version_of_dircolors__are_recognized_but_ignored.
0x00019932 65 str._Below_are_TERM_entries__which_can_be_a_glob_patterns__to_match
0x00019973 75 str._against_the_TERM_environment_variable_to_determine_if_it_is_colorizable.
0x000199be 11 str.TERM_Eterm
0x000199c9 10 str.TERM_ansi
0x000199d3 13 str.TERM_color
[...]

Quick reference - mémo - cheatsheet

Commande Description
r2 -d commande ou r2 -d pid Lance radare2 en mode debug et se positionne juste avant l’entry point main
vpp Entre en mode debugger visuel:
- La touche p permet de switcher entre les modes visuels
- [F7] pour debug step into
- [F8] pour debug step over
- [F2] pour positionner un breakpoint
fs Affiche les flagspaces
fs * Sélectionne tous les flagspaces (par défault)
fs strings Sélectionne le flagspace des chaines de caractère
f Affiche les valeurs du (des) flagspace(s) courant(s)
"? 1 + 2 * 12" Calcule une expression : /reverse-engineering-intro-radare2/expression.png
dr ou dr= Affiche la valeur des registres généraux
i Affiche des infos sur le fichier binaire (même chose que rabin2 -I monfic)
iS= Affiche les sections avec une visualisation en barres ascii art. Pour la notion de section, se référer à la doc officielle de radare2
pd Désassemble le code
ie Affiche le point d’entrée du programme
aaa Lance une analyse automatique des fonctions du programme
afl Liste les fonctions du programme
pdc@0x080485f5 Désassemble en pseudo-c le code de la fonction ayant pour adresse 0x080485f5
/reverse-engineering-intro-radare2/pdc.png

Tips - astuces

Astuce
Pour afficher une aide contextuelle à une commande, ajouter un point d’intérrogation. Ex: afl?
Pour répéter une commande plusieurs fois, préfixer du nombre de répétitions. Ex: 3px
En mode visuel (Vpp), les commandes classiques sont disponibles en appuyant préalablement sur : (comme dans vi)
On peut chaîner plusieurs commandes avec le point-virgule, comme dans un shell. Ex: fs strings; f
Pour les outputs json, ajouter ~{} pour prettifier le résultat. Ex: of~{} au lieu de of

Ressources externes

Le Radare2 book officiel : https://book.rada.re/