IOT Fuzz 两种思路

代码和测试用例

基于Qiling框架和afl++进行跨平台二进制Fuzz

Qiling框架

https://docs.qiling.io/en/latest/
https://github.com/qilingframework/qiling

Qiling是一个基于Unicorn后端的高层次的二进制模拟框架,它有如下特性

跨平台: Windows,MacOS,Linux,BSD,UEFI,DOS
跨架构: X86,X86_64,ARM,ARM64,MIPS,8086
多种文件格式: PE,MachO,ELF,COM
支持Linux内核模块,Windows驱动,MacOS内核
在独立的环境中模拟,沙盒化机器代码
支持跨平台,跨架构的调试功能
提供高层次的API用于设置沙盒
允许多个不同层次的Hook(指令级,基本块级,内存访问级,错误处理,系统调用,IO,等等)
允许动态打包的文件
基于Python

Qiling 比较 Unicorn 的优势

Unicorn只是一个纯粹的cpu模拟器,只专注于考虑理解模拟器的虚拟内存,在内存空间之上的
高级别上下文,类似动态库,系统调用,I/O处理,或其他可执行格式像PE,Mach0或者ELF,它
都不关心,没有操作系统相关的上下文。

Qiling是在高层次上设计的框架,不仅可以发挥Unicorn模拟CPU指令的能力,还能理解操作系统,
和许多可执行文件格式,甚至动态链接,所以Qiling在不需要原生操作系统的层面上,执行二进制
文件。

比方说平常要用unicorn模拟一个.so文件,可能还需要考虑好内存映射的问题,手动把.so按照
Linux的ELF的解析方式映射到unicorn的内存中.Qiling就把这个过程简单化了,它能够按照
文件格式正确映射可执行文件。这在配合IDA等软件做分析时很方便。

尽管可能想要一个框架一把梭,自动化把所有平台都模拟起来不太现实,毕竟IOT这块还有许多硬件
特定相关的API。但是通过qiling至少已经能把起步的一些轮子问题解决了,剩下就能专注去处理
一些硬件特定问题也方便。

基于Qiling做二进制fuzz

Fuzz是目前自动化测试比较流行的方法,白盒的Fuzz可以直接用一些现成的框架做测试。但是正对二进制
的Fuzz,尤其是跨平台的,操作起来还比较麻烦,目前常见的有afl-unicorn,afl-qemu,libfuzzer等。

在跨平台上,afl-qemu效果比较差,定制起来比较麻烦,afl-unicorn虽然定制化程度比较高,但也是有前面
提到的一些基本的轮子问题,要手动解决,做这项工作就会花很长时间。

Qiling的fuzz是基于afl-unicorn工作的,解决Unicorn在前期harness工作上繁琐的问题,又有Unicorn高定制化能力,
基于Qiling做二进制Fuzz的harness很好写,下面给出一个例子。

#include<stdio.h>
#include<stdlib.h>#define SIZE 10int main(){char buf[SIZE] = {0};char tmp = 0;int idx = 0 ;buf[idx] = getc(stdin);if(buf[idx]=='A'){puts("OK");}else if(buf[idx]=='E'){tmp = getc(stdin);while(tmp=='v' || tmp == 'G' || tmp == '3'){buf[idx++] = tmp;tmp = getc(stdin);}buf[idx] = '\x00';puts(buf);puts("PUTS");}else if(buf[idx]=='x'){exit(0);}return 0;}

这段C语言代码有几个分支,其中一个存在栈溢出

比如当输入Evvvvvvvvvvvvvvvvvvvvvvvvv,超过缓冲区容量就产生了溢出

这段代码默认在x64上编译好后,有完整的保护权限,现在我们可以用Qiling
编写一个harness,同时用afl-unicorn运行它。

