driller部分代码只是读取输入种子然后返回一个可用的新种子,实际fuzz的时候还是需要搭配fuzzer使用:https://github.com/shellphish/fuzzer

不过,fuzzer中不是直接使用Driller类,而是LocalCallback类,因此有必要看看这一部分是如何实现的。

fuzzer的shellphuzz脚本相关代码:

    if args.grease_with:print ("[*] Greasing...")grease_extension = fuzzer.GreaseCallback(args.grease_with,grease_filter=helper_module.grease_filter if helper_module is not None else None,grease_sorter=helper_module.grease_sorter if helper_module is not None else None)if args.driller_workers:print ("[*] Drilling...")drill_extension = driller.LocalCallback(num_workers=args.driller_workers, worker_timeout=args.driller_timeout, length_extension=args.length_extension)stuck_callback = ((lambda f: (grease_extension(f), drill_extension(f))) if drill_extension and grease_extensionelse drill_extension or grease_extension)

由于后面fuzzer里对stuck_callback是直接调用的

    def _timer_callback(self):if self._stuck_callback is not None:# check if afl has pending fav'sif ('fuzzer-master' in self.stats and 'pending_favs' in self.stats['fuzzer-master'] and \int(self.stats['fuzzer-master']['pending_favs']) == 0) or self.force_interval is not None:self._stuck_callback(self)

所以重点看Driller类的__call__方法,即driller_callback函数

    def driller_callback(self, fuzz):l.warning("Driller stuck callback triggered!")# remove any workers that aren't runningself._running_workers = [x for x in self._running_workers if x.is_alive()]# get the files in queuequeue = self._queue_files(fuzz)#for i in range(1, fuzz.fuzz_id):#    fname = "fuzzer-%d" % i#    queue.extend(self.queue_files(fname))# start drillingnot_drilled = set(queue) - self._already_drilled_inputsif len(not_drilled) == 0:l.warning("no inputs left to drill")while len(self._running_workers) < self._num_workers and len(not_drilled) > 0:to_drill_path = list(not_drilled)[0]not_drilled.remove(to_drill_path)self._already_drilled_inputs.add(to_drill_path)proc = multiprocessing.Process(target=_run_drill, args=(self, fuzz, to_drill_path),kwargs={'length_extension': self._length_extension})proc.start()self._running_workers.append(proc)__call__ = driller_callback

这个函数大致是把afl fuzz时的queue文件夹内的种子依次取出用来作为Driller的输入,然后创建子进程执行,子进程的命令类似这个:

timeout -k 610 600 /home/waterfire/.virtualenvs/angr/bin/python3.6 /home/waterfire/.virtualenvs/angr/lib/python3.6/site-packages/driller/local_callback.py /home/waterfire/fuzz/example/test /dev/shm/work/test/sync /dev/shm/work/test/sync/fuzzer-master/fuzz_bitmap /dev/shm/work/test/sync/fuzzer-master/queue/id:000002,sync:driller,src:000007,+cov --length-extension 10

即用timeout执行后面的命令600秒,如果到了还没执行完就在610秒杀死,后面就是执行local_callback.py以及其参数,依次为目标二进制、工作目录、fuzz的bitmap路径、fuzz的队列中的输入样例。

接下来看local_callback.py的执行部分:

