From d4d633a1bc5d030d045213daa7e2b50605474b85 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Tue, 10 Oct 2023 22:18:14 +0200 Subject: [PATCH] Continue reverse engineering notes --- content/secu_systeme/2_initiation_re/index.md | 155 ++++++++++++++++-- 1 file changed, 144 insertions(+), 11 deletions(-) diff --git a/content/secu_systeme/2_initiation_re/index.md b/content/secu_systeme/2_initiation_re/index.md index 192bf3d..d095950 100644 --- a/content/secu_systeme/2_initiation_re/index.md +++ b/content/secu_systeme/2_initiation_re/index.md @@ -124,12 +124,12 @@ monde de l'ingénierie inverse. Cette syntaxe est plus simple : `[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 +Le vocabulaire 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. +Les registres sont de petits espace mémoire 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. @@ -147,7 +147,7 @@ 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); + répétition (typiquement les boucles); * `esi` et `edi` utilisés comme source (*extended source index*) et destination (*extended destination index*) pour certaines instructions de copie. @@ -155,15 +155,15 @@ 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` +Il est d'ailleurs possible de découper `ax` en deux registres 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é +Il existe aussi des registres 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 +Dans 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]. @@ -194,7 +194,7 @@ hell: 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 +comporte un désassembler, 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. @@ -276,7 +276,7 @@ binaire. #### Question 3-a -Dasn le code assembleur, il semble y avoir 3 arguments. IDA nous les donne en +Dans le code assembleur, il semble y avoir 3 arguments. IDA nous les donne en commentaire : ```asm @@ -305,7 +305,6 @@ main() { Ce qui donnera en assembleur : ```asm - main: push ebp ; backup current base pointer mov ebp, esp ; get the new base pointer @@ -325,5 +324,139 @@ 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. +La décente de `0x18` dans la pile permet à la fonction appelée de mettre en +place un espace pour les variables locales. + +## Les conventions d'appel + +Nous avons vu dans le cas pratique (question 3-b) la convention d'appel +`__cdecl`. Une convention d'appel définie les règles d'appel d'une fonction +dont : + + * Comment sont transmis les paramètres à la *fonction appelée*; + * L'ordre dans lesquels ces paramètres sont passés; + * Quels registres doivent être préservés par la *fonction appelantes*; + * Comment la pile est nettoyée lors du retour à la *fonction appelante*. + +Une convention d'appels peut dépendre de l'architecture, du système +d'exploitation, du compilateur, du langage (`__cdecd` est issue du *C*). Il +existe aussi : + + * `stdcall` : variation de la convention `pascal`, utilisée par *Open Watcom + C++* et l'API *Win32*. Comme pour `cdecl` les éléments sont poussés de droite + à gauche et les registres `ebx`, `ecx` et `edx` dont préservés pour + l'appelant; + * `Microsoft fastcall` : les deux premiers arguments ( à partir de la gauche) + sont passés par les registres `ecx` et `edx` (s'ils rentrent) puis les autres + sont poussés sur la pile de droite à gauche. + +### Deux convention principales pour x86_64 + +Pour ce qui concerne ce cours, nous parlerons de deux conventions principalement +utilisées. + +#### Convention de Microsoft + +Les arguments sont passés -- dans l'ordre -- par les registres `rcx`, `rdx`, +`r8`, `r9` [^microsoft] et le reste sur *la pile* de droite à gauche. Un espace +mémoire de 32 octets est réservés sur la pile avec les arguments par la fonction +appelante. Le retour se fait dans `rax` pour les entiers jusqu'à +64bits[^retour_ms] mais en vas de retour plus importants, alors `rax` contient +un pointeur. + +[^microsoft]: pour les entiers, struct et pointeurs. Pour les flottants sur les + registres `xmm0` à `xmm3`. +[^retour_ms]: et `xmms0` pour un flottant. + +#### Convention Unix (SYS-V) + +Les arguments sont passés par `rdi`, `rsi`, `rdx`, `rcx`, `r8` et `r9`[^sysv] et +le reste sur la pile. La valeur de retour est positionnée dans `rax` pour les +valeurs jusqu'à 64 bits et `rax:rdx` entre 64 et 128 bits[^retour_sysv]. + +[^sysv]: de `xmm0` à `xmm7` pour les flottants +[^retour_sysv] `xmm0` et `xmm1` pour les flottants + +### Pratique + +Afin de découvrir ce que fait le programme `secrets2` il faut commencer par +l'exécuter si c'est possible. Ensuite nous passons dans IDA. + +Un petit tours par les chaînes de caractères via le raccourci *shift + F12* +permet d'en apprendre plus. Nous pouvons ainsi voir le message d'aide avec ce +qui semble être l'utilisation de la commande. Nous voyons aussi ce qui semble +être un message qui **invite l'utilisateur à la saisie**. + +En affichant les *cross-references* dans IDA, il est alors possible de voir ou +est utilisé cette chaîne et de trouver le registre ou est stocké cette saisie +(enfin l'adresse mémoire contenant la saisie). En retraçant sont utilisation, +nous pouvons voir qu'elle est envoyée dans la fonction `secret`. + +Il est primordial d;annoter le code assembleur dans IDA mais aussi de renommer +les variables afin de rendre le code le plus lisible possible. Ainsi nous +pouvons renommer la variable `s` en `buffer`. + +Une fois toutes ces étapes réalisées nous pouvons en déduire que la fonction +échappe les caractères qui pourraient être interprétés d'une chaîne résultant +d'une commande `ls`. + +## Shellcode + +Nous en avons déjà vu lors du cours de sécurité logicielle notamment [le TD +5]({{