首页
论坛
课程
招聘
[原创]2017-8890堆喷的一些思考
2018-10-29 23:46 7099

[原创]2017-8890堆喷的一些思考

2018-10-29 23:46
7099

       说来惭愧,仅仅是8890的堆喷,我也搞了快一个多月。除了时间上有限,业余时间搞搞,另一个就是经验不足,技术尚浅。。。

       “不贪多,尽量吃透每个cve的利用,后面应该会比较容易上手“,有个大牛告诉我。大牛说的对,坚持就会有进步。

       话不多说,直接切入主题。不讲漏洞细节,细节分析的文章很多,我只讲讲自己堆喷的时候遇到的一些问题、一些想法和思路,一方面是为了总结下,另一方面是技术交流。大概就是下面这几条:

1.     堆喷方式的选择

        object-based类型的堆喷是用的比较多的堆喷方式,但是具体搞起来也有很多种方式,有用add_key,sendmsg,sendmmsg来喷的,也有用像8890里面用到的这种setsockopt的方式等;

        具体用的时候就发现,这些每一种堆喷的方式都不太一样,包括:分配内存size是否可控、内存里的content是否可控(二进制可控?或者是必须满足一些条件如字符串等)、是否是占位式的堆喷(这个是我起的名字,占位式的堆喷就是说kmalloc了之后,并不立即释放,释放时间是可以在用户态控制;非占位式的堆喷就是kmalloc之后,立马kfree)

        刚开始喷8890的时候,开始用了sendmsg,add_key,效果不好,从崩溃上看,有时候会kfree一堆object,仔细分析了之后发现,sendmsg,add_key这两个堆喷方式都是非占位式的,内存用完了之后立马被kfree。kfree就会把对应的object链入到freelist里面去,而object的最前面放的可是next指针,指向下一个空闲的object。但是我们得控制ip_mc_list头部的8字节指针next_rcu,所以,非占位式的堆喷效果不会太好。

        当然,非占位式的堆喷也有很强的时候,就比如之前2015-1805的利用,科恩实验室很巧妙地用了这种方式。

        反观占位式的堆喷,就非常符合8890的这个场景。(但是怎么来找这样的堆喷接口?我刚开始是在那些可能存在阻塞的系统调用里面找,没找到,又问了问大牛,说可以从文件系统、驱动这些地方去找找,这些地方会有一些生命周期比较长的内存分配操作,还有大牛知道其他思路吗,求告知)接着就用setsockopt来喷了,结果还是比前面要好。

2.     多

        多?什么多?

        我用了很多线程来调用setsockopt,而且每个线程里,就一个socket而言,可以调用很多次setsockopt。多多益善,堆喷的内存多了,命中的概率也会增加。

3.     干净

堆喷的大体过程就是:(1) alloc ip_mc_socklist,分配受害的ip_mc_socklist

                                    (2) free ip_mc_socklist,释放受害的ip_mc_socklist

                                    (3) alloc evil ipv6_mc_socklist, 分配ipv6_mc_socklist

         这三个过程中间,应该尽量保持做尽可能少的其他操作。

         我在开始做第(3)步的时候,直接在第(2)步完成之后,就pthread_create了很多线程,然后在每个线程里面用setsockopt做堆喷。但是实际效果就是基本上喷不对,总是崩。  

         还是问了大牛,大牛一语中的“你在堆喷的时候做pthread_create这么重的操作,你确定能喷上吗?”。我仔细一想,果然如此,free掉的ip_mc_socklist很大可能是被pthread_create里的某个操作给占掉了。

顺着这个改进思路又改了,结果好像还是不行,依然很难喷上去;

又检查了代码,发现我在第(2)步之后,写了很多printf,,会不会是这个玩意的问题?删掉删掉。删掉之后可以偶尔喷对几次了。

         所以说,这三个过程期间能少写一些代码就少写,不能少的,就看看能不能往前往后挪。

4.     尽量别主动放弃cpu

         这个也是我无意中删除了自己利用代码里的sleep,堆喷效率下降很多之后想到的。不过这一条也仅仅是我的推断:

         在堆喷期间进行主动地sleep操作,就相当于当前进程主动放弃cpu,这样进程一调度,指不定就把什么高优先级的进程给调度到了当前cpu,这样,如果是在堆喷的第(2)阶段,而这个高优先级的进程里面有什么内存的alloc操作,那很大可能把受害的ip_mc_socklist给占了,那堆喷肯定没法成功了。

5.     堆喷时的defragmentation

         这里所说的就是去除slab里面的碎片化的一些空闲内存块。因为之前看了king团队发的8890 poc,就发现里面有个什么defrag的操作,一直不明白为什么要做这样的操作。直到看到了这篇论文:

