ref:https://www.sigpwn.io/blog/2018/5/13/adding-afl-bloom-filter-to-domato-for-fun

Adding AFL Bloom Filter to Domato for Fun

So I have been playing with Domato for few weeks now and wrote a blog about it's internals along the way. Unfortunately there is no feedback mechanism in the open-sourced version of Domato, although according to the blog post by Ivan Fratic (@ifsecure) of google project zero they are experimenting with coverage guided fuzzing using modified version of WinAFL's DynamoRIO client. I had a chat with Richard Johnson (@richinseattle) of Cisco Talos Vulndev Team while staying in Dubai for OPCDE 2018 and he gave me an idea of adding some kind of feedback mechanism in the syntax level instead of binary level feedback. First thing that came up to my mind was AFL's bloom filter. Since it is known to be so effective, why not try adding this to Domato as well?

Adding unique IDs to grammar rules

If you read my previous post, you will have understanding of how grammar rules are parsed and stored in data structures. In AFL, unique ids are assigned to each basic block(对于基本块制定一个唯一的id). In our case, assigning unique ids to each grammar rules seems appropriate since order of selecting certain grammar rules for expanding symbols is similar to visiting basic blocks in the control flow graph. (以选择不同的语法组合成为代码覆盖率计算的替代。)

So in the grammar.py file of Domato, I made following changes:

def _parse_code_line(self, line, helper_lines=False):
"""Parses a rule for generating code."""
rule = {
'type': 'code',
'parts': [],
'creates': [],
'uid' : self._get_new_uid() # add this field
} def _parse_grammar_line(self, line):
"""Parses a grammar rule."""
# Check if the line matches grammar rule pattern (<tagname> = ...).
match = re.match(r'^<([^>]*)>\s*=\s*(.*)$', line)
if not match:
raise GrammarError('Error parsing rule ' + line) # Parse the line to create a grammar rule.
rule = {
'type': 'grammar',
'creates': self._parse_tag_and_attributes(match.group(1)),
'parts': [],
'uid': self._get_new_uid() # add this field
}

Now each rule contains a field named 'uid' that stores unique integer value.

Selecting less chosen rule for expanding symbols

To record which rules were chosen in the previous generated case, I added a Python dictionary for this purpose.

# coverage map
self._cov = {}

Now when choosing the rule for expanding current symbol, we need to reference the coverage map. Note that algorithm used in AFL is like following.

cur_location = <COMPILE_TIME_RANDOM>;//选择的rule
shared_mem[cur_location ^ prev_location]++;
prev_location = cur_location >> 1;//prev_location代表之前选择的rule,以rule覆盖率来替代目标运行代码覆盖率

So in our case,  cur_location is the unique id of a rule we are considering to select. prev_location is previously chosen rule. Following code checks whether if there is an never selected order of grammar rules (thus bitmap_idx is not in the coverage map,代码选择顺序是否出现过) and selects first encountered rule of this case.

If every combination of previously selected grammar rule and current rule candidates have been selected before (so every possible bitmap_idx is already present as a key in coverage map), code saves how many times certain combination has been chosen.

def _select_creator(self, symbol, recursion_depth, force_nonrecursive):
...
# select creator based on coverage map
# select creator that has been selected less
hits = []
for c in creators:
bitmap_idx = c['uid'] ^ self._prev_id
if bitmap_idx not in self._cov:
self._cov[bitmap_idx] = 1
self._prev_id = c['uid'] >> 1
return c
else:
hits.append(self._cov[bitmap_idx])

Among the grammar rules chosen, code saves a list (less_visited_creators[]) of relatively least selected rules. If cdf is not available for rules for some symbol, it randomly chooses from less_visited_creators[] and records coverage info accordingly.

idx = random.randint(0, len(less_visited_creators) - 1)
curr_id = less_visited_creators[idx]['uid']
self._cov[(self._prev_id ^ curr_id) % MAP_SIZE] = self._cov[self._prev_id ^ curr_id] + 1
self._prev_id = curr_id >> 1
return less_visited_creators[idx]

Similarly, if cdf is available for some symbol, it uses cdf instead randomly choosing a grammar rule and records coverage information.

idx = bisect.bisect_left(less_visited_creators_cdf, random.random(), 0, len(less_visited_creators_cdf)-1)
curr_id = less_visited_creators[idx]['uid']
self._cov[(self._prev_id ^ curr_id) % MAP_SIZE] = self._cov[(self._prev_id ^ curr_id) % MAP_SIZE] + 1
self._prev_id = curr_id >> 1
return less_visited_creators[idx]

Results

Because I lack resources to be used for fuzzing, testing was somewhat limited. Also I believe Google fuzzed modern browsers with Domato (or customized internal versions) long enough so there is a very low chance of myself finding exploitable crashes with my limited resources. However, my version of Domato was able to find more unique crashes than the original open-sourced version after fuzzing IE11 on Windows 10.(发现更多不同的崩溃)

