CVE 2013-2094 exploit 实验笔记
这些是本人在学校的计算机系统课上做的一个exploit的复现实验,由于本人第一次接触计算机安全相关的知识,以下内容仅为本人的实验内容和个人理解。如有错误和不足之处敬请谅解。作者Joe Damato 对此漏洞已经有比较详细的讲解了。本人对于其中不易理解的部分有更进一步的解释。
1. links
2.6.38 内核下载:
Series 2.6.38 : Linux (launchpad.net)
ubuntu 10.04 64-bit:
Index of /releases/10.04.0 (ubuntu.com)
exploit代码:cve-2013-2094/rewritten_semtex.c at master · realtalk/cve-2013-2094 · GitHub
Joe Damato 的 cve介绍原文: A closer look at a recent privilege escalation bug in Linux (CVE-2013-2094) at time to bleed by Joe Damato
看内核源码的网站:kernel 2.6.38
2. 实验流程
2.1 安装ubuntu64 虚拟机
版本:Ubuntu 10.04 64-bit
2.2 编译 2.6.38 内核
参考的教程(蛮详细的):
https://blog.csdn.net/qq_34247099/article/details/50949720
要注意检测内核是否安装成功。
2.3 开始exploitation
将exploit代码解压到一个文件夹内,cd进去
注意编译时要加O2优化:
gcc rewritten_semtex.c -O2 -o re
./re
3. exploitation 分析
3.0 漏洞
CVE 2013-2094 实际上是一个数组越界改写的漏洞。其影响范围为linux kernel 版本 2.6.37 到 3.8.9
在系统调用 “pref_event_open” 中以结构体 “perf_event_attr” 指针作为输入。
结构体成员如下:
struct perf_event_attr {
__u32 type;
__u32 size;
__u64 config;
...
}
其中config 为一个无符号64位整数。
接下来该系统调用会依次调用两个函数"pref_swevent_init" 和 “sw_pref_event_destroy”:
其中第一个函数尝试将config输入给event_id, 如果config数值较大会导致even_id整数溢出成为负数,然后永远跳过之后的if语句。最后atomic_inc
函数会导致位于pref_swevent_enabled[event_id]
这个地址的值递增。 也就是说在pref_swevent_enabled
数组基址之前的地址被递增。
第二个函数中evnet_id 为无符号64位类型整数,同时没有进行数组越界的检测。同样如果config的数值过大,会导致数组越界。在atomic_dec
函数中会尝试递减数组范围外的地址。
3.1 寻找目标
3.1.1 如何利用越界访问
我们可以尝试以0x0000 0000 ffff ffff
作为系统调用中config的输入。在第一个函数中event_id
会被赋值为0xffff ffff
也就是-1, 导致pref_swevent_enabled
数组基址的前一位地址被递增。
同时在第二个函数中,event_id
会被赋值为0x0000 0000 ffff ffff
十进制为 4294967295, 导致数组越界访问。
我们知道虚拟地址中内核部分为0xffff ffff 8000 0000
到 0xffff ffff ffff ffff
根据上图中的计算。atomic_dec
函数最终会导致用户空间从0x4 0000 0000
到 0x3 8000 0000
的部分被递减。
举一个例子如果pref_swevent_enabled
数组的基址为0xffff ffff 81c4 3d60
, 根据计算递减会发生在0x3 8000 0000
到 0x3 9000 0000
之间
我们可以生成一个memory map 地址为 0x3 8000 0000
到 0x3 9000 0000
之间然后全部设值为0. 等系统调用之后根据值的变化来决定递减发生的位置。
同样在这个例子中递减会发生于 0x0000 0003 81c4 3d5c
其中offset 为 0x1c43d5c
通过offset我们便可以计算出pref_swevent_enabled
数组的基址 0xffff ffff 8000 0000 + offset + 4= 0xffff ffff 81c4 3d60
根据基地址我们就可以操纵这个漏洞发生的位置了。
3.1.2 尝试递增IDT table Gate Descriptor
详细关于中断机制和IDT的介绍在此链接文本的第六章中
Intel® 64 and IA-32 Architectures Developer’s Manual: Vol. 3A
简单来说就是对于每一个Interrupt number 都有一个叫 IDT table Gate Descriptor 的数据结构来储存其相关信息,其中包括中断处理函数的虚拟地址。
如上图所示在64位的 IDT Gate Descriptor 中 offset 63…32 中既阴影部分,存储着中断处理函数的上32位。因为该函数位于内核空间,所以上32位的值为0xffff ffff
。 如果我们可以将这个值递增,该值溢出变为0, 此时中断处理函数地址会变为用户空间中,我们就可以创建memory map 来注入shellcode。