if __name__ == "__main__":parser = argparse.ArgumentParser(description="Driller local callback")parser.add_argument('binary_path')parser.add_argument('fuzzer_out_dir')parser.add_argument('bitmap_path')parser.add_argument('path_to_input_to_drill')parser.add_argument('--length-extension', help="Try extending inputs to driller by this many bytes", type=int)args = parser.parse_args()logcfg_file = os.path.join(os.getcwd(), '.driller.ini')if os.path.isfile(logcfg_file):logging.config.fileConfig(logcfg_file)binary_path, fuzzer_out_dir, bitmap_path, path_to_input_to_drill = sys.argv[1:5]fuzzer_bitmap = open(args.bitmap_path, "rb").read()# create a folderdriller_dir = os.path.join(args.fuzzer_out_dir, "driller")driller_queue_dir = os.path.join(driller_dir, "queue")try: os.mkdir(driller_dir)except OSError: passtry: os.mkdir(driller_queue_dir)except OSError: passl.debug('drilling %s', path_to_input_to_drill)# get the inputinputs_to_drill = [open(args.path_to_input_to_drill, "rb").read()]if args.length_extension:inputs_to_drill.append(inputs_to_drill[0] + b'\0' * args.length_extension)for input_to_drill in inputs_to_drill:d = driller.Driller(args.binary_path, input_to_drill, fuzzer_bitmap)count = 0for new_input in d.drill_generator():id_num = len(os.listdir(driller_queue_dir))fuzzer_from = args.path_to_input_to_drill.split("sync/")[1].split("/")[0] + args.path_to_input_to_drill.split("id:")[1].split(",")[0]filepath = "id:" + ("%d" % id_num).rjust(6, "0") + ",from:" + fuzzer_fromfilepath = os.path.join(driller_queue_dir, filepath)with open(filepath, "wb") as f:f.write(new_input[1])count += 1l.warning("found %d new inputs", count)

其中inputs_to_drill是种子的队列,默认只有参数传递的fuzz种子,如果设置了length_extension参数就会扩展之后加入inputs_to_drill,然后对每个种子通过Driller类的drill_generator方法生成新种子,这个方法最后还是会用到前一篇讲的_drill_input。

现在,我更想关注的是driller与fuzz交互的部分,即driller如何获取已fuzz的路径以及如何将新的种子传递给fuzz。

首先,从上面代码可以看到生成新种子后,直接在queue里创建新文件写入种子即可。

其次,已fuzz的路径应该是通过fuzz_bitmap传递,上一篇里可以看到fuzz_bitmap会作为参数传递给angr.exploration_techniques.DrillerCore

self._core = angr.exploration_techniques.DrillerCore(trace=r.trace, fuzz_bitmap=self.fuzz_bitmap)

DrillerCore类中最重要的是step方法

   def step(self, simgr, stash='active', **kwargs):simgr.step(stash=stash, **kwargs)# Mimic AFL's indexing scheme.if 'missed' in simgr.stashes and simgr.missed:# A bit ugly, might be replaced by tracer.predecessors[-1] or crash_monitor.last_state.prev_addr = simgr.one_missed.history.bbl_addrs[-1]prev_loc = prev_addrprev_loc = (prev_loc >> 4) ^ (prev_loc << 8)prev_loc &= len(self.fuzz_bitmap) - 1prev_loc = prev_loc >> 1for state in simgr.missed:cur_loc = state.addrcur_loc = (cur_loc >> 4) ^ (cur_loc << 8)cur_loc &= len(self.fuzz_bitmap) - 1hit = bool(self.fuzz_bitmap[cur_loc ^ prev_loc] ^ 0xff)transition = (prev_addr, state.addr)mapped_to = self.project.loader.find_object_containing(state.addr).binaryl.debug("Found %#x -> %#x transition.", transition[0], transition[1])if not hit and transition not in self.encounters and not self._has_false(state) and mapped_to != 'cle##externs':state.preconstrainer.remove_preconstraints()if state.satisfiable():# A completely new state transition.l.debug("Found a completely new transition, putting into 'diverted' stash.")simgr.stashes['diverted'].append(state)self.encounters.add(transition)else:l.debug("State at %#x is not satisfiable.", transition[1])elif self._has_false(state):l.debug("State at %#x is not satisfiable even remove preconstraints.", transition[1])else:l.debug("%#x -> %#x transition has already been encountered.", transition[0], transition[1])return simgr

prev_loc和cur_loc分别将执行step前后的两个地址后20bit映射到了2字节,然后把它们异或的值作为fuzz_bitmap的索引,并通过fuzz_bitmap对应的值是否为0xff来判断该路径是否被执行过。如果未被执行过就会求解约束并当成功求解时添加结果。

