0.UAF
0-1.What’s UAF?
UAF(Use After Free),即释放后利用。通常情况下,一块内存被释放后,用户不应访问到这块被释放的内存区域。但如果用户能通过一些办法访问到这块被free的内存,则这种情况称之为UAF。
而我们知道,当一块chunk被free后,其user_data区会存放一些指针,如果我们能修改这些指针,那么就有可能达到劫持控制流的目的。
0-2.Cause
达成UAF一般有三种情况:堆溢出、指针悬挂、overlap。
堆溢出和栈溢出差别不大。
指针悬挂(也称野指针)是指若堆指针在释放后未被置空,当下次访问该指针时,依然能够访问到原指针所指向的堆内容,就会形成漏洞。
overlap,一般是double free漏洞。这种漏洞是UAF中特殊的一种,可以通过一些方式转化为基本的堆问题。通常结合指针悬挂使用。
0-3.How2Use
倘若我们有UAF,那么我们就可以利用UAF来修改fd指针为我们的target。当再次分配内存时,target就会被分配给用户。
而如果这个target能够被分配给我们用户,那么我们就能够实行任意内存地址访问和任意内存地址写。
而有了任意内存地址写后,就可以修改一些内存地址,比如got,hook指针,栈等等,实现控制执行流,进而getshell。
在2.23版本的libc中,这种实现相对简单;但2.26的版本后加入了如tcache等新机制,这种方法的实现变得相对困难。
1.fastbin及其相关检查机制
1-1.About
fastbin是一种单链表结构的bins,遵循LIFO,用于管理fastbin free chunk。
总共有十个链表,从0x20开始以0x10递增,最大为0x80。每个链表中fastbin的size是一样的。
大小属于fastbin的chunk被free掉时,不会改变next chunk的prev_inuse位,也就是说不会被合并。
1-2.Check
- 分配时,会检查chunk头部size字段,比如分配一个大小为0x70的chunk,会检查分配的chunk的size字段,如果size符合0x70-0x7f,则可以分配;若不是则程序异常退出。
- 释放时,会检查fastbin的链表头部指针是否和当前free的地址相同,若相同则异常退出。(防止连续释放同一chunk,这个机制可以利用double free漏洞绕过。)
2.fastbin attak
2-1.利用堆溢出漏洞
这种方式直接覆盖fd指针为target的地址即可,与栈溢出基本类似,不过多阐述。2-2.直接利用UAF
如果能够直接利用UAF,则可以直接修改fd指针。
但要注意的是,想要分配的目标地址附近一定要有个头部size字段。
通常来说,在libc中函数的地址的指针都是形如0x7fxxxxxxxx,如果把偏移改一下,就会得到一个0x7f。由于chunk是0x10对齐的,所以0x7f会被当做0x70处理。
通常来说,修改的地方是__malloc_hook或者got表或者栈。
2-3.利用指针悬挂和double free漏洞
倘若没有直接的UAF,但是有指针悬挂,试想,如果不考虑检查机制,free掉一个chunk两次,这样他的fd指针就指向了自己,然后申请他,改掉其fd指针,再次申请后,fastbin中就有了target。
1 | fastbin->A |
如果考虑检查机制,则需利用double free漏洞来绕过,及在两次free A中加一个无关紧要的free B。
1 | fastbin->A |