import unicornaflunicornafl.monkeypatch()import os
import sysfrom qiling import *class FuzzStdin:def __init__(self):self.buf = b''def write(self,s):self.buf += sdef read(self,l):if l <= len(self.buf):ret = self.buf[:l]self.buf = self.buf[1:]else:ret = self.bufself.buf = ''return retdef fileno(self):return 0def show(self):passdef clear(self):passdef flush(self):passdef close(self):self.outpipe.close()def lseek(self,a,b):passdef getBuf(self):return self.bufdef main(inputFile):stdin = FuzzStdin()stdout = FuzzStdin()ql = Qiling(["./fuzz"],"../rootfs/x8664_linux",stdin=stdin,stdout=None,stderr=None)base = int(ql.profile.get('OS64','load_address'),16)# 更具IDA确定main函数地址偏移main_addr = base + 0x11A9ret_addr = base + 0x12C4def stack_chk_fail(*args):os.abort()#劫持stack_chk_fail,默认gcc出现栈溢出会调用这个函数退出,劫持他,用os.abort向afl汇报一个崩溃ql.set_api('__stack_chk_fail',stack_chk_fail)#应为这个二进制文件全保护先启动一部分初始化代码,把动态地址绑定好try:ql.run(end=main_addr)except Exception as e:print(e)os.abort()#把stdin换成我们的文件输入内容def start_afl(_ql):#fork afl serverstatus = _ql.uc.afl_forkserver_start(exits=[0])if status == unicornafl.UC_AFL_RET_FINISHED:exit(0)fd = open(inputFile,"rb")stdin.write(fd.read())ql.hook_address(callback=start_afl,address=main_addr)#这里是需要fuzz的部分,从main函数开始try:ql.run(begin=main_addr,end=0)except Exception as e:print(e)os.abort()if __name__ == "__main__":if len(sys.argv) == 1:raise ValueError("No input file provided")main(sys.argv[1])

给好种子文件

使用afl-unicorn做fuzz

afl-fuzz -m none -i fuzz_inputs -o fuzz_outputs -U python3 harness.py @@

给的种子是A,他是第一个分支的,在docker下跑了11min,出了第一个crash,
给出更好的语料库,fuzz效果会更好。

基于BooFuzz做网络协议黑盒Fuzz

BooFuzz框架

https://boofuzz.readthedocs.io/en/stable/user/quickstart.html
https://github.com/jtpereyda/boofuzz

Boofuzz是久经世故的Sulley Fuzz的分支和继承者。除了大量的错误修复,boofuzz的目标是可扩展性。目标是:Fuzz一切。

基于BooFuzz做Ftp服务Fuzz

BooFuzz是基于状态和数据块变异的Fuzz,稍微阅读了源码,手册,个人感觉BooFuzz有些方面可能不像我们直观想象的那样,首先对于每个请求,他不是组合各个变异的字段,而是把每个你定义的变异字段按顺序试一遍,对于请求的状态图,他也不会把定义的请求路径前后顺序的变异结合起来,只是单纯的Fuzz每个路径上的节点。

不过就单从对各个字段的Fuzz出发,BooFuzz还是可以做的不错的,下面给出一个Fuzz ftp服务的例子

from boofuzz import *
import time//可以定义一个数据变异生成器
class Path(Fuzzable):def __init__(self,*kargs,**kwargs):super(Path,self).__init__(*kargs,**kwargs)def mutations(self,default_value):s = b'a'for i in range(20):yield ss += b'a'*20session = Session(target=Target(connection=TCPSocketConnection("127.0.0.1", 21)))def def_proto(session):user = Request("lv1",children=(String(name="key", default_value="USER",fuzzable=False),Delim(name="space", default_value=" ",fuzzable=False),Static(name="val", default_value="anonymous"),Static(name="end", default_value="\r\n"),))pwd = Request("pwd",children=(Static(name="pass", default_value="PASS"),Static(name="space", default_value=" "),Static(name="val", default_value="anonymous"),Static(name="end", default_value="\r\n"),))cwd = Request("cwd",children=(Static(name="cpath", default_value="CWD"),Static(name="space", default_value=" "),Path(name="path",default_value="a"),Static(name="end", default_value="\r\n"),))session.connect(user)session.connect(user,pwd)session.connect(pwd,cwd)return user,pwd,cwduser,pwd,cwd = def_proto(session)time.sleep(5)session.fuzz()

跑到第17个出现crash,但是第17个已经没响应了,看看第16个发了啥

CWD指令 307 Bytes 大小参数时 crash,可以用OllyDbg或其他调试器定位一下,实际上是个栈溢出

