进化内核模糊测试

自从 2014 年开始的高性能 tracing 和 fuzzing

  • 2014 - High Performance Fuzzing
    • 样本选择、Engine 设计、AFL-DYNINST、Windows fork()
  • 2015 - Go Speed Tracer
    • Guided Fuzzing、二进制翻译、硬件 Tracing
  • 2016 - Harnessing Intel Processor Trace for Vulnerability Discovery
    • Intel Processor Trace
    • 使用 Intel PT 用户模式模糊测试
    • 原生 Windows 程序的持久模糊测试模式
    • 开源了 Windows 上 Intel Processor Trace 的驱动 https://github.com/intelpt

介绍

  • 内核是关键攻击面
  • 现代缓解措施利用隔离和沙盒
  • 武器化的 Exploits 也包含了内核攻击
    • Pwn2own
    • 泄露的政府 warez
  • 内核的 Vulndev 仍处于初级阶段

应用程序沙盒

IE 沙盒、IE Protected 模式、Chrome 沙盒、Adobe Reader 沙盒

Windows 隔离/沙盒

驱动签名验证、Patchguard / Kernel Patch Protection、App Containers、ProcessMitigationPolicy

Evolutionary Fuzzing

  • 2006: Sidewinder – Sparks & Cunningham
  • 2007: Evolutionary Fuzzing System – Jared Demott
  • 2007: Bunny the Fuzzer – Michal Zalewski
  • 2013: American Fuzzy Lop – Michal Zalewski
  • 2014: Nightmare/BCCF – Joxean Koret
  • 2015: Honggfuzz – Robert Swiecki
  • 2015: covFuzz – Atte Kettunen
  • 2016 : Choronzon – Zisis Sialveras / Nikos Naziridis

在 Fuzzing 期间 trace 并提供反馈,Evolutionary 算法:

  • 评估当前输入样本的适应度
  • 管理可能的样本池

Evolutionary Fuzzing 的要求

  • 快速 tracing 引擎,基本块粒度的代码覆盖度
  • 快速日志,内存驻留覆盖度 map,并非每个基本块的列表
  • 快速进化算法,最小化全局 population map、最大化池多样性

AFL 提供了完整的软件包

  • 传统畸变策略的多样性
  • 通过编译时插桩检测块覆盖
  • 简化的遗传算法
    • 边覆盖被编码为元组(包括覆盖度和频率),在布隆过滤器中进行跟踪
  • 使用 portable Posix API 来进行共享内存、进程创建

其贡献:

  • 跟踪边覆盖度、全局覆盖度map、fork server(减少目标初始化)、持久化 Fuzzing、构建可在其他工作流中重用的唯一输入样本语料库

Trace Logging

  • 每个块分配一个 Unique ID
  • 每个边都是 byte map 的索引(使用 bloom filter)
  • 使用源基本块到目的基本块的ID计算哈希值
  • 每次转换的边增量 map
  • 每个 trace 很容易与整个 session 历史进行比较

WinAFL

  • Ivan Fratric - 2016
  • 内存和进程的创建都使用 Windows API
  • 代码覆盖度基于 DynamoRIO
  • 基于 module 进行过滤
  • 块和边 tracing 模式
  • 持久执行模式

WinAFL - IntelPT

  • Richard Johnson - 2016
  • 第一个硬件辅助的 Windows 指导型 Fuzzer
  • 第一个公开的用于 Windows 内核的指导型 Fuzzer

特性

  • 基于 Intel PT 的代码覆盖度引擎
  • 为解码 Intel PT trace 的在线反汇编引擎
  • 基于 module 的过滤器
  • 边跟踪模式
  • 持久执行模式
  • 内核跟踪模式

内核代码覆盖度

  • 内核代码覆盖度很难获得
  • 开源代码可以被编译器插桩
  • 二进制代码必须使用运行时插桩、静态重写或硬件引擎

已有工具与方法

源码级

  • GCC
    • gcc –coverage
    • AFL 为 .s 中间文件添加了 hook
  • Clang
    • Clang -fprofile-instr-generate -fcoverage-mapping
    • afl-clang-fast 使用编译器 pass

二进制级

  • QEMU
    • Hook Tiny Code Generator(TCG)、翻译中间语言到 Native ISA
  • BOCHS
    • Work for j00ru
  • syzygy
    • 使用 AFL 静态重写 PE32 二进制程序
    • 要求 symbols
    • 要求额外的 dev 来让 WinAFL 内核感知

Intel / AMD CPUs - Branch Trace Store

  • 每个内核线程的硬件 trace
  • 和 Last Branch Record 联合起来得到边覆盖度(edge transition)
  • 某些 Hypervisor 支持直连

进化内核模糊测试

最近发布用于 Windows BTS 的开源软件 https://github.com/marcusbotacin/BranchMonitoringProject

Intel Processor Trace 在 Broadwell / Skylake 引入

进化内核模糊测试

优势

  • 极低的性能开销(15%的 CPU perf hit 用于记录)
  • 日志直接送至物理内存,绕过 TLB 并且 eliminate 了 cache 污染
  • 最小日志格式
    • 每个条件分支 1bit
    • 间接分支只记录目的地址
  • 解码 trace 需要额外的开销,需要定制 disassebly

