Nicholas Dean Stephens:谢谢介绍。我将向大家介绍我们自动的漏洞挖掘,我们要有自动的一些技术,挖掘对于整个英特网的挑战怎么样应对。
首先你们知道我的名字了,我是Shellphish CTF团队的研究人员,我们要找到我们的挑战,找到漏洞进行挖掘和修复。我在CGC的黑客大赛之前的几天入这个团队,我最后实际上得了第三名,CGC的黑客挑战实际上是一个DARPA的竞赛,实际上这是美国的国防部高级研究计划局,有很多的竞赛,
比如说有自驾的比赛无人驾驶的比赛,还有其他的比赛,比如说机器人的比赛,可以是用于救灾方面的机器人。最近我想对我们的主题比较接近的就是CGC的比赛,作为一个工具和项目,来找到整个项目的漏洞,然后进行补丁和执行以及修复漏洞。
怎么样进行运营呢?实际上好像是一个攻击保护的流程,每一个参赛者要有一些服务作为服务的提供者,不管是软件或者是硬件,这些都是有漏洞了,实际上组织者知道这个漏洞在哪里,你的目标就是要找到这些漏洞,然后在你的竞争主体之前进行补丁,作为团队来解救。
有意思的一点,实际上我们通过的是机器,而不全是人工的,我们有基础设施,更利于机器自动。CGC对于挖掘的定义越来越松散了,实际上就像这个漏洞来进行更改化,我们这个基础设施实际上有更多的页面和机械,并不全是人工的。
我们可以看到,它实际上更多的迎合了设备,我们可以通过机器进行部署。实际上环境越来越简单了,尤其是对这个项目的分析方面。
这是两种不同的挖掘类型,CGC就是建立一个POV,是可以挖掘的,实际上把这两种不同的挖掘放在一起,这样的话,你可以是第一种挖掘,有可能你会挖掘第二种的漏洞,可以找到任意一种或者是两种。
这样做的过程中,你通过自己的目标,通过这个竞争。另一方面的挖掘就是你可以记录,比如说你可以通过你的页面来泄漏一些记忆,必须展示在这个项目之内,你有四个连续的Bits。
基础设施这方面也在变化,我们有通过这样一个界面,应该有裁判的服务器进行沟通,我们把POV借来提交,有一堆的项目捆绑,和整个价值进行讨价还价,比如说可以列出这些价值。
另一个有意思的,实际上整个环境是越来越简单了,以前可能是250多个的点,现在我们只有7个系统的号,减少了这个OS,我们主要是在这个界面上,这7个系统的Call来进行传输、接收、FD,然后来进行分配和再分配,还有随机,随机实际上是开放的,你可以通过不同的出口进行传输之后的终结,所以我们有这7个系统的Call可以利用。
现在的问题实际上我们需要很大的工程力量,来进行工作,提供解决方案,我们不需要API的这么一个模型。这个奖项实际上是一个什么情况呢?我们有96轮,每一个轮实际上有新的挑战,这些挑战你可以展现,你可以去除,或者可能是一样的挑战。
比如说你可以坚持五轮,每一轮的时候你有分数,看看你得到的分数是多少。所以你得到这些轮的分数叠加起来,你有新的挑战来进行缝补修复和测试,如果你把这些功能全部完成了进行补丁了就会得分。
还有关于安全方面,可能你被攻击了,你如果被攻击了的话,那么这个挑战实际上你就失败了。作为团队,如果你攻击了其他的团队,你也可以得分,你被攻击了你就没有分的,你还会得这个激励奖。
这是一个实际的钓鱼的情景,好像像一个饮料机,我们可以看到,我们要找到这个挑战,我们要进行缝补、撞击,要挖掘这些问题。这个是很大的流程我们怎么做的,我们有不同的元素,我们要和整个环节进行联络,我们要执行,我们要把我们的技术输入输出,
在整个的管道的链条中我们还有其他的系统中各个的元素,我们有52个工作点,这些工作点有工人坚守,我们要维护这些设备。一个有意思的点就是挖掘这个链条,这个链条有点意思,最左边所有的技术我们可以产出测试的一些案例,我们可以找到漏洞进行测试。
我们要建立挖掘或者是找到其他的漏洞进行修复,我将重点谈一谈这个测试方面。
我们怎么样找到这个漏洞,怎么样进行测试?这个是我们的流程。实际上我们团队也是最开始要用AFL,每一个挑战可能要有8个这方面的工作,有一个主人,七个工作人员。在整个过程当中,我们要有能力增加更多的工作人员。
实际上这个是我们模拟Fuzzer的挑战,我们并不是来修复AFM,我们知道其他的团队他们要在堆上重新写一些程序,但是我们不是这样做。我们还有网络的发掘,实际上我们最后也是这样做的,
我们并不是没有预料到这个交通量,我们要利用网络,来决定哪一个撞击是我们要感兴趣的,我们要找到哪个点。我们很多测试基础设施是基于AFL,这是非常有意思的交易。
我们有一个Driller,主要是通过AFL+Angr加在一起使用的,我们一开始就使用这样的符号执行,我们希望能够真正的用这样的一种特定的输入方式去获得一种很好的解决办法。因为这样的解决办法在测试的时候是特别快的,而且可以通过这种模糊测试。
因为原来很多的方法可能会使得这个测试速度很慢,但是我们可以通过这样Driller的方式,能够通过通用的输入,然后去找到这个解决的办法。同时又通过这种符号执行,通过特定输入来找到一个解决的办法。
所以说是非常容易的,而且很多的这种数据的来回交换也是非常直接的。而且我们也可以看到,其实在很多的这些,比如说有一些问题出现,就会导致你运算的时间特别长。有了这种模糊测试,我们就可以去避免一些非常耗时的计算,所以说它是一个特别简便的方式,这里面只有四个分支。
首先有一个模糊测试,比如说X1,在一段时间你可以看到这个Fuzzer运行了一段时间,你可以得到它最后的一个覆盖范围。之后用Driller,会有一个动态的符号执行,可以一直追踪整个路径,通过这种二位的计算方式去追踪这个路径。
在其他的一些测试里面可能没有办法特别好的测试出来的,我们可以用位图的方式去实现这样一个测试和执行。我们到底能不能够真正的解决基础的内容?其实我们是可以的,我们通过一些新的测试案例来产生这样一个结果。
我们确实一开始的时候可能会觉得很难去运行,但是我们通过了这样的Driller结构,可以进行一些很快速的模糊测试,我们就不需要耗费太多的时间去关注在那些小的执行方面了。最后我们能够看到,我们这个测试其实是非常简单的,
我们有三种方式,AFL、Network和Driller,通过不同的测试方式,我们也可以把它接入到其他的一些管道里面。有的时候没有办法执行,有的时候流量特别大,每秒达到几个比特的数级,我们就可以用这种网络的方式进行测试。
在整个管道里面,我们有Crash来进行利用,比如像Rex,它们是我们的记忆、存储,所以我们就用同样的追溯的方式,去利用这样一个Crash,然后把这个作为一种输入,然后把它得出CGC的漏洞利用。
我们就可以进行这种符号的追踪,当我们进行了这个追踪之后会进行一个分类,看看这个Crash是属于什么样的类型,在这里面我们也可以利用不同的漏洞利用的技术来进行分类。比如说可以用ROP,用壳代码去绕过这样一个注册,也可以去探索,把这种Crash进一步的利用和发掘,这个就是在一种利用的阶段。
给大家举一个例子,我觉得是非常有意思的,有每一个步骤,我们看看具体是怎么操作的。比如说在这里面有一个符号追踪,出现了一个缓冲区的溢出,那个里面有一个功能的Point,在中间我们怎么定位这个Crash,首先在左边有一个箭头,我们把它叫做一个输入,是我们想像的,我们把这个称为一组符号的位数。
然后我们把它加入到这个漏洞的元素里面,我们去把一些数据放在堆栈里面。我们可以看到这个堆栈里面有些信息被启动出来,可以被拨叫。在这里面有一个标本,我们可以在这个堆栈上创建数据。这样的话,我们可以放在这个堆栈里面然后再进行复制。
假设有一个Crash出现了,比如说36AA,之后我们进行追踪,每一次迭代我们就看到,都会把这个数据加入到堆栈里面。这里面有象征的位数,其实我们假设是36个A,如果说它是出现了一个Crash,我们会把这个创建出来,最后会有一个符号的数据,我们可以看到这个Crash发生的时间,可以让我们解读出在什么样的情况下可以把这个Crash进行分类。
其实在这里是举的比较简单的例子,它是基本的一种Crash,解释一下我们可能会出现什么类型的Crash。我们可以重写这个PC,有PC重写的这种Crash。如果它不是符号的话,可能是出现了重写。
如果说确实是重写的话,我们可以进行读取内容。基于这样一个计算结果,我们可以进一步的去利用这个漏洞,最基本的一个方式或者说技术就叫做漏洞利用的逻辑。我们有不同的一些方面,有一些技术我们可以去使用,在分类的时候我们要决定需要利用什么样的技术。
这里面有几个关于Rex的技术,比如说PC的重写,还有一些就是直接进入了壳代码,或者是他需要去介入ROP的链条,有些时候是间接的描述。我们可以看它到底是处于什么样的一种分类,我们可能就需要重新配置这个PC,重新来配置这个注册器。
还有一些其他的方面,我们还有一种Point to Flag的技术,点到标记的技术,我们可以把它回归到我们能够控制的这样一个缓冲状态。我们就可以试图把它回到我们能够控制的缓冲区,然后我们可以重新来追溯,我们现在可以知道,有PC的重写之后,我们就可以通过这样一种方式重新把它控制到我们能够接受的一个缓冲区。
如果说我们直接跳到壳代码的话,我们就可以直接把这个Crash的状态转到可以发掘利用的一个状态。在这里面演示,比如说在PC,在缓冲区里边有一个壳代码,有记忆的模块,然后去控制这个缓冲区,这个壳代码会拿到一个地址,需要看到这个地址,然后再把它拉出来,他会觉得这个缓冲区应该是和他想要去跳到的这个壳代码必须是一致的。
然后他们就是把这个缓冲区进行一些条件的限制,然后能够承载我们的这个壳代码。Buffer是发现了这样一个符号的缓冲区,在这个时候我们就需要去具体化。其实这里面有很多不同的东西,比如说Crash的日期,还有在上面加的这些限制条件,让它能够介入到这种漏洞利用的状态,其实是很简单的。
我们更感兴趣的就是跟这个壳代码更加类似,如果说这个区域能够执行的话,我们就能够把它控制到能够控制的堆里面。我们会有一个片段,在CGC里面我们叫做符号的变量,把这个变量又用到我们的C文件夹里面,我们可以进行一些动态的运行。
所以我们有一个Chain,有它的长度。最后一个很有意思的步骤,我们想要找一个Gadget,可以把这个堆的Point接入到我们的Chain里面,我们就要去看一下这个Chain的堆怎么能够把它加入到里面。
如果说我们想要执行这样一个Gadget,我们这个Chain就要去被激活执行。所以我们就是不断的去探索,然后我们发现,其实它只是加入一些限制的条件。我们新的这种堆的Point,可能确保这个地址上的内存能够让这个PC和Gadget相联系,这个也是我们去描述这样一个Crash的过程。
还有一些,可以直接写入。在实际的代码里面,我们希望能够确保你不去使用那个Gadget去改变你的内核,而我们应该控制的是这个缓冲区。
还有一些方法,在这里面关于Rex的问题就是太慢了,取决于这些小的执行。我们有一些方法可以在这里面去克服这个问题,我们AFL如果说大家曾经用过的话就可以看到,其实很多东西都是特别独特的,他们就是用不同的路径去做,但是最后能够得出同样的一个Bug。
绝大多数情况下,我们就看到通过不同类型的Crash,我们可以总结出我们希望能够把所有的Crash都一起来加以利用。我们可能要看一下这个挑战是怎么样的,后面还有一些,比如说有20个Challenge等等,我们就要逐一的进行分析,所以我们要进行符号执行。
这张幻灯片是整个追溯所有的这些内容,用这种分析分类的方法,我们可以了解到这个Crash是属于什么样的类型,然后我们去看核心的文件,去看到底这个Crash是属于什么类型的,是PC重写的Crash,还是说基本的这样一些不同的Crash。它可以让我们能够避免很多不必要的这些步骤。
这也是让我们能够进一步的降低成本的,POVFuzzer模糊测试,我们可以把你的Crash文件追踪出来,然后在Crash的日期发生之前,要对比一下出现了什么样的状况。使用我们的这个技术是非常有效的,我们这个团队做的非常令人印象深刻。
在整个挖掘过程中,应对挑战中我们的一些技巧。实际上有一些是泄漏一些数据,我们怎么样阻止这些呢?我们有Test cases这样的工具,我们来做一个举旗的行动,在旗帜下面我的一些数据我们要找到这些泄漏,然后攻击,进行逆转数据,然后要分析,
如果技术逆转的话,因为这种攻势,我们要在运作的过程当中解释,不管是NAL还是其他的方式,我们进行攻击过程中有的可能有一些事情有漏洞,所以我们要把这些数据进行保留,而不是泄漏出来。后面的这个问题实际上我们要挖掘这些泄漏。
怎么样解决这个问题?我们要利用这些执行过程中的挖掘。我们看到很多的泄漏实际上不需要任何的修改,不需要很多运营的时间,我们只是来产生一些东西,然后要把它进行流动,然后进行运营,我们来进行逆转,然后把它送回去。
我们怎么样做呢?我们使用一个插入的系统来解决我们的挑战进行执行,这个实际上很有效。最主要的问题就是可能这个速度比较慢,比如我们说的我们使用系统的速度比较慢,可能是一个CPU的差不多三百万的速度,低于普通的CPU。
QEMU的速度也是比CPU要低了2.5倍,我们在整个的追溯过程中,如果我们有这种表现或者是一个系统的Call的话我们要进行更新,看看什么样的是比较突出的,我们必须要进行标注。这个比普通的追溯要好,因为我们使用我们一个新的系统来进行启动。
我们在重新启动过程当中使用的是“麒麟”的系统,我们可以得到更多的追踪,我们有实际的追踪,还有意义上的追踪,有两种不同的追踪。最后执行的过程当中我们要有不同的状态,要进行拓展,看看什么是突出的,什么是旗帜的方式进行挖掘,然后看看逆转的方式是什么。
我们加入这些限制,挖掘这些泄漏,看看所有的产出是什么,我们限制的情景是什么,来进行判断和挖掘。
现在我们看看这些成果,我们是得的第三等奖,Mayhem是一等奖,Xandra是二等奖,我们是三等奖,有时间,有更新得分数。最右边红色的横线实际上可以看到我们的进展情况,所有的这些团队,实际上作为这个团队来说我觉得非常好。
如果再进一步看这些结果的话,我们看到Mechaphish找到了更多的挑战,有15个挑战,我们解决了11个,有的团队找到了9个或者是10个挑战,并且解决了这些挑战,所以Mayhem是CGC的赢家,他们的系统曾经在比赛过程中瘫痪了,Mayhem停止了他们的运营很长时间,他们说他们有漏洞,这个机器是不能运转了。
我们可以想,他们要重新启动,要重新进行补丁,他们来进行反应。但是我们可以看到最后的结果,CGC实际上给他的分数最高,最后他赢了,比如说你的补丁或者时间,而是看你应对了多少挑战。所以解决的挑战越多的话,赢的可能性就越大。
有的时候到晚上,机器可能会停止运转,没有关系,晚上你解决挑战的问题会更多。所以我们可以看到挖掘方面,Shellphish在挖掘方面表现得很好,仅仅低于Codjitsu这个团队,他们解决了一半的挑战,他们得到了这个成就,
可能速度比较快,他们解决挑战的时间是我们的10倍,比我们快。如果时间用得短的话,他们的某一个项目的得分就会比我们高。这个就是我们比赛的情景。
我们回顾一下我们的收获或者是感想。整个系统是不是需要重新评估呢?比如说怎么样把所有的关键点能够进行维护,怎么样进行一些漏洞的挖掘,整个的流程我们需要不需要重新的进行评估?
我们可以看到整个的系统实际上有很多的技巧可以找到不同的阶段,你利用你的技巧来进行挖掘。可能是比较有意思的一个过程,不管是人工还是自动,我们有自己的挖掘技术,希望我们能够找到更好的自动的技术。
我想和大家分享的另一点,CGC的分数可能有一些和其他的比赛是不一样的,因为它涉及到的漏洞和挑战,还有时间,你得到的这个分数,有一个团队做的不是非常好,有的时候做的好会给1分,但是做的不好分就会被拿走。
所以整个做起来,有可能你得分数非常低。但是非常有幸,我们做了很多,我们应对了很多的挑战,做了很多补丁,得了第三名。一定要对攻击进行防护,比如说Mayhem他们做得非常好,他们得得了第一,他们找到了问题,然后进行补丁、挖掘和修补。
所以有意思的一点,最终的这些CGC的分数是怎么得的,想得到最高分,就是要找到这些漏洞,然后进行挖掘。我们要更关注什么点呢?有可能是大家进行争论的,我不知道答案。
以上就是我的一些想法,谢谢大家的聆听,谢谢组织者来邀请我进行发言,我们是开源的,大家可以查到我的讲话,我们都是基于CGC的,所有我们做的这些事情都是基于我们的项目。如果大家比较感兴趣的话,可以找到我们参与的大赛的情况,谢谢!