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. OpenCV---Canny边缘提取

    一:Canny算法介绍 Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是: 好的检测- 算法能够尽可能多地标识出图像中的实际边缘. 好的定位- 标识出的边缘要尽可能与实际图像中的实 ...

  2. Android Studio获取调试版SHA1和发布版SHA1的方法

    前言: 当我们在集成高德地图定位功能到项目中的时候,需要用到发布版和调试版的安全码SHA1,所以今天我就来总结一下分别在Windows和Mac下是怎么来获取SHA1的,希望对大家有所帮助. 首先,统一 ...

  3. JS中的new操作符原理解析

    var Person = function(name){ this.name = name; } Person.prototype.sayHello = function() { console.lo ...

  4. easyui 更改dialog弹出的位置

    方法一: 在弹出dialog的时候不用$('#dialogDiv').dialog('open');打开.用$('#dialogDiv').window('open');打开.再用window的res ...

  5. 【Hadoop】用web查看hadoop运行状态

    博文已转移,请借一步说话.http://www.daniubiji.cn/archives/621 上一篇文章(去博客园),我们安装完hadoop,下面我们从视觉上看看hadoop怎么玩的. 我们可以 ...

  6. session_write_close()的作用

    简单地说,当开启session_start以后,这个session会一直开启,并且被一个用户使用.其他用户开启session的话要等待第一个session用户关闭以后才可以开启sessio,这样就造成 ...

  7. arguments.length

    本文地址:http://www.cnblogs.com/veinyin/p/7607083.html  arguments.length是实参的个数,与形参个数无关.

  8. phpStudy 虚拟主机

    转载:http://blog.csdn.net/sinat_35861664/article/details/53557574 windows下配置虚拟主机,实现多域名访问本地项目目录 1.Apach ...

  9. 记一次powershell反混淆(2)

    样本地址 https://www.hybrid-analysis.com/sample/4b4b8b13c264c8f7d7034060e0e4818a573bebc576a94d7b13b4c174 ...

  10. Perl6多线程2: Promise new/keep/bread/status/result

    来源于个人理解的翻译. 创建一个 promise: my $p = Promise.new; 可以打印运行 的Promise 状态: my $p = Promise.new(); $p.then({s ...