《From Collision To Exploitation: Unleashing Use-After-Free Vulnerabilities in Linux Kernel》,

         这里面就提到了defragmentation的操作,原因也得是自己看了slub allocater里面的一些操作才明白了。

内核的内存状况很有可能是处于这种状态的:freelist所处的slab1是一个快要分配满了的slab,上面可能就只有几个个空闲的内存块。此时进行堆喷的第(1)步,执行完了之后,可能内核里的其他部分还有内存分配操作,这样,就干脆把freelist所处的slab1给用完了,而且呢,freelist顺便就被设置到了slab2这个还有空闲内存块的slab上了。

         进行第(2)步的时候,slab1上的ip_mc_socklist被free掉了,但是这个时候,slab1也只是被链入到了partial里面去了,并不直接分配给freelist,

再到第(3)步的时候,要alloc内存块,那肯定是从slab2上面分配,slab1上被free了的ip_mc_socklist能不能被覆盖那还不好说;

         所以,为了尽可能避免上面描述的这种情况发生,就有了defragmentation,它的目的就是把这些slab里面的小的内存块给占用掉,这样在进行第(1)步的时候,让ip_mc_socklist大概率不被分配到这些碎片当中去。

         试想,当第(1)步中的ip_mc_socklist被分配到了一个slab的中前部分,也就是说分配完ip_mc_socklist之后,这个slab还有一大把的空闲内存块,接着第(2)步之后,堆喷的ipv6_mc_socklist大概率也是从同一个slab上分配的,而且大概率就会占用到ip_mc_socklist的那块内存。

6.     堆喷的三步尽量从时间和空间上紧凑

         时间久了指不定会发生什么事。

         还是从slub allocator的特性上来看,假设第(1)步和第(2)步中间隔了很久很久,可能看起来并不影响堆喷,但是仔细分析却不然。

         第(1)步分配完ip_mc_socklist,过了很久一段时间之后,可能ip_mc_socklist所在的slab1估计都被用完了,没有空闲的块了,然后freelist也重新找了一块slab2来用了。接着再来第(2)步,把ip_mc_socklist给free掉,那它所在的slab1也就链入到patial里面去了,第(3)步的时候,再喷,那也是从slab2里面分配内存空间,slab1还得再等等才能被用到。


【公告】欢迎大家踊跃尝试高研班11月试题,挑战自己的极限!

收藏
点赞0
打赏
分享
最新回复 (12)
雪    币: 11527
活跃值: 活跃值 (2823)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
LowRebSwrd 活跃值 4 2018-10-30 14:51
4
0
赞!关键存在一个patial,没有放入到freelist, 被重新占位。
雪    币: 1874
活跃值: 活跃值 (7759)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2018-10-30 14:55
5
0
,测试一下
最后于 2018-10-30 14:55 被kanxue编辑 ,原因:
雪    币: 431
活跃值: 活跃值 (65)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
ID蝴蝶 活跃值 1 2018-10-30 18:38
6
0
好文。,这就是内功了。
雪    币: 261
活跃值: 活跃值 (52)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
wule 活跃值 2 2018-10-30 20:35
7
0
多多交流
雪    币: 25
活跃值: 活跃值 (170)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
endlif 活跃值 1 2018-10-31 14:48
8
0
wule 多多交流[em_67]
能拉个群么 一起交流么 最近也在学习android系统漏洞 
雪    币: 284
活跃值: 活跃值 (191)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
gezigezao 活跃值 2018-11-1 15:33
9
0
m
雪    币: 13848
活跃值: 活跃值 (2924)
能力值: ( LV13,RANK:830 )
在线值:
发帖
回帖
粉丝
大帅锅 活跃值 4 2018-11-2 14:38
10
0
我最近也在研究这个,编译的kernel和busybox放入qemu中,不知怎么的调用result=setsockopt(server_socket, SOL_IP, MCAST_JOIN_GROUP, &group, sizeof (group));这句的时候总是返回-1.
雪    币: 261
活跃值: 活跃值 (52)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
wule 活跃值 2 2018-11-3 00:02
11
0
大帅锅 我最近也在研究这个,编译的kernel和busybox放入qemu中,不知怎么的调用result=setsockopt(server_socket, SOL_IP, MCAST_JOIN_GROUP, ...
打打日志,跟跟
雪    币: 7517
活跃值: 活跃值 (672)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
jltxgcy 活跃值 2 2019-2-6 10:16
12
0
请问如何defragmentation,是用cat /proc/slabinfo,计算free object?这篇文章的思路https://yq.aliyun.com/articles/1725?
雪    币: 261
活跃值: 活跃值 (52)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
wule 活跃值 2 2019-2-12 10:02
13
0
/proc/slabinfo高版本默认没有,defragmentation我是尝试来做的,多试几次,看看那个数目效率最好
游客
登录 | 注册 方可回帖
返回