-
-
[原创]2017-8890堆喷的一些思考
-
发表于:
2018-10-29 23:46
10745
-
说来惭愧,仅仅是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里的某个操作给占掉了。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课