Dance In Heap(二):一些堆利用的方法(上)
0×00 前面的话
在前面的文章里我们稍微有点啰嗦的讲解了堆中的一些细节,包括malloc、free的详细过程,以及一些检查保护机制,那在这篇文章里,我们就开始结合这些机制,以64位为例来看一看如何对堆进行攻击。本篇文章稍微讲解了一下UAF漏洞,然后根据源码分析了一下哪些地方使用了 unlink 宏,将unlink漏洞与其他的 chunk 释放操作做了一下区分并分析了unlink漏洞,最后讲解了另外一种利用 chunk 从 bin 中释放但不同于unlink的漏洞 unsortedbin attack。
本篇文章目录
0x01 Use After Free
0x02 Unlink
0x03 unsortedbin attack
0x04 小结
0×01 Use After Free
要学习堆中的漏洞,最基础不过的就是这个 UAF 了,UAF 漏洞原理很简单,就是在 free 掉 chunk 后,指向该 chunk 的指针还能正常使用
#include<stdio.h>
#include<stdlib.h>
struct shell {
void (*getshell)();
};
struct data {
int data;
};
void test_getshell(){
printf("I get the shell\n");
}
int main () {
struct shell *p;
p = (struct shell*)malloc(sizeof(struct shell));
p->getshell = test_getshell;
free(p);
struct data *q;
q = (struct data*)malloc(sizeof(struct data));
q->data = 1234;
p->getshell();
return 0;
}
编译运行一下
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00000000000004d2 in ?? ()
我们可以看到 p 指向的函数地址被我们用1234给替换掉了,这就意味着我们能够利用这样一个漏洞控制 rip 寄存器,执行指令。
0×02 unlink
unlink漏洞想必大家都不陌生,在前面我们提到过,系统通过 unlink 宏将 free chunk 从链表中取出,但是我在这里强调一下,并非所有从链表中取出 chunk 的操作都利用到了 unlink 宏,要知道,我们在 malloc 时,也多次将 chunk 从 bin 中取出,我想结合部分源码(只截取了取出部分的代码)来强调一下 unlink 的使用状况。
在 malloc 操作中,我们多次进行了 bin 之间的转移,具体如下
从 fastbin 中取出 chunk
mfastbinptr* fb = &fastbin (av, idx);
victim = *fb;
*fb = victim->fd;
从 unsortedbin 中取出 chunk
victim = unsorted_chunks(av)->bk
bck = victim->bk;
unsorted_chunks(av)->bk = bck;
bck->fd = unsorted_chunks(av);
从 unsortedbin 向 smallbin 转移 chunk
if (in_smallbin_range(size)) {
victim_index = smallbin_index(size);
bck = bin_at(av, victim_index);
fwd = bck->fd;
从 unsortedbin 向 largebin 转移 chunk
mark_bin(av, victim_index);
victim->bk = bck;
victim->fd = fwd;
fwd->bk = victim;
bck->fd = victim;
从 smallbin 中取出 chunk
idx = smallbin_index(nb);
bin = bin_at(av,idx);
victim = last(bin);
bck = victim->bk;
bin->bk = bck;
bck->fd = bin;
从 largebin 中取出 chunk
unlink(victim, bck, fwd);
合并 fastbin 中 chunk 并加入到 unsortedbin 中(单向链表,bk指针需要获取)
prevsize = p->prev_size;
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));115
unlink(p, bck, fwd);
......
size += nextsize;
unlink(nextchunk, bck, fwd);
我们发现不仅仅在 free 时进行向前向后合并时使用 unlink 宏,在 malloc 时也会有零星的 unlink 使用,而且一定要注意,上面的除了6、7外,在进行取出 chunk 操作时,并没有进行 unlink,所以在对这一部分进行漏洞利用时,不需要考虑 unlink 的检查。
现在言归正传,来看看 unlink 漏洞。
#define unlink(P, BK, FD) {
FD = P->fd;
BK = P->bk;
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
malloc_printerr (check_action, "corrupted double-linked list", P);
else {
FD->bk = BK;
BK->fd = FD;
上面所示是 unlink 宏的主要实现,我们现在设想申请两个chunk,并利用第一个chunk溢出到第二个chunk的size位,将第一个chunk的 inuse 位改写为 free状态,这时候我们再free第二个chunk,此时系统通过第二个chunk的size检查第一个chunk,发现他是free状态,那么这时候就会使用unlink将第一块chunk从bin中释放出来并与第二块合并
a = malloc(0x20)
b = malloc(0x20) // b.size = 0x20 + chunk_header | inuse(0x01) == 0x31
a[0x20+4] = 0x30 // 覆盖 inuse 位
free(b) // 检查inuse位,发现 a 为 free,执行 unlink,合并两个 chunk
这时候其实a并没有在 bin 中,但是如果我们对 a 的前两个元素(即”fd”、”bk”)进行构造,那么就可以造成任意地址写入。
首先我们需要绕过检查,我们进行一个小小的计算
P->bk->fd == P // [P+0x18]+0x10 == P [P+0x18] == P-0x10
P->fd->bk == P // [P+0x10]+0x18 == P [P+0x10] == P-0x18
发现我们只需要在 b 的”fd”指针处放入 b-0×18,在”bk”指针处放入 b-0×10,即可绕过检查
执行完 unlink宏后,我们的b变成了这样
FD->bk = BK *P = P - 0x10(0x8)
BK->fd = FD *P = P - 0x18(0xc) // 这一步覆盖上一步
也就是说 现在 b 处存放着 b-0×18 的地址,这时候我们再向 b 写入数据也就是向 b-0×18 处写入数据了
--------|-------|
b | |----
--------|-------| |
····· | | |
--------|-------| |
b-0x18 | |<---
--------|-------|
这时候我们通过两次写入来造成任意地址写入,第一次写入0×18个字节,最后几位放入要写入的地址
--------|-------| |-------|
b |address|----> | 写入 |
--------|-------| |-------|
····· | |
--------|-------|
b-0x18 | AAAA |
--------|-------|
我们再次写入时,就是修改该地址处的数据了,比如修改got表什么的
0×03 unsortedbin attack
对 unsortedbin 的攻击主要利用从 unsortedbin 中取出 chunk 的操作来进行向任意位置写入一个不可控的指针,注意这里,从unsortedbin链表中取出chunk并不是使用unlink宏,所以不需要绕过 unlink 检查。首先我们需要创建两个 chunk 来避免 free 第一个 chunk 时将该 chunk 并入 top chunk,并且第一个 chunk 要足够大,确保其能进入到 unsortedbin中
p = malloc(0x400)
malloc(0x200)
然后将 p free掉,此时 p 进入到 unsortedbin中,然后改写其的 bk 指针,并malloc
free(p)
p[1] = 0xdeadbeef-0x10 // 任意地址 - 0x10
malloc(0x400)
我们看一下从 unsortedbin 中取出 chunk 的操作
victim = unsorted_chunks(av)->bk // victim为free掉的p
bck = victim->bk; // bck 为 任意地址 -0x10
unsorted_chunks(av)->bk = bck; // 调整链表
bck->fd = unsorted_chunks(av); // 任意地址 -0x10 + 0x10 = unsortedbin
这个漏洞自由度较小,不过可以用来修改一些阈值,例如更改libc中的max_fast,从而使得任意分配都使用fastbin来实现,为其他漏洞提供方案。
0×04 小结
在这次的文章中,我们简单的讲解了一下UAF漏洞,然后主要对从 bin 中释放 chunk 时的操作进行了漏洞利用,包括经典的 unlink,当然我们也结合源码分析了一下它的使用状况,以及非unlink式的chunk释放,unsortedbin attack。
Dance In Heap(二):一些堆利用的方法(上)的更多相关文章
- Binary Heap(二叉堆) - 堆排序
这篇的主题主要是Heapsort(堆排序),下一篇ADT数据结构随笔再谈谈 - 优先队列(堆). 首先,我们先来了解一点与堆相关的东西.堆可以实现优先队列(Priority Queue),看到队列,我 ...
- 第十章 优先级队列 (b2)完全二叉堆:插入与上滤
- 二叉堆(一)之 图文解析 和 C语言的实现
概要 本章介绍二叉堆,二叉堆就是通常我们所说的数据结构中"堆"中的一种.和以往一样,本文会先对二叉堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本 ...
- 二项堆(一)之 图文解析 和 C语言的实现
概要 本章介绍二项堆,它和之前所讲的堆(二叉堆.左倾堆.斜堆)一样,也是用于实现优先队列的.和以往一样,本文会先对二项堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本 ...
- 打印二叉堆(Java实现)
打印二叉堆:利用层级关系 我这里是先将堆排序,然后在sort里执行了打印堆的方法printAsTree() public class MaxHeap<T extends Comparable&l ...
- 二叉堆(二)之 C++的实现
概要 上一章介绍了堆和二叉堆的基本概念,并通过C语言实现了二叉堆.本章是二叉堆的C++实现. 目录1. 二叉堆的介绍2. 二叉堆的图文解析3. 二叉堆的C++实现(完整源码)4. 二叉堆的C++测试程 ...
- 二叉堆的实现(数组)——c++
二叉堆的介绍 二叉堆是完全二元树或者是近似完全二元树,按照数据的排列方式可以分为两种:最大堆和最小堆.最大堆:父结点的键值总是大于或等于任何一个子节点的键值:最小堆:父结点的键值总是小于或等于任何一个 ...
- 【BZOJ 1129】[POI2008]Per 二叉堆
这个东西读完题之后,就能知道我们要逐位计算贡献.推一下式子,会发现,这一位的贡献,是当前剩余的数字形成的序列的总数,乘上所剩数字中小于s上这一位的数的个数与所剩数字的总数的比.所以我们维护“当前剩余的 ...
- 数据结构 之 二叉堆(Heap)
注:本节主要讨论最大堆(最小堆同理). 一.堆的概念 堆,又称二叉堆.同二叉查找树一样,堆也有两个性质,即结构性和堆序性. 1.结构性质: 堆是一棵被完全填满的二叉树,有可能的 ...
随机推荐
- HDU 3315 KM My Brute
参考题解 二分图的最优匹配.图很容易建立.再处理相似度的时候.把每个权值扩大100倍.然后再对i==j时 特殊标记.使他们的权值再++1.后面选择的时候就很容易挑出.按原匹配 匹配的个数. 100*( ...
- HDU 5371 Manacher Hotaru's problem
求出一个连续子序列,这个子序列由三部分ABC构成,其中AB是回文串,A和C相同,也就是BC也是回文串. 求这样一个最长的子序列. Manacher算法是在所有两个相邻数字之间插入一个特殊的数字,比如- ...
- LayoutInflater的用法
Instantiates a layout XML file into its corresponding View objects. It is never used directly. Inste ...
- luogu3369 【模板】普通平衡树(Treap/SBT) treap splay
treap做法,参考hzwer的博客 #include <iostream> #include <cstdlib> #include <cstdio> using ...
- HTML5之中国象棋,附带源码!
好久没写随笔了,好怀恋2013年的日子,因为现在不能回到过去了! 再见了 感谢你为我做的一切! 进入正题:HTML5之中国象棋 很小就会下象棋了, 这是象棋的测试地址:点击我吧 然后点击里面的象 ...
- matlab 画图进阶
matlab 画图进阶 applications of matlab in engineering 图表类型的选择 first:advanced 2d plots special plots logl ...
- .net SignalR 聊天室
代码地址:https://gitee.com/srnsrn/netSignalr.git 运行项目打开多个页面 私密聊天
- iOS-----5分钟学会枚举的正确使用姿势-Enumeration宏
前言 Enum,枚举,相信大部分编程语言都有对应的枚举类型,功能可能有多有少,但是枚举最核心的功能是 “规范的定义代码中的状态.状态码.选项”. 状态.状态码.选项 什么是状态:同时只能出现一个值(状 ...
- 【bzoj2561】最小生成树 网络流最小割
题目描述 给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最 ...
- 【Luogu】P3950部落冲突(树链剖分)
题目链接 状态奇差无比,sbt都能错一遍. 不动笔光想没有想到怎么做,画图之后发现一个很明显的性质…… 那就是两个开战的部落,其中一个是另一个的父亲. 所以在儿子那里加个权值.查询的时候树链剖分查询链 ...