跟着白泽读paper丨MoonShine: Optimizing OS Fuzzer Seed Selection with Trace Distillation

\color{red}{如需转载请注明出处,侵权必究。}

MoonShine: Optimizing OS Fuzzer Seed Selection with Trace Distillation

本文发表于Usenix Security 2018,作者:Shankara Pailoor,Andrew Aday,Suman Jana。三位作者均来自于Columbia University。

1. 主要内容

OS Fuzzer是一种主要在操作系统内核与用户态程序间利用system-call进行安全漏洞挖掘的工具。现有Fuzzer的效率主要依赖种子程序中system-call序列的高质量与多样性,但是产生好的种子程序是一个很难的问题,因为每一个system-call的行为都将严重依赖于前一个system-call所产生的内核状态,因此现在流行的Fuzzer都依赖于人工编写的规则产生可用的种子程序,然而这种方法不仅浪费了大量的人力资源,而且产生的种子程序也比较缺乏多样性。
在这篇文章中,作者设计了一种名为Distillation(蒸馏)的算法,并且开发了用这种算法来产生种子程序的框架工具——MoonShine。它通过利用真实世界中的程序产生的Trace,因为真实世界的程序为了让自身功能的正常运行,需要满足Trace中system-call正常执行所需要的内核状态。MoonShine使用了轻量级的静态分析来对不同的system-call进行依赖关系的检测。
作者将MoonShine嵌入到了Syzkaller(Google开发的OS Fuzzer)中,从3220个真实世界中的程序提取了共计3195个Trace,包含280万个system-call,MoonShine通过蒸馏算法将其优化到14000个。另外,嵌入了MoonShine的Syzkaller发现了17个新的Linux内核漏洞。

MoonShine的工作流程图

2. 解决方法

2.1问题陈述

大多数现在的OS Fuzzer都是利用人工编写的规则来满足前后system-call之间的依赖,生成可用的种子程序,MoonShine从真实的程序运行中产生Trace,因为现实世界运行的程序为了让功能正常运行,需要满足这种依赖。但是这样做有两个challenge,第一个是正常运行的程序,Trace所包含的system-call增长地很快,比如Chromium会在十秒左右的时间产生46万个system-call,因此这样的Trace没法直接当成seed程序使用,而另一方面这样的system-call序列如果因为过长进行缩短的话,很难知道哪些system-call之间有依赖关系。现有的方法通过动态测试的方法进行优化,但是大都时间复杂度较高,不具备可伸缩性。
为了避免这种情况的发生,作者采用了静态分析的方法,首先作者定义了前后system-call之间的两种依赖关系:
Explicit Dependencies:如果系统调用c_i与系统调用c_j满足这种关系,那么表示c_i产生的结果被c_j直接当做输入参数使用。
Implicit Dependencies:如果系统调用c_i与系统调用c_j满足这种关系,那么表示c_i将会通过与c_j在内核中共享的数据来影响c_j的执行,即便c_i的输出与c_j的输入没有重叠。

左边是seed的原始序列,右边是经过蒸馏过的system-call序列。其中可以很明显地看出来第三行的mmap与第二行的open构成了implicit dependency,因为mmap的输入参数直接使用了open的输出,而第一行的mlockall与第六行的msync构成了implicit dependency关系,如下图所示,mlockall会对msync的条件语句的变量进行修改,进而影响到了msync的代码覆盖率。

2.2算法思路

下图是对Trace进行蒸馏算法的伪代码示意图:

代码示意图

首先MoonShine会首先计算每个system-call的coverage,然后将每个system-call的coverage从大到小排序(第5-8行)。对于每一个system-call,首先会判断这个system-call对覆盖率有没有提升(第10行),如果没有的话就剔除(如果这个system-call存在状态依赖的话会在11行与12行通过Dependency添加到seed)MoonShine都会计算它们的Explicit与Implicit Dependency然后合并(第11-13行)。之后这些Dependencies与这个system-call将会和seed合并,另外还会把当前system-call的coverage记录在一个集合中(第14-16行),这样保持了各个system-call在seed中的顺序与在原有Trace中的顺序一致。

接下来给出求Explicit与Implicit Dependency的伪代码:

Explicit与Implicit Dependency的伪代码

对于每一个Trace,MoonShine都会为其构造一个包含两类结点的依赖图:1.结果结点;2.参数结点。其中结果结点包含三类信息:1.返回值;2.返回类型;3.在Trace中产生这样结果结点的system-call。参数结果保存的信息类似:值,类型以及这个参数所属于的system-call。一条从参数结点a指向结果结点r的边表示a依赖于产生r的system-call,MoonShine通过解析Trace来构造这样的图。利用这种依赖图,可以通过遍历依赖图来检测Explicit Dependency。
而对于Implicit Dependency,MoonShine通过静态控制流分析得到。这两个方法会互相进行递归调用,在Trace上不断向上搜索Dependency。Implicit Dependency产生的原因是他们分别对同一个内存中的变量进行了读/写。这样便产生了两种定义:如果一个system-call读了一个变量,那么就称为Read Dependency,同理可以定义Read Dependency。那么可以很容易地给出Implicit Dependency的定义,如果一个system-call的Read Dependency集合与另一个system-call的Write Dependency集合的交集不为空,那么可以认为这两个system-call之间存在着Implicit Dependency关系。

3. 工具实现

为了能够执行蒸馏算法,MoonShine需要知道每个system-call执行后内核的代码覆盖率,作者采用了Kcov进行了覆盖率的测量。
作者通过扩展STrace实现了Tracer,之所以要对STrace进行再开发的原因是要捕捉system-call的名称、参数和返回值。本身STrace是通过fork和exec来跟踪system-call的,他们最后共添加了455行代码和3个文件,并且计划向STrace的开发者提供补丁。
作者通过使用Smatch,一个对C进行静态分析的框架,来进行控制流分析。Smatch允许用户使用hook的方式对程序进行跟踪,这种hook类似于C的表达式,如赋值hook、条件hook,Smatch通过遍历程序的AST完成这项功能。MoonShine如果要跟踪Read Dependency的话,那么通过注册一个Condition Hook来检测条件语句,而Write Dependency只要注册一个Assignment Hook,它会来检测赋值语句的左值。

4. 测试

4.1种子程序

MoonShine的Trace主要通过如下程序来获取:1.Linux Testing Project;2.Linux selftests;3.Open Posix Tests;4.Glibc Testsuite。
由于MoonShine本身只是用来进行优化种子选取的模块,不是整个OS Fuzzer,因此需要嵌入到现有的OS Fuzzer中去。作者为此选取了Google开发的Syzkaller,同时他们将嵌入了MoonShine的Syzkaller运行在了Google的两个fuzzing groups上面,每个group包含4个3.75GHz的CPU与3.6GB的memory。

4.2漏洞检测能力

结果分析

作者检测了三种不同的情况:不使用蒸馏算法(即采用Syzkaller自身编写的人工规则,Default),使用蒸馏算法(Explicit Dependency,E)与使用蒸馏算法(Explicit+Implicit Dependency,I+E)。作者对每一个种子程序的集合分别运行了三次,每次运行了24小时,最后发现使用蒸馏算法可以多发现17个漏洞,其中如果不使用Implicit Dependency的话,能发现7个。

4.3代码覆盖率

与4.2中的测试情况一样,作者依旧分为三类进行测试并在每种情况下运行了24小时,最后发现,(I+E)发现了53270个独立的基本块,(E)发现了51920个独立基本块,而Default发现了47320个独立基本块。

5. 不足之处

5.1缺少线程之间的依赖跟踪

MoonShine的依赖跟踪算法假设了一个system-call的所有依赖都由同一个线程或者父进程产生,但是如果一个system-call依赖的资源由并行线程或进程产生,那么现在的MoonShine的实现将无法跟踪这样的依赖。

5.2静态分析产生误报

作者称使用静态分析去检测implicit depedency可能会产生误报,但是这不会让代码覆盖率下降,只会让Trace的长度变地更长。
作者为此做了实验并发现产生这种误报的主要原因是不够精准的指针分析,如果两个system-call同时读写了一个struct field,MoonShine不能决定是否对应的指针引用了相同的struct实例。

文丨RainyD4y, dotsu, DJR


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335