IOT Fuzz 两种思路相关推荐

  1. 第七篇:使用 CUDA 进行计算优化的两种思路

    前言 本文讨论如何使用 CUDA 对代码进行并行优化,并给出不同并行思路对均值滤波的实现. 并行优化的两种思路 思路1: global 函数 在 global 函数中创建出多个块多个线程对矩阵每个元素 ...

  2. 利用网络信息减少因果推断中的confounding bias--结合两种思路的新方法

    点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 本期AI TIME PhD专场,我们有幸邀请到了来自亚利桑那州立大学的博士生郭若城,为我们带来他的精彩分享--利用网络信息减少因果推断中 ...

  3. 解析word:doc,docx的两种思路

    两种思路: 用相应的库直接读取文件 doc转换成docx python在windows与linux下读取doc文件 https://blog.csdn.net/qq_33447950/article/ ...

  4. 两种思路将Python中两个有序数组合并为一个有序数组

    第一种思路: 把两个数组合为一个数组然后再排序,问题又回归到冒泡和快排了,没有用到两个数组的有序性. 第二种思路: 循环比较两个有序数组头位元素的大小,并把头元素放到新数组中,从老数组中删掉,直到其中 ...

  5. Netstars CTO 陈斌:技术管理的两种思路

    陈斌 NETSTARS CTO 读完需要 5 分钟 速读仅需 1 分钟 陈斌 NETSTARS CTO, 翻译的图书<架构即未来><架构真经><数据即未来>< ...

  6. WebGIS中解决使用Lucene进行兴趣点搜索排序的两种思路

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 目前跟信息采集相关的一个项目提出了这样的一个需求:中国银行等 ...

  7. 奥比中光深度摄像头_乐视三合一奥比中光Orbbec Astra Pro在ROS中配置显示RGB、深度、IR图像的两种思路...

    乐视的电视机摄像头带有深度信息,可用于体感识别.视觉SLAM.点云地图构建.三维重建等应用.但是刚开始无法显示RGB彩色图像,最后解决的过程发现有两种方法可以实现,一种是基于OpenNI的,另一种是基 ...

  8. 链表反转的两种思路及算法

    这样的思路用代码实现主要是有四行(具体内容懒得写了,作为一只摸鱼王),核心四行在就可 //做一个自定义函数,如link *turnlink,加一个for循环,进行如下四行 lm->next=lm ...

  9. qt实现窗口拖动的两种思路

    提要 窗口按下鼠标不放拖动窗口移动,鼠标释放的时候,停止拖动.这个过程可以用两种方法来实现. 1.鼠标点击后,获取鼠标按下点的坐标和起初窗口左上角的坐标,用鼠标按下点的坐标减去鼠标左上角的坐标,求出这 ...

最新文章

  1. 第八章 异常控制流 笔记
  2. C++类的案例(一)
  3. 二叉树非递归先序遍历
  4. 设计模式(六)命令模式
  5. wxWidgets:wxMemoryOutputStream类用法
  6. OSChina 周三乱弹 —— 爸爸说,这个是从他硬盘里掉出来的
  7. 修改表名的sql语句_SQL第一关——入门
  8. StackPanel
  9. 高德地图根据经纬度生成位置定位图片(发送位置)
  10. matlab学习---矩阵求最大值,赋值
  11. IOS 应用安全测试内容
  12. HDLBits刷题Day6
  13. 青蛙跳石头java_青蛙跳台阶(JAVA)与递归问题探究
  14. 全网清晰虚拟机安装截图
  15. 前端--HTML入门
  16. WebQQ协议分析(1)——登录
  17. 4、福尔摩斯到某古堡探险
  18. feasycom蓝牙对接Android,2.4G低功耗蓝牙解决方案
  19. 高抛低吸,谁都知道,为什么还亏钱?
  20. 数字化转型之数字化和业务化论证

热门文章

  1. 【笔记】vs2015 使用GIT的时候 “Could not open '***.VC.opendb'”
  2. 云服务之第一课云计算概述
  3. springboot大学生拼车管理系统 毕业设计-附源码201507
  4. 迅雷看看的带宽限制 是不能限制 还是不想限制?
  5. Excel操作之获取数据——从Excel导入CSV文件数据
  6. vue中使用echarts绘制仪表盘
  7. 原创漫画|区块链能干啥?一张图看懂区块链落地应用
  8. 「Android」 APK瘦身探索
  9. 如何自己主动进行Win11系统升级安装教学
  10. Unity 之 NGUI UIRoot 的屏幕适配问题