深入了解请看 Harnessing Intel Processor Trace for Vuln Discovery

稀疏二进制包格式(sparse binary packet format)
进化内核模糊测试

复杂格式:使用 Intel 开源的 libipt 库解码

WindowsPtDriver 用于为 Windows 提供 Intel Processor Trace 的支持
PtCov Intel Processor Trace Library 为内核态驱动交互提供用户态 API,便于将任一文件 Fuzzer 转换为覆盖度驱动的 Fuzzer

PtCov Intel Processor Trace Library
进化内核模糊测试
进化内核模糊测试
进化内核模糊测试

其他方法

  • Single step / branch step (BTF)
    • 每条指令到 singlestep 都启用了 int 0x1
    • 只在分支处中断 dbgctrl msr flag
  • PMU Sampling
    • 在每个分支强制中断
    • 异步但是很慢
    • 任何架构都能运行(包括 ARM)
  • Dynamic binary translation(动态二进制翻译)
    • 尝试为驱动运行 Pin

Linux Kernel Fuzzing

  • Trinity(https://github.com/kernelslacker/trinity
    • 为 Linux 内核树构建
    • 通过 templates 实现类型感知
    • 没有覆盖度驱动
  • ”Jones has considered feedback-guided fuzzing for Trinity in the past, but found the coverage tools that were available at the time to be too slow.”

Syzkaller- 2016

  • 覆盖度驱动的系统调用 Fuzzing
    • 使用 ASAN 代码覆盖度的 GCC port 构建
    • gcc -fsanitize-coverage=trace-pc
  • 通过 /sys/kernel/debug/kcov 公开代码覆盖度
  • 模版驱动的系统调用 fuzzing
  • 严重依赖 KASAN 来捕获错误
  • 进化内核模糊测试

优劣

  • 良好的工具支持
  • 监控的 WebUI
  • 良好的日志
  • Repro(重写)最小化
    进化内核模糊测试

缺点是工作流复杂、配置复杂,不容易重定向

TriforceAFL - 2016

  • 基于 QEMU 做代码覆盖度跟踪的 AFL
  • 为 QEMU post-boot 添加 fork server
  • 为 API 添加序列化技术
    • 允许像 fuzzing 一个文件格式一样 fuzz API
  • 扩展了 QEMU trace 在 AFL 中的支持以用于内核
  • 为了性能考虑,在 boot 后 COW QEMU 中的 fork()
  • 使用自定义的 hypercalls 来扩展本地 ISA(aflcall)
    • Startforkserver、getwork、startwork、endwork
  • 使用系统调用 templates / shapes
  • 序列化系统调用为文件,使用 AFL 进行 fuzzing
  • 支持系统调用序列 进化内核模糊测试

Windows Kernel Fuzzing

内核攻击面包括任何不可信的输入

  • 用户态:系统调用、文件解析、软件中断
  • 设备:网络、USB、Firewire

两大类:结构化的输入或者 API

系统调用

  • Ntoskrnl.sys
    • Windows 系统服务
    • 约 465 系统调用
  • Win32k.sys
    • 内核态图形显示接口支持
    • 约 1216 系统调用
  • Win32k.sys 文件解析
    • 字体:TTF、OTF、FON
    • 图片:BMP、JPEG、CUR、ANI、ICO
    • 元文件:EMF、WMF
  • 其他攻击面
    • 图形驱动、音频驱动、网络驱动、打印驱动

遗产

  • Ioctlfuzzer – Dimitry Oleksander (cr4sh)
  • Misc Syscall fuzzers
  • Misc file format fuzzers

技术

  • 随机系统调用参数或 ioctl 输入
  • Hook 与中断(ioctlfuzzer)
  • Dumb 或结构化文件 fuzzing

KernelFuzzer - 2016

Windows 系统 API Fuzzer

  • API 类型感知是有效的
  • 每个类型的生成器可以手动定义,但这太繁琐
  • Pre-generated HANDLE tables
  • 输出每个测试用例的 C 代码用于在崩溃后重现
  • 可以从 TriforceAFL 风格的 API 序列生成中受益

Windows Graphics Driver Fuzzing

  • Windows 图形层次结构
    • Gdi32.dll -> Dxgkrnl.sys -> HW driver
  • 感兴趣的 Direct3D 函数
    • D3DKMTEscape、D3DKMTRender、D3DKMTCreateAllocation、D3DKMTCreateContext
    • 进化内核模糊测试
  • 内部图形函数的入口点
    • 每个驱动程序实现专有格式的 *pData(几个头字段与命令数据)
    • 是进化型文件格式 fuzzing 的完美目标
  • 查找 D3DKMTEscape 的用法
    • 进化内核模糊测试
    • 进化内核模糊测试
    • 进化内核模糊测试
  • Intel HD Graphics Driver - igdkmd64.sys
    • 7.5MB 的图形驱动
  • NVIDIA Graphics Driver – nvlddmkm.sys
    • 800 图形处理函数

结论

  • 内核暴露出了大量的攻击面
  • 硬件 tracing 让代码覆盖率收集变得容易
  • 代码在 https://github.com/intelpt