Pour rappel, le but de ce guide n’est pas de vous donner la réponse, mais plutôt de vous y amener par la compréhension. Ainsi, il ne contient pas de flag.
Table des Matières
Narnia1
Si mes explications ont été suffisamment claires et précises et que vous avez été persévérant, vous avez normalement obtenu le mot de passe du compte narnia1.
Nous pouvons ainsi créer une nouvelle session SSH avec cet utilisateur.
Découverte
De la même manière que narnia0, nous avons accès au code source de l’exécutable narnia1 :
#include
int main(){
int (*ret)();
if(getenv("EGG")==NULL){
printf("Give me something to execute at the env-variable EGG\\n");
exit(1);
}
printf("Trying to execute EGG!\\n");
ret = getenv("EGG");
ret();
return 0;
}
Pour faire simple, ce script lit la valeur de la variable d’environnement “EGG”. Cette valeur est vide par défaut. Nous pouvons lui configurer une valeur en tapant la commande :
export EGG=test
Seulement, cela produit un Segmentation Fault:
Cela signifie que le processeur ne comprend pas une instruction et que par conséquent il ne peut pas l’exécuter. Il s’attend en effet à une valeur de EGG soit exécutable…
Après différentes tentatives, j’ai fait quelques recherches sur comment je pourrais passer une valeur compréhensible par l’ordinateur.
Et c’est à ce moment-là que j’ai découvert les shellcodes.
Qu'est-ce qu'un shellcode ?
Un shellcode est un ensemble de caractère qui est interprétable par la machine.
Ce shellcode permet par exemple d’afficher Hello World.
Mais comment fabrique-t-on un shellcode ?! Me diriez-vous.
Ce n’est pas aussi compliqué que cela en a l’air.
Réflexion
La première étape de la “fabrication” d’un shellcode est d’écrire le programme en assembleur.
Par exemple, on souhaite afficher “Hello World” :
section .text
global _start
_start:
jmp short ender ; on saute à ender
starter:
xor rax, rax ;on nettoie les registres pour être sûr qu'ils soient vides
xor rbx, rbx
xor rdx, rdx
xor rcx, rcx
mov al, 4 ;on appelle la fonction write (syscall write)
mov bl, 1 ;on veut écrire sur la sortie standard (stdout = 1)
pop ecx ;on récupère l'adresse mémoire de notre chaine sur la pile
mov dl, 11 ;longueur de la chaine de caractère
int 0x80 ;appel système pour executer la première partie du code
xor rax, rax ;on remet rax à 0
mov al, 1 ;appel système pour sortir (exit)
xor rbx,rbx ; on remet à 0 le base pointer parce que c'est plus propre
int 0x80 ; appel système pour sortir
ender:
call starter ;on appelle starter et on met l'adresse de la chaine sur la pile
db "hello world"
On compile le code avec la commande :
nasm -f elf64 hello.s
On obtient un fichier en .o. Il nous suffit de le transformer en executable linux avec la commande :
ld -s -o hello hello.o
Cette commande permet de lier le code objet avec les librairies de l’OS et de créer un fichier ELF. On obtient ainsi un fichier exécutable, qui nous affiche bien “hello world” si nous l’exécutons.
En tapant la commande :
objdump -d hello
On obtient la fonction désassemblée, avec les adresses mémoires, en hexadécimal de notre code :
Encadré en rouge, vous pouvez voir notre code, en hexadécimal, dans un langage compréhensible par la machine. Ce sont ces caractères qui vont composer notre shellcode.
Voici ce que donne notre shellcode dans cet exemple :
Attention : votre shellcode ne DOIT PAS contenir de \x00, sinon il ne fonctionnera pas.
En effet, ce caractère correspond à la fin d’une chaine de caractère. La suite du shellcode ne sera ainsi pas interprété.
Pour résoudre ce problème, il vous faudra utiliser les bonnes tailles de registres.
Une fois votre shellcode créé, il ne vous reste plus qu’à l’injecter dans la variable d’environnement “EGG”.
⚠️ Attention : Votre shellcode doit pouvoir être interprété comme du contenu exécutable. Vous ne pouvez pas simplement attribuer à EGG la valeur du shellcode.
Pour cela nous allons nous aider de python !
Grâce à cette commande, nous allons pouvoir exécuter le shellcode :
Vous avez maintenant compris le fonctionnement d’un shellcode ainsi que sa construction. Vous avez donc toutes les cartes en main pour résoudre ce challenge. Il ne vous manque plus qu’à fabriquer un shellcode fonctionnel pour ce cas.
Recent Comments