diff --git a/content/secu_systeme/1_introduction/index.md b/content/secu_systeme/1_introduction/index.md deleted file mode 100644 index e34b8b5..0000000 --- a/content/secu_systeme/1_introduction/index.md +++ /dev/null @@ -1,339 +0,0 @@ ---- -title: "Sécurité système : introduction" -date: 2023-09-07 -tags: ["bibliothèque", ".got"] -categories: ["Sécurité système", "Cours"] ---- - -## Définition : un exécutable - -C'est un fichier contenant un programme et identifié par le système -d'exploitation en tant que tel ([définition par Wikipédia][l_execwiki]). Il -existe plusieurs format d'exécutable en fonction du système d'exploitation. - -Il ne faut pas confondre programme et scripts, le premier contenant le code -**exécutable**, le second est **interprété** (par un programme) et passe -éventuellement par du code intermédiaire ou [bytecode][l_bytecode] : *Portable -Executable* Pour Microsoft Windows, *Match Object* pour Apple MacOS / iOS, -*Executable and Linkable Format* pour beaucoup de système Unix. - -Pourquoi compiler du code? Plusieurs avantages : - - * un programme compilé est moins consommateur de ressources et par conséquent - plus rapide à l'exécution; - * pour protéger sa propriété intellectuelle (par la possibilité d'obfuscation - du code machine généré); - * pour se passer de l'**interpréteur** et ainsi éviter une étape - (complexification de la pile d'exécution). - -Le code interprété a aussi ses avantages : - * il est indépendant de la plate-forme d'exécution; - * en général il existe une multitude de bibliothèques utilisable rapidement - (coucou Python); - * le développement est simplifié et plus interactif, le langage est alors plus - accessible et le développement peut-être plus rapide (langage de plus haut - niveau) - - -[l_bytecode]: https://fr.wikipedia.org/wiki/Bytecode -[l_execwiki]: https://fr.wikipedia.org/wiki/Fichier_ex%C3%A9cutable - -## La compilation - -Un exécutable contient donc du code machine, le code source qui le défini est -alors **compilé** en code machine. Mais la compilation est en fait plus -compliquée que cette simple *"traduction"*. Elle se compose en fait de 4 grande -phases : - - 1. le préprocessing; - 2. la compilation; - 3. l'assemblage; - 4. l'édition de liens - -### le préprocessing - -Chargé de modifier le code source avant la compilation. Ici le moteur de -préprocessing se charge de remplacer les macro (`#define`), les constantes -[^f_const], les inclusion d'entêtes (`#include`) par le code effectif; - -[^f_const]: Voici quelques exemples de constantes de bases : - - `__FILE__` : affiche le nom du fichier source; - - `__LINE__` : affiche le numéro de la ligne atteinte; - - `__DATE__` : affiche la date de compilation du code source; - - `__TIME__` : affiche l'heure de compilation de la source. - -### la compilation - -C'est à cette étape que le code (`C`, `C++`, `Rust` etc.) est transforme en -assembleur. Cette étape se compose elle-même de plusieurs parties. - -#### L'analyse lexicale - -Lors de cette étape, le compilateur analyse le texte du code source. Il est -découpé en *mots* ou *tokens* définis par des **expressions rationnelles** et -**des automates à états finis**. - -Il revient à **l'analyseur lexical** de réaliser cette opération. Lors de -cette étape, les *"bruits"* sont ignorés : commentaires et espaces. Les -*lexèmes* -- représentant une instance de la petite unité de signification -- -sont ainsi définis. Si l'analyseur syntaxique rencontre un lexème inconnu, il -lèvera une erreur. - -Il existe plusieurs analyseur lexicaux : flex, lex[^n_lex] etc. - -Il ne revient pas à l'analyseur syntaxique de vérifier que l'enchainement des -lexème est correct, il transmets juste le résultat de son analyse à l'étape -suivante. - -[^n_lex]: analyseur en *C* co-écrit par Eric Schmidt, cofondateur de Google. - -#### L'analyse syntaxique - -Réalisée par **l'analyseur syntaxique** qui traite les informations reçues par -l'analyseur lexical. Contrairement à l'étape précédente, il est question ici de -se focaliser sur la validités syntaxique *d'une phrase*. - -C'est un processus itératif dont le résultat est un *Arbre Syntaxique Abstrait* -construit en fonction de la **grammaire du langage**.Il est construit au fur et -à mesure que l'analyseur avance dans le code source. Deux outils d'analyse -syntaxique sont principalement utilisés : - -#### L'analyse sémantique - -Lors de cette étape le compilateur vérifie la cohérence du code, certaines -erreurs relevant de la grammaire seront détectées comme par par exemple : - -```c -// erreur sur les types -int my_integer = "a string"; - -// Accès à une variable en dehors de son scope -{ int x = 3;} x = 4; -``` -Lors de l'analyse syntaxique, l'*Arbre Syntaxique Abstrait* est enrichi -d'information sur le sens des phrases du code. - -#### La production de code intermédiaire - -Cette étape, le code est transformé dans un langage intermédiaire entre le -langage de haut niveau (*C*, *C++*) et le langage machine. C'est à partir de ce -code que le compilateur appliquera des optimisations. C'est aussi lors de cette -étape que le code peut être offusqué afin de rendre son analyse plus complexe -(dans le logiciel privateur, ça va de soit). - -#### Les optimisations - -Ici, le compilateur réalise des optimisations sur le code intermédiaire. La -plupart de ces optimisations effectué sur le code de plus haut niveau le -rendraient moins compréhensible et pourrait se révéler plus fastidieux à écrire. - -#### La génération de code assembleur - -Ici le code intermédiaire optimisé est transformé en assembleur. Le compilateur -créé les fichiers `*.S`. On appelle aussi cette étape **génération de code -natif**. Lors de cette étape, le code généré est spécifique à une architecture -donnée et ce afin de profiter des instructions disponible sur celle-ci (*MMX*, -*SSE*, *NEON* etc.). - -#### L'assemblage - -Le compilateur créé un fichier objet `*.o` par fichier source. Ces fichiers -objets sont bien des binaires, il contienne déjà les segments nécessaires -(`.text`, `.data` ...) dans un format dépendant du système cible (PE pour -Microsoft Windows©, Mach-O pour Apple MacOS©, ELF pour Linux). - -Lors de cette étape, le compilateur enlève tous les *labels*, mais afin de -pouvoir résoudre les symboles (fonctions, variables, etc.) il va créer la -**table des symboles**. - -Cette table contenu dans chacun des fichiers objets générés fait référence à la -position des élément dans ce fichier. Le compilateur résout ces symboles **lors -de l'édition de liens**. - -#### L'édition de liens - -C'est le moment ou le compilateur agrège les différents fichiers objets en un -seul exécutable. Le *linker* responsable de cette étape doit résoudre les -symboles et les liers aux différents fichiers objets et bibliothèques. - -C'est aussi lors de cette étape que les différents segments composants le -programme sont créés et que la **table de relocation** est créée (très utile -pour les mécanismes d'ALSR). - -Il existe deux type d'édition de liens : - - * **statique** : les éléments issus de bibliothèques sont inclus dans le - binaire final. Dans ce cas la résolution des symboles **est totale**; - * **dynamique** : les bibliothèques partagées ne sont pas incluses dans le - binaire. La résolution des symboles ne peut-être que partielle. - -Dans le cas de la compilation **dynamique**, le *linker* doit identifier les -symboles appartenant aux bibliothèques partagées. Leur résolution se fera alors -au moment de l'exécution. - -## Exécution - -L'exécution d'un programme se passe en plusieurs étapes : - - 1. le noyau est averti que qu'il doit charger le fichier binaire; - 2. l'élément chargé du chargement de notre binaire se charge de l'analyser; - 3. le noyau alloue de la mémoire pour notre programme; - 4. il *map* la mémoire allouée avec les éléments du programme; - 5. il est maintenant temps de passer le flot d'exécutions au programme. - -Bien évidement le binaire n'est pas chargé tel quel en mémoire, d'où l'étape -*d'analyse*. Sous Linux et les système Unix en général, le format d'exécutable -utilisé est ELF. ce format, largement documenté, sert de base pour le *loader* - -### Segments et sections - -C'est deux éléments qui composent un fichier binaire au format ELF sont souvent -source de confusion. - -*Les segments* contiennent des éléments nécessaires à l'exécution alors que *les -sections* contiennent des informations utiles pour les liens, la relocation et la -résolution de symboles. - -Les *sections* sont des composantes des *segments*. Prenons l'exemple du segment -`LOAD` qui contient des sections `.data`, `.got`, `.bss` ... Elles contiennent -soit des données brutes: - - * `.text` : du code; - * `.data` : des données initialisées comme par exemple: - ```c - int x = 42; - ``` - * `.bss` : des données non initialisées - * `.rodata` : des données en lecture seule comme les constantes statiques - -## Le format ELF - -Comme nous le disions, c'est le format binaire d'enregistrement de code compilé -utilisé par la plupart des systèmes de type *Unix*. Il commence par les nombres -magiques[^n_magic] `0x7fELF`. Il se compose ensuite d'un entête fixe. Celui ci -contient (entre autres) l'*endianess* (big ou little), l'ABI, le type -(bibliothèque, exécutable), l'architecture cible. - -Après viens le *Program Header Table* qui contient des segments et informations -nécessaire à la création du processus en mémoire. - -Ensuite la *Section Header Table* référençant et décrivant les sections - -Enfin le fichier ELF contient les données référencées par ces deux tables. - -[^n_magic]: dans notre cas, ensemble de caractères utilisés pour désigner un - format de fichier. - -## ELF : Pratique - -### Propriété de `ls` - -Le plus simple pour obtenir des information est d'utiliser le programme `file`. - -```shell -$ file /bin/ls -ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, -interpreter /usr/lib/ld-linux-x86-64.so.2, -BuildID[sha1]=4d53da289d128a5ccee3f944db35244bf91c7a99, -for GNU/Linux 3.10.0, not stripped -``` - -Nous apprenons donc que cet exécutable est un ELF 64bits pour uns architecture -*Intel x86_64*, lié dynamiquement, chargé par la bibliothèque `ld-linux-x86-64`. -Ici le binaire est *not stripped* : les différents *labels* ne sont pas -supprimés (ici pour NixOS). - -Il est aussi possible de récolter plus d'informations avec `readelf` notamment -la version de la *libc* utilisée. Ce genre d'information peut permettre de mener -une attaque. - -### les sections `.plt` et `.got` - -Ces différentes sections permette la résolution de symboles. `.plt` signifie -*Procedure Linkag Table* et `.got` *Global Offset Table*. On parle alors de -relocation. - -Pour la section `.plt`, toutes ses entrées sont initialisées pour pointr vers -l'editeur du lien et non l'adresse de la bonne fonction. C'est lors de premier -appel de la fonction en question que sont adresse sera résolue - elle st donc -effectuée au *runtime* - et mise à jour. On parle alors de *lazy symbols -binging* - -La section `.got` fait plus office d'annuaire référençant juste les adresss de -fonctions mais aussi de variables globales des bibliothèques). - -#### `.got` et `plt.got - -Ces deux sections sont utilisés pour les symboles ayant besoin d'être résolus -**au moment du chargement du binaire en mémoire**. - -#### `.plt` et `.got.plt` - -Ces deux sections se chargent de la résolution fainéante. - -### Segments et sections avec `realelf` - -#### Le segment `GNU_STACK` - -Il permet la configuration de la pile lorsque le binaire est chargé. Il sert par -exemple à la mise en place de protection (pile non exécutable par exemple). - -#### Le segment `GNU_RELRO` - -Il indique quelles régions de la mémoire doivent être marquées en lecture seule -une fois la résolution des symboles effectuée. Il existe deux type : - - * **full**: `.got` et `.got.plt` sont passés en lecture seule - * **partiel**: seule la `.got` est en lecture seule. - -*[ELF]: Executable and Linkable Format - -## Le format PE - -PE pour *Portable Execution* est le format de binaire utilisé par Microsoft -Windows. Comme pour Linux, un *loader* réalise l'analyse et le chargement du -binaire en mémoire. Dans ce format, la notion de segment n'existe pas, mais il -se compose de 3 entêtes : - - * un reliquat de l'ère MS DOS avec comme *magic number* `MZ`. cette section - affiche un message d'erreur du style *Ce programme ne n'exécute pas en mode - MSDOS* lors de son exécusion en mode DOS; - * une entête *PE* avec comme *magic number* `PE`; - * une entête optionnelle. - -Il se compose aussi: - - * une partie *data directories*; - * une table des sections (`text`, `data`, etc.); - * les sections en questions (avec leurs entêtes). - -### CFF explorer - -Ce programme disponible uniquement pour Windows permet d'analyser les fichiers -binaires (exécutable, bibliothèques, etc.). - -### Entête optionnelle - -Elle est quasiment tout le temps présente et permet notamment de définir le -point d'entrée (*entrypoint*), d'activer les protections comme l'ASLR ou autre -mécanismes de sécurité. - -### Entête *data directories* - -Elle contient la localisation et la taille de chaque `directory`. Ces -*directories* sont de plusieurs natures : - - * signatures cryptographiques; - * icônes; - * configurations; - * *export-table* : référençant les fonctions exportées par le binaire; - * *import-table* : référençant les DLL importées par le binaire, les fonctions - issues de ces DLL sont référencées dans l'*Imports Address Table*; - * *relocation table* : table référençant les relocations. - -Plusieurs *directories* peuvent appartenir à une section. - -### Entêtes de sections - -Elles contiennent les information relatives à leurs sections respectives : nom, -adresse virtuelle, taille, droit d'accès. diff --git a/content/secu_systeme/2_initiation_re/index.md b/content/secu_systeme/2_initiation_re/index.md deleted file mode 100644 index 192bf3d..0000000 --- a/content/secu_systeme/2_initiation_re/index.md +++ /dev/null @@ -1,329 +0,0 @@ ---- -title: "Sécurité système : initiation au reverse engeneering" -date: 2023-09-21 -tags: ["ingénieurie inverse", "assembleur"] -categories: ["Sécurité système", "Cours", "TD"] ---- - -Nous avons revu dans le cours précédents les bases du fonctionnement d'un -binaire de la compilation à son exécution. Dans cette partie nous allons -appréhender les bases de l'ingénierie inverse. À l'issue de celle-ci nous -devrions être en mesure de réaliser de petits *crackme*. - -L'étape de compilation est en quelque sorte destructrice : Il n'est plus -possible à partir du binaire compilé de retrouver le code source correspondant. -Mais il est tout de même possible de **désassembler** : on reconstitue un code -assembleur. - -Ainsi afin de faire du reverse engineering, il est nécessaire de **comprendre la -compilation**, de savoir de quoi se **compose un binaire** et comment **il est -exécuté**. - -Une compréhension de l'assembleur, des type de structures qu'il manipule est -primordiale. Il est aussi nécessaire de maîtriser les outils à notre -disposition, de savoir coder un minimum (en *C*, *Python*). - -## La gestion de la mémoire - -Les sections `.rodata`, `.bss` et `.data` contiennent des données mémoires. Deux -structures existent pour les manipuler : la pile et le tas. - -### La pile - -Elle manipule des données statiques. C'est une structure de type LIFO (*Last In -First Out) qui croit vers le bas : plus on descend plus les adresse augmentent. -Sa taille est alignées sur un *int32* ou *int64* en fonction de l'architecture -(32 ou 64 bits). - -*Deux "fonctions"* permettent de la manipuler : `push()` afin de placer un -élément -- la pile descend alors d'une case -- et `pop()` pour reprendre un -élément -- la pile remonte d'un élément. - -Elle se situe **dans l'espace mémoire d'un processus**, ainsi chaque processus a -sa pile. Elle a une structure linéaire; son accès est **rapide** (pas -d'allocation de mémoire à effectuer) mais la **taille des éléments que l'on peut -y stockée est limitée**. - -### Le tas - -Il manipule des données dynamiques représentées par une structure de données -hiérarchisée. Le tas est lui aussi positionné dans l'espace mémoire d'un -processus. - -Il n'est pas limité en taille (enfin presque pas...) mais nécessite de coûteuses -allocations mémoire qui le rend plus lent. Le développeur peut lui même allouer -de la mémoire sur le tas avec la présence de fonctions comme `malloc()` (et ne -pas oublier de les libérer avec `free()`). L'implémentation de ces mécanismes -mémoire dépendent de **l'allocateur**. - -## Initiation au reverse Engineering - -### L'assembleur - -C'est un langage de bas niveau mais encore compréhensible par un humain -(initié...). Il est dépendant de l'architecture, prenons par exemple le code *C* -suivant: - -```c -int sum (int a, int b ){ - return a +b; -} -``` - -Voici ce code en assembleur *x86_64* : - -```asm -sum(int, int): - push rbp - mov rbp, rsp - mov DWORD PTR [rbp-4], edi - mov DWORD PTR [rbp-8], esi - mov edx, DWORD PTR [rbp-4] - mov eax, DWORD PTR [rbp-8] - add eax, edx - pop rbp - ret -``` - -Et en assembleur *ARM64*: - -```asm -sum(int, int): - sub sp, sp, #16 - str w0, [sp, 12] - str w1, [sp, 8] - ldr w1, [sp, 12] - ldr w0, [sp, 8] - add w0, w1, w0 - add sp, sp, 16 - ret -``` - -On parle alors d'ISA pour *Instruction Set Architecture*, cela représente le jeu -d'instruction disponible. Nous y trouvons les opérations élémentaires : -addition, soustraction, multiplication, division, et / ou (exclusifs ou non) -etc. Ici mon manipule les registres et la mémoire directement. Une *ISA* ne -contient pas d'opérateur avancés comme les structures de contrôles que nous -pouvons trouver dans les langages de haut niveau (`while ...`, `if ... -else ...`, `for ...`). - -### L'assembleur x86 (32 et 64 bits) - -Tout comme pour le cours de sécurité logicielle, nous utiliserons principalement -l'assembleur *x86_32* pour ce cours (et quelques fois sa version 64). Mais par -contre nous utiliserons **la syntaxe *Intel*** majoritairement utilisée dans le -monde de l'ingénierie inverse. Cette syntaxe est plus simple : - - * les suffixes de mnémoniques pour n'existes pas en syntaxe Intel, ainsi - `movl`, `movw` ou encore `movb` deviennent **`mov`**; - * les préfixes sur les registres et immédiats disparaissent : `%eax`, `$1`, - `$0x0ff` deviennent **`eax`, `1` et `0x0ff`**; - * l'ordre des opérandes est inversé : ce n'est plus `source, destination` mais - **`destination, source`**. `movl $1, %eax` devient **`mov eax, 1`** - * les accès indirect à la mémoire sont aussi plus simple : `(%eax)` devient - `[eax]` et `3(%eax)` devient `[eax + 3]` voir le cours [accès à la mémoire de - sécurité logicielle]({{}}) - -Le vocablulaire reste le même que celui vu lors des cours [d'introduction de -sécurité logicielle]({{ref "secu_logicielle/1_introduction/index.md"}}) - -### L'assembleur x86 : les registres - -LEs registres sont de petits espace memoire directement intégrés au processeur. -Ce sont les espace mémoires les plus rapides disponible sur un ordinateur, mais -aussi les plus petits. Il sont dédiés entre autres au stockage de données. - -Certains de ces registres ont des **rôles bien déterminés** par exemples : - - * `eip` pour *extended instruction pointer* pointe vers la prochaine - instruction à exécuter[^eip], il porte aussi le nom de *Compteur Ordinal*. - **il ne peut être modifié** contrairement à tous les autres registres; - * `ebp` pour `extended base pointeur` pointe vers le bas de la pile; - * `esp` pour `extented stack pointer` pointe lui vers le haut de la pile. - -Tous ces registres sont noté *extended* dans leurs versions **32 bits** - -Certains autres ont des spécificité, mais il est tout à fait possible pour le -programmeur de les utiliser à sa guise : - - * `ecx` par exemple est utilisé comme compteur dans certaines instructions de - repétition(typiquement les boucles); - * `esi` et `edi` utilisés comme source (*extended source index*) et destination - (*extended destination index*) pour certaines instructions de copie. - -Les registres peuvent être découpés en sous registres : - -> `a` 8 bits -> `ax` 16 bits -> `eax` 32 bits -> `rax` 64 bits - -Il est d'ailleurs possible de découper `ax` en deux registes de 8bits : `al` -(bits 0 à 7) et `ah` (bits 8 à 15). Ces découpes permettent certaines -optimisations comme par exemple le **stockage de deux entiers 16 bits** dans un -registre 32bits ou encore pour les instruction se basant sur **l'interprétation -du contenu** des registres. - -Il existe aussi des registes d'états, mais nous les avons vu [en sécurité -logicielle]({{}}) -DAs le cadre de ce cours, le *Zero Flag*, *Sign Flag* et *Carry flag* sont -importants. Le carry flag correspond à la présence d'une retenue [voir sur -Wikipedia][carry_flag]. - -Pour rappel, voici un exemple d'utilisation du *Zero flag* : - -```asm - -start: - mov eax, 1 - dec eax ; décrémente eax - - ; comme le résultat de la précédente instruction est 0 - ; alors notre programme va forcément brancher... - jz hell - -; [...] - -hell: -``` - -[^eip]: en x86, dans certaine ISA, il pointe l'instruction en cours). - -[carry_flag]:https://fr.wikipedia.org/wiki/Indicateur_de_retenue - -## Pratique - -### IDA Free - -C'est un outils gratuit et multi plate-forme d'analyse de binaire. Il existe -aussi plusieurs versions payantes (pro, home, corporate ...). La version free -comporte un desassembleur, un décompilateur "cloud" pour x86_64 seulement. Il -permet la manipulation de binaire au formats différents (ELF, PE Mach-O). Il -s'interface aussi avec des débogueras notamment GDB. - -C'est un outil puissant mais difficile à prendre en main. - -### Étudions `ls` (binaire ELF) - -Nous ouvrons notre binaire ls modifié avec `lift` lors du précédent TD pour -l'étudier avec *IDA Free*. - -#### question b - -`strcpy` se trouve dans la section `.dynsym`, section des symboles résolus -dynamiquement lors de son premier appel. - -#### question c - -Dans IDA, le code couleur utilisé entre autres dans la section `.dynsym` -correspond aux éléments fournis à l'extérieur de notre binaire, comme dans les -bibliothèques partagées. - -#### question d - -Les chiffres hexadécimaux dans ne nom de la fonction `sub_xxxxxx` correspondent -aus décalage (*offset*) de celle-ci par rapport à l'adresse de chargement de -notre binaire. - -### Les raccourcis clavier - -Ils sont une part importante de l'utilisation d'IDA, en voici quelques-uns: - -| raccourcis | fonction | commentaires | -|------------|----------|--------------| -| crtl + w | sauvegarder la base de données | très utile cat IDA est instable -| ctrl + shitf + w | effectuer un snapshot de la base de données | CF au dessus -| ctrl + z | annuler | | -| n | renommer un objet (variable, fonction, etc.) | hexrays | -| y | modifier le type d'un objet (variable, fonction, etc.) | asm / hexrays | -| alt + a | interpréter l'objet comme une chaine de caractères | | -| h | interpréter la selection comme un décimal / hexadécimal | asm / hexrays | -| r | interpréter la selection comme un caractère | asm / hexrays | -| c | interpréter la portion comme du code asm | asm | -| d | interpréter la portion comme data | asm | -| u | retirer l'interprétation | asm | -| : ou ;|ajouter un commentaire au niveau de l'instruction | visualiseur | -| insert | ajouter un commentaire avant l'instruction | asm / hexrays | -| espace | cycle entre la vue graph et linéaire | hexrays | -| F5 | décompiler (si possible) | | -| entrée ou double-clic | su un symbole -> aller où pointe le symbole | asm / hexrays | -| echap | revenir à la position précédente - en arrière | asm / hexrays | -| ctrl + entrée | revenir à la position précédente - en avant | asm / hexrays | -| x | afficher les cross références *xref* d'un objet | asm / hexrays | -| alt + t | recherche de texte | | -| alt + b | recherche de motif binaire | | -| alt + i | rechetche un *immédiat* | | -| tab | passer de la vue *asm* à la vue hexrays | | -| ctrl + e | afficher les points d'entrées du binaire | | -| maj + F1 | afficher la fenêtre des types locaux | | -| maj + F12 | afficher la fenêtre des chaîne de caractères | | - -Il faut voir IDA comme un bloc note accompagnant le travail d'ingénierie inverse -Il faut **absolument** documenter au fur et à mesure des investigations et faire -autant d'instantanés que possible (stabilité...). - -### Analyse du binaire `mysecrets` - -#### Question 1 - -Dans IDA, lorsque nous faisons `ctrl+e` nous atterrissons dans la liste des points -d'entrées du binaire chargé. Dans le cas de `mysecret`, nous atterrissons dans -la fonction `main:`. Ce qui est normal pour un binaire ELF. - -#### Question 2 - -Pou trouver la section `.rodata`, il suffit de trouver la liste des segments -(mais pas au sens ELF...) avec le raccourci clavier `ctrl+s`. Cette section -contient les données en lecture seule, ici toutes les *strings* de notre -binaire. - -#### Question 3-a - -Dasn le code assembleur, il semble y avoir 3 arguments. IDA nous les donne en -commentaire : - -```asm -ebp + arg0 -ebp + arg4 -ebp + arg8 -``` - -#### Question 3-b - -La convention d'appel utilisées ici est `__cdecl` (pour *C declaration*), c'est -la convention utilisés par le langage C et C++ -- la convention d'appel dépend -aussi de l'ABI système, du compilateur ). Ici les arguments sont placés sur la -pile par la fonction appelante (*caller*). Il sont placé dans l'ordre inverse, -prenons comme exemple le programme *C* suivant : - -```c -int add_3 ( int a, int b, int c){ - // [...] -} -main() { - add_3 (1, 2, 3); -} -``` - -Ce qui donnera en assembleur : - -```asm - -main: - push ebp ; backup current base pointer - mov ebp, esp ; get the new base pointer - - push 3 - push 2 - push 1 - call add_3 - ; [...] -``` - -#### Question 3-c - -Les instructions `push epb` et `mov epb, esp` permettent de mettre en place le -*base pointer* après l'avoir sauvegardé pour assurer sa remise en place lors du -retour de notre fonction `secrets`. - -#### Question 3-d - -La décente de `0x18` dans la pile permet à la fonction apellée de mettre en -place un espace pour les variables locales.