I generated 10,000 html files with both original Domato and my customized version and used them to fuzz IE11 to see which gets more unique crashes. The result if the following.

  • Original : 16 unique crashes
  • Customized : 20 unique crashes

I will soon release the code for those who are interested (it there is someone :P), although I guess by reading this blog you have enough information to go try out by yourself.

Any feedbacks or reporting of errors, please reach out !

ref:Adding AFL Bloom Filter to Domato for Fun的更多相关文章

  1. Skip List & Bloom Filter

    Skip List | Set 1 (Introduction)   Can we search in a sorted linked list in better than O(n) time?Th ...

  2. Bloom Filter:海量数据的HashSet

    Bloom Filter一般用于数据的去重计算,近似于HashSet的功能:但是不同于Bitmap(用于精确计算),其为一种估算的数据结构,存在误判(false positive)的情况. 1. 基本 ...

  3. 探索C#之布隆过滤器(Bloom filter)

    阅读目录: 背景介绍 算法原理 误判率 BF改进 总结 背景介绍 Bloom filter(后面简称BF)是Bloom在1970年提出的二进制向量数据结构.通俗来说就是在大数据集合下高效判断某个成员是 ...

  4. Bloom Filter 布隆过滤器

    Bloom Filter 是由伯顿.布隆(Burton Bloom)在1970年提出的一种多hash函数映射的快速查找算法.它实际上是一个很长的二进制向量和一些列随机映射函数.应用在数据量很大的情况下 ...

  5. Bloom Filter学习

    参考文献: Bloom Filters - the math    http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html    B ...

  6. 【转】探索C#之布隆过滤器(Bloom filter)

    原文:蘑菇先生,http://www.cnblogs.com/mushroom/p/4556801.html 背景介绍 Bloom filter(后面简称BF)是Bloom在1970年提出的二进制向量 ...

  7. bloom filter

    Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员. 结    构 二进制 召回率 ...

  8. Bloom Filter 概念和原理

    Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员.如果检测结果为是,该元素不一定 ...

  9. 【转】Bloom Filter布隆过滤器的概念和原理

    转自:http://blog.csdn.net/jiaomeng/article/details/1495500 之前看数学之美丽,里面有提到布隆过滤器的过滤垃圾邮件,感觉到何其的牛,竟然有这么高效的 ...

随机推荐

  1. 全表 or 索引

    这一篇文章证实了以前对MySQL优化程序的工作原理. MySQL就像一个人一样,总是聪明的去选择当前最快的方式去查询,而不是像Oracle数据那样死板地根据规格去查询. 查询的要求在于快.而对于数据库 ...

  2. linux shell学习三

    Shell for循环 Shell for循环的语法如下所示 for 变量 in 列表 do command1 command2 ... commandN done 举例: ..} do echo $ ...

  3. 前端PHP入门-031-文件上传-六脉神剑

    php.ini的设置 php.ini的文件太多,找不到的时候你可以使用 Ctrl+F 搜索相关配置项. 配置项 功能说明 file_uploads on 为开启文件上传功能,off 为关闭 post_ ...

  4. 用CSS3画出一个立方体---转

    css3实践—创建3D立方体 要想实现3D的效果,其实非常简单,只需指定一个元素为容器并设置transform-style:preserve-3d,那么它的后代元素便会有3D效果.不过有很多需要注意的 ...

  5. C11构造函数的改善

    1.委托构造函数 委托构造函数就是允许在同一个类中一个构造函数可以调用另一个构造函数,从而在初始化时简化变量的初始化. class CTest { public: int x; int y; int ...

  6. POJ2043 Area of Polygons

    Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 1020   Accepted: 407 Description Yoko's ...

  7. HTTP/2.0 简单总结(转载)

    HTTP/2.0 简单总结(转载于https://linjunzhu.github.io/blog/2016/03/10/http2-zongjie/) 如何使用上 HTTP/2.0 需要浏览器的支持 ...

  8. vps建站教程 CentOS6如何安装配置FTP服务器

    通过之前的几篇文章,我们都知道了如何配置PHP环境,也知道如何保护我们的vps以及如何绑定多个域名建设多个网站.有时候我们为了让我们的朋友也能用我们的vps建站又不想给他们太多权限,有时候我们想要当个 ...

  9. android ViewPager之OnPageChangeListener接口

    项目中在使用ViewPager的时候,一般都要在界面滑动的时候做一些事情,android中有个专门的状态回调接口OnPageChangeListener. /** * Callback interfa ...

  10. python OS 模块 文件目录操作

    Python OS 模块 文件目录操作 os模块中包含了一系列文件操作的函数,这里介绍的是一些在Linux平台上应用的文件操作函数.由于Linux是C写的,低层的libc库和系统调用的接口都是C AP ...