HoS 发表于 2016-4-14 11:15

吾爱破解2016安全挑战赛第3题Android溢出题分析

题目要求在提供的 arm64 模拟器上用 CVE-2015-3636 漏洞实现提权。关于 CVE-2015-3636 的分析网上有很多,可以参考 KeenTeam 的Own your Android! Yet Another Universal Root。
GitHub 上也有 PoC ,https://github.com/fi01/CVE-2015-3636,32 位的,修改一下就能在 64 位跑。剩下的就是绕过 PXN 和 SELinux 。
漏洞利用思路
1. 利用 ret2dir(physmap) 覆盖 socket 的 close 函数指针2. 调用 close(sockfd) 取得 pc3. ROP 修改 thread_info.addr_limit ,获得任意地址读写4. 修改 thread_info.task.cred 和 security 提权
漏洞触发地址
直接运行 GitHub 上的 PoC 会发现崩溃地址不是 0x200200 ,而是 0x1360 (为什么还要加个 1 )。
http://7xqei9.com1.z0.glb.clouddn.com/2016-04-14-14605611452374.jpg
这是一个低地址,一般 mmap 是 map 不到的,需要修改 mmap_min_addr 。一般需要 root 权限才能改,但这里其实 shell 用户也可以改。修改方法:echo 4096 > /proc/sys/vm/mmap_min_addr
绕过 PXN由于内核开启了 PXN ,不能从内核地址直接跳到用户地址,需要使用 ROP 绕过。关于 ROP 我也不太熟,找了很久才找到一段,像 JOP 多一点。可以参考这篇文章 PXN防护技术的研究与绕过 。
http://7xqei9.com1.z0.glb.clouddn.com/2016-04-14-14605618740354.jpg
这一坨,有点长,地址是文件地址,要加上 0xffffffc000080000(用 RopGadget 时忘记加了,又不想跑多一次)

效果就是修改 addr_limit ,泄漏 sp 。修改之后就能在用户态随意读写内核地址了。然后修改 thread_info.task.cred 就能拿到 root 权限。但因为 SELinux 的存在,还是存在很多限制。
相当于unsigned long thread_info_addr = sp & 0xFFFFFFFFFFFFC000;
unsigned long addr_limit_addr = thread_info_addr + 8;
*(void *)addr_limit_addr = 0xFFFFFFFFFFFFFFFF;
绕过 SELinux虽然可以直接设置 security 的 sid 为 1 ,拿到 u:r:kernel:s0 权限,但这不是最高权限。u:r:init:s0 权限最高,但 sid 不固定,需要找到 init 进程获取,如何找 init 进程?找 init_task 。KeenTeam 的这篇 How to Root 10 Million Phones with One Exploit 讲的很详细。
搜索 init_task ,先从 /proc/iomem 读出 kernel data 地址,然后特征搜索。然后遍历 init_task.task ,找到 init 进程。

for (k = 0xffffffc0005f6000; k < 0xffffffc000687bcf; k += 8) {
    read_pipe((void*)k, &init_info, sizeof init_info);
    if ((init_info.stack & 0x1ff) == 0 && init_info.usage == 0x2 && init_info.flags == 0x200000) {
      // printf("Init_info at %p\n", (void*) k);
      init_task_addr = (void *)k;
      break;
    }
}
修改了sid后可以执行 system(id) ,但不能执行 system(sh) 。估计是跟 sepolicy 有关,感觉又是很麻烦的,就没继续弄了。
第 5 题
搞定这个后第 5 题就简单了,漏洞可以越界读写比 buffer 高的内核堆地址。因为时间关系,暴力解决了。就是fork一堆子进程,利用漏洞将找到所有 task_info 的 addr_limit 改掉,找到有权限的子进程继续提权。当然这种方法很不稳定。可以通过设置查找 comm 来精确定位。
后记
比赛之前刚好在看 KeenTeam 的那几篇文章,结果比赛题目就出这个,只能说运气比较好。其实我是想来做 CrackMe 的,结果调这个就调了两天。因为之前没写过漏洞exp,时间都花在看文档上,代码都是到处抠的,乱到自己都不想看 (*つ _ ⊂* ),就不贴了。
最后感谢吾爱和 360 举办这次比赛,感谢 KeenTeam 的分享。

HoS 发表于 2016-4-14 15:18

四川无声pkav 发表于 2016-4-14 13:59
因为0x1360不能mmap就没做了,题目设计有问题。如果能修改mmap_min_addr这就算是另外的洞了。360出题前也不 ...

开始也没管这个,直接su改了
后来 exp 写好了,还在想怎么绕过 mmap_min_addr ,没想到shell用户居然可以直接改
感觉是故意设置的

四川无声pkav 发表于 2016-4-14 13:59

因为0x1360不能mmap就没做了,题目设计有问题。如果能修改mmap_min_addr这就算是另外的洞了。360出题前也不写个exp验证一下。

coolboy 发表于 2016-4-14 11:40

厉害啊啊

a353138127 发表于 2016-4-14 11:49

666膜拜大神,本乃小白看不懂!

Ericky 发表于 2016-4-14 12:15

打算学习漏洞 顶一下像楼主学习

第三条腿的爱 发表于 2016-4-14 12:36

大神膜拜

赖哥 发表于 2016-4-14 12:39

小菜来学习了 感谢大牛分析

天地无空 发表于 2016-4-14 12:46

学习一下,谢谢分享

KiSs雨悸 发表于 2016-4-14 13:06

厉害,佩服!动手多练

z491749617 发表于 2016-4-14 13:47

冰楓丶殘瀷 发表于 2016-4-14 13:47

前排!!!!!
页: [1] 2 3 4 5 6
查看完整版本: 吾爱破解2016安全挑战赛第3题Android溢出题分析