Beginner Binary Exploitation Lab

Posted by:

|

On:

|

I completed this project as a part of the Georgia Tech Intro to Information Security course. This project covers foundational concepts for binary exploitation and assembly language. Due to Georgia Tech’s academic integrity policy, I am unable to share exact answers, but I will go over my process for completing the project.

Part 1 – Basic Overflow 1

I was given four files, an e.py file containing pwntools skeleton code to develop and send a payload, the compiled flag c executable, a readable flag.c file with the c program code, and a user.txt file with my student ID to calculate the flag value for submission.

First, I examine flag.c to see what the code is doing and gain ideas for exploitation.

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <unistd.h>
#include "../../shared/kernels_lib.c"


void unsafe() {
  u_int64_t make_me_not_zero = 0;
  int buffer[10];
  printf("hey man can i borrow a string i promise ill pay you back\n");
  //read(0,buffer,200);
  scanf("%s",buffer);
  if (make_me_not_zero != 0) {
          printf("got the flag\n");
          call_me();
  }
}

int main(){
  unsafe();
  return 0;
}

From the file, I see the buffer size is 10, and the goal is to change the “make_me_not_zero” value. Upon visually looking at this code, I think I could try sending a value greater than length 10 to write out of bounds for the scanf function and hopefully overwrite the make_me_not_zero variable.

I begin the testing process using the e.py file and pwntools. I began testing with payloads of length greater than 10 until I found one long enough to overflow into make_me_not_zero. The payload was sent using pwntools p.sendline and p.recvline.

#!/usr/bin/env python3
import sys
import os

from pwn import *

context.update(arch='x86_64', os='linux')
    
#initialize payload
payload = '1111111111111111111111111111111111111111111111111111'
p.sendline(payload)
p.interactive()

Sending a payload long enough through the pwntools exploit program results in an overflow and reveals the flag. This was a very basic buffer overflow problem but demonstrates the concept behind buffer overflows overwriting data when input is left unchecked.

Part 2 – Basic Overflow 2

Again, I was given four files in similar format to part 1. I utilized the pwntools skeleton code e.py, a compiled flag binary, a readable flag.c program, and the user.txt file when calculating the flag hash. I began by reading the flag.c file and inspecting it for vulnerabilities.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "../../shared/kernels_lib.c"

//FOLLOW ALONG WITH THE PWNTOOLS TRAINING VIDEO, IT GOES OVER AN IDENTICAL C>

int main(int argc, char* argv[]){
  int read_ret;
  char buffer[123];
  printf("Feed Me A Stray String:\n");
  read_ret = read(0, buffer, 1000);
  return 0;

}

//FIND THIS FUNCTION CALL IN OBJDUMP
void can_you_reach_me() {
  call_me();
}

In the code I see the buffer is size 123 and that the program uses the read() call from user input. The program gives hints in the comments to use objdump to analyze the binary and find the address of call_me(). The objective is to overflow the buffer and return the program to the call_me() address.

I used the command objdump -D flag > flag.asm to create a file with the assembly code to find the address of call_me(). I used vim to search through the assembly file to find the function “can_you_reach_me” and the associated address using the shortcut / to search for the string. The associated address appears next to the <call_me> function and is 0x401a9e

Next, we need to go through the debugger to see where our program is returning and how we can break it. In this example we use pwntools debugger dbg. We start by initializing a cyclic payload in pwntools of an arbitrary length – I chose 264 bytes to trigger a segmentation fault in the debugger. This will send a repetitive 4 byte payload of alphabetic characters in the form aaaabaaacaaadaaaeaaa….etc. We will want to search for this string in its hexadecimal form in the debugger after the segmentation fault occurs.

Here the cyclic function was successful in overwriting data from the debugger in the bottom of this image where the return address was overwritten and reads 0x626161…. Next I used cyclic_find() to find the exact number of bytes before this overwrite occurs so that I can add the desired return address here. Take note of the last 4 bytes 0x6261616b and search for this using cyclic_find(). I automate the sending of this payload by sending the exact number of bytes until the address is found as the payload using this payload = cyclic( cyclic_find( 0x6261616a ) ) Append the return address of the call_me() function found earlier so the program returns to the desired location. This is done with payload += p64( 0x401a9e )

Running the python pwntools exploit code will retrieve the flag.

Posted by

in