Driller源码阅读笔记(二)相关推荐

  1. Driller源码阅读笔记(一)

    Driller源码:https://github.com/shellphish/driller 所给样例为: import drillerd = driller.Driller("./CAD ...

  2. werkzeug源码阅读笔记(二) 下

    wsgi.py----第二部分 pop_path_info()函数 先测试一下这个函数的作用: >>> from werkzeug.wsgi import pop_path_info ...

  3. ThreadPoolExecutor源码阅读笔记(二)FutureTask

    BlockingQueue: 队列他决定了任务的调度方式,我们主要关注BlockingQueue的offer, poll,take三个方法 offer往队列里面添加任务如果队列已经满了话返回false ...

  4. 源码阅读笔记 BiLSTM+CRF做NER任务 流程图

    源码阅读笔记 BiLSTM+CRF做NER任务(二) 源码地址:https://github.com/ZhixiuYe/NER-pytorch 本篇正式进入源码的阅读,按照流程顺序,一一解剖. 一.流 ...

  5. 代码分析:NASM源码阅读笔记

    NASM源码阅读笔记 NASM(Netwide Assembler)的使用文档和代码间的注释相当齐全,这给阅读源码 提供了很大的方便.按作者的说法,这是一个模块化的,可重用的x86汇编器, 而且能够被 ...

  6. libreCAD源码阅读笔记1

    libreCAD源码阅读笔记1 一 前言: 正如官网(https://www.librecad.org)所说,libreCAD是一个开源的CAD制图软件,可以运行在Windows.Apple.Linu ...

  7. Live555源码阅读笔记(一):源码介绍文档 及 源码目录结构

    目录 一.Live555介绍 1.Live555项目介绍 2.官网及帮助文档介绍 二.源码目录结构 1.UsageEnvironment 2.BasicUsageEnvironment 3.group ...

  8. dgl源码阅读笔记(3)——DeepWalk

    dgl源码阅读笔记(3)--DeepWalk 图神经网络开源库dgl阅读笔记 文章目录 dgl源码阅读笔记(3)--DeepWalk 图神经网络开源库dgl阅读笔记 @[TOC](文章目录) 前言 一 ...

  9. Transformers包tokenizer.encode()方法源码阅读笔记

    Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode

最新文章

  1. Python进阶之路 3.4.2 条件语句(if、else和elif)
  2. iis8 php mysql_windows2012下 iis8+php5.2+mysql5 配置
  3. Andoird自定义ViewGroup实现竖向引导界面
  4. DbEntry 访问Access2010数据库
  5. java 下载excel到本地_java已知下载链接将Excel文件利用httpclient下载到本地
  6. c语言课程设计实训主要目的,《C语言课程设计实验大纲.doc
  7. 2022PMP考试敏捷知识点(2)
  8. java 密码 星号显示_Java多线程 例子 cmd窗口下 实现输入密码星号显示
  9. 多目标应用:基于MOGWO的地铁隧道上方基坑工程优化设计(提供MATLAB代码)
  10. MySQL模糊查询like优化,再也用不着 like+% 了
  11. 浅谈面向对象的编程思想:如何优雅地把大象装进冰箱?
  12. Gherkin简单使用
  13. #金数据#微信小程序#微信小程序跳转金数据小程序并获取问卷信息
  14. 汪汪汪WDG--看门狗的作用
  15. 服务机器人“大战”进入下半场,竞争焦点变了
  16. 电子专业如何写毕业论文
  17. rust: 引用第三方库(Cargo.toml、Cargo.lock文件)
  18. 使用JAVA对接跨境贸易电子商务数据交换接口拼接xml
  19. 统一数据交换(UDX)
  20. 【电子刊物制作】名编辑电子杂志大师教程 | 设置多国语言浏览界面

热门文章

  1. 如何给老婆解释什么是Restful
  2. 人工智能个性化和逼真的漫画素描生成输入人脸图像创建漫画照片
  3. python3 yield
  4. 三菱伺服定长追剪,系统为Q172DSCPU,高级同步模式
  5. 微软MPP2.0 Microsoft Pen Protocol V2.0 officialEEAP.pdf
  6. 控制搜索引擎蜘蛛的爬行收录
  7. 到底如何保证线程安全,总结得太好了。。
  8. 第十四届蓝桥杯省赛C/C++研究生组试题及答案分享
  9. 用户选择好用的投票小程序最有用的投票小程序微信推送里投票制作教程
  10. fpga实操训练(从模块到系统开发)