Syzkaller内核模糊测试技术详解与实战
字数 4005 2025-11-21 12:59:47

Syzkaller内核模糊测试技术详解与实战

一、简介

Syzkaller是Google安全研究人员开发并维护的开源内核Fuzz工具,主要由dvyukov维护。该工具使用Go语言编写,包含少量C代码,具有部署快速、使用简便的特点,支持多种操作系统(Linux、Android、Windows、openbsd、darwin等),其中对Linux系统的支持最为全面。

内核通过系统调用进行交互,因此Syzkaller的Fuzzing通过不断构造系统调用序列来驱动内核执行。这些系统调用组合会触发内核中的各种逻辑路径,进而暴露潜在的安全漏洞。为了生成更高效的测试用例,Syzkaller通过内核插桩机制获取覆盖率反馈来引导Fuzzing过程。

二、基本架构

2.1 组件构成

Syzkaller主要分为两个核心组件:

syz-manager(主控模块)

  • 运行在宿主机上,每个虚拟机对应一个syz-manager启动的管理进程
  • 内置fuzzing核心逻辑(包括系统调用生成、变异、语料更新等)
  • 收集并记录覆盖率和崩溃信息
  • 提供Web UI展示统计信息

syz-executor(执行模块)

  • 运行于每个虚拟机内部
  • 接收syz-manager下发的系统调用程序(syscall sequence)
  • 启动临时子进程执行单一测试输入(一系列系统调用)
  • 收集KCOV覆盖率信息,反馈执行结果
  • 报告崩溃、挂起或异常状态
  • 以C++静态编译方式实现,进程间通过共享内存通信,保证简洁高效

2.2 工作流程

  1. syz-manager生成系统调用序列,封装成二进制文件
  2. 通过SSH将测试程序传输到目标虚拟机
  3. syz-executor接收程序,执行系统调用组合以触发内核不同代码路径
  4. 利用内核的KCOV插桩收集覆盖率信息,作为反馈引导Fuzz
  5. syz-manager监控虚拟机运行状态,遇内核panic自动重启虚拟机(借助虚拟机快照和watchdog机制)
  6. 崩溃和覆盖率数据被收集并持久化,便于后续分析和复现

三、环境配置

3.1 硬件要求

CPU虚拟化支持

egrep -wo 'vmx|svm' /proc/cpuinfo | sort | uniq
  • 输出vmx表示Intel CPU支持虚拟化
  • 输出svm表示AMD CPU支持虚拟化
  • 无输出需在BIOS中开启虚拟化功能(Intel VT-x或AMD-V)

内核KVM支持

sudo modprobe kvm
sudo modprobe kvm_intel  # Intel CPU
# 或
sudo modprobe kvm_amd    # AMD CPU

3.2 编译Syzkaller

安装Go编译器

# 下载Go 1.23.7
wget https://go.dev/dl/go1.23.7.linux-amd64.tar.gz

# 解压到/usr/local
sudo tar -C /usr/local -xzf go1.23.7.linux-amd64.tar.gz

# 设置环境变量
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$GOROOT/bin:$GOPATH/bin:$PATH

sudo apt install gcc

# 配置Go国内代理(可选)
export GOPROXY=https://goproxy.cn,direct

安装依赖

sudo apt update
sudo apt install build-essential clang llvm libncurses5-dev libssl-dev libelf-dev bc
sudo apt install make flex bison libncurses-dev libelf-dev libssl-dev

编译Syzkaller

git clone https://github.com/google/syzkaller
cd syzkaller
make all

# 交叉编译(如arm架构)
make CC=aarch64-linux-gnu-g++ TARGETARCH=arm64

编译完成后,执行文件位于syzkaller/bin/目录。

3.3 编译Linux内核

下载并配置内核(以6.12.38为例):

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.38.tar.xz
tar -xvf linux-6.12.38.tar.xz && cd linux-6.12.38

make defconfig
make kvm_guest.config

启用必要配置选项

scripts/config --enable CONFIG_KCOV           # 启用KCOV
scripts/config --enable CONFIG_KASAN          # 启用KASAN
scripts/config --enable CONFIG_KASAN_INLINE   # 允许内联检测代码
scripts/config --enable CONFIG_DEBUG_INFO
scripts/config --disable CONFIG_DEBUG_INFO_NONE
scripts/config --enable CONFIG_DEBUG_INFO_DWARF4  # 开启内核调试信息生成

# 网络相关配置
scripts/config --enable CONFIG_NET_SCHED
scripts/config --enable CONFIG_NET_CLS_ACT
scripts/config --enable CONFIG_NET_SCH_FQ
scripts/config --enable CONFIG_NET_SCH_NETEM
scripts/config --enable CONFIG_NET_SCH_INGRESS
scripts/config --enable CONFIG_NET_SCH_HTB
scripts/config --enable CONFIG_NET_SCH_PRIO

scripts/config --enable CONFIG_CONFIGFS_FS    # 启用configfs文件系统支持
scripts/config --enable CONFIG_SECURITYFS     # 启用securityfs文件系统
scripts/config --enable CONFIG_KCOV_JIT
scripts/config --enable CONFIG_DEBUG_KERNEL
scripts/config --enable CONFIG_LOCKDEP

重新生成配置并编译

make olddefconfig
make -j$(nproc)

编译后生成的关键文件:

  • bzImage:经过压缩的可启动内核镜像
  • vmlinux:带有调试符号的未压缩内核镜像

3.4 Qemu配置

安装Qemu

sudo apt install qemu-system-x86

创建虚拟机镜像

sudo apt install debootstrap
cd /linux

# 下载syzkaller的create-image.sh脚本
wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh
chmod +x create-image.sh

# 运行创建镜像脚本(Linux项目不能存在于挂载目录上)
./create-image.sh

脚本运行后生成的文件:

  • bullseye.img:虚拟机硬盘镜像文件
  • bullseye.id_rsa:SSH私钥
  • bullseye.id_rsa.pub:SSH公钥

启动虚拟机测试

qemu-system-x86_64 \
  -m 2G \
  -smp 2 \
  -kernel /linux/arch/x86/boot/bzImage \          # 指定bzImage文件
  -append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \
  -drive file=/linux/bullseye.img,format=raw \     # 指定文件系统
  -net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
  -net nic,model=e1000 \
  -enable-kvm \
  -nographic \
  -pidfile vm.pid \
  2>&1 | tee vm.log

测试SSH连接

ssh -i /linux/bullseye.id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost

四、基本用法

4.1 配置文件

创建Syzkaller配置文件test.cfg

{
  "target": "linux/amd64",           // 目标平台架构
  "http": "127.0.0.1:56741",         // WebUI接口
  "workdir": "/linux/workdir/",      // 工作目录
  "kernel_obj": "/linux/",           // 内核路径
  "image": "/linux/bullseye.img",    // QEMU虚拟机镜像
  "sshkey": "/linux/bullseye.id_rsa", // 连接虚拟机用的私钥
  "syzkaller": "/syzkaller/",        // syzkaller源码路径
  "procs": 8,                        // 每个VM中并发fuzz实例数量
  "type": "qemu",                    // 虚拟机类型
  "vm": {
    "count": 4,                      // 启动的VM数量
    "kernel": "/linux/arch/x86/boot/bzImage", // bzImage路径
    "cmdline": "net.ifnames=0",      // 内核参数(简化网络设备名)
    "cpu": 2,                        // 每个VM的CPU数量
    "mem": 2048                      // 每个VM的内存(单位:MB)
  }
}

4.2 启动运行

基本启动

syz-manager -config test.cfg

调试模式

syz-manager -config test.cfg --debug

启动后可通过http://localhost:56741访问WebUI界面。

4.3 KCOV覆盖率分析

Syzkaller使用KCOV接口收集代码覆盖信息,可通过以下地址查看覆盖率:

http://127.0.0.1:$(PORT)/cover

覆盖率颜色标注说明

  • 已覆盖:黑色
  • 部分覆盖:橙色
  • 函数未执行:暗红色
  • 未覆盖:红色
  • 未插桩:灰色

生成覆盖率报告

# 构建syz-cover工具
make cover

# 获取原始覆盖率数据
wget http://localhost:<syz-manager端口>/rawcover

# 生成覆盖率报告
bin/syz-cover --config <syzkaller配置文件路径> rawcover

# 导出函数覆盖率CSV文件
bin/syz-cover --config <syzkaller配置文件路径> --csv <输出文件名> rawcover

# 导出源码行覆盖率JSON文件
bin/syz-cover --config <syzkaller配置文件路径> --json <输出文件名> rawcover

五、Syzlang系统调用描述语言

Syzkaller定义了一套声明式语言syzlang,用于描述系统调用的接口和参数格式。

5.1 基本结构

syzlang文件包含以下元素:

| 元素 | 示例 | 说明 |
|------|------|------|
| include | include <linux/fs.h> | 引用头文件(仅标注) |
| syscall | open(file filename, flags flags[open_flags], mode flags[open_mode]) fd | 定义系统调用 |
| flags | open_flags = O_RDONLY, O_RDWR, O_CREAT | 枚举值集合 |
| bitmask | prot_flags = PROT_READ, PROT_WRITE | 按位或组合 |
| struct | sock_fprog { len len[filter, int16]; filter ptr[in, array[sock_filter]] } | 定义结构体 |
| union | union u [ type1, type2 ] | 定义联合体 |
| 别名 | type buffer ptr[in, array[int8]] | 类型模板/别名 |
| 注释 | # comment | 单行注释 |

示例

open(file filename, flags flags[open_flags], mode flags[open_mode]) fd
read(fd fd, buf buffer[out], count len[buf])
close(fd fd)

open_flags = O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, O_CREAT
open_mode = S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP

5.2 系统调用描述格式

基本格式

syscallname(argname1 type1, argname2 type2, ...) return_type

常用类型

  • intN / intptr:普通整数类型(带有可选范围、对齐)
  • flags[flagname]:枚举或位标志
  • ptr[in, type]:指针(方向可选in/out/inout)
  • array[type, size]:数组(长度可选固定/范围)
  • string[filename]:字符串(如生成文件路径)
  • len[fieldname] / bytesize[fieldname]:指定字段长度

类型模板与别名

type buffer[DIR] ptr[DIR, array[int8]]
type optional[T] [
  val T
  void void
] [varlen]

5.3 调用属性

可选关键字修饰系统调用行为:

  • no_generate:不自动生成调用(用于seed触发)
  • no_minimize:崩溃最小化时跳过该调用
  • ignore_return:不使用返回值作为反馈路径
  • timeout[N], prog_timeout[N]:增加fuzz超时时间
  • disabled:禁用该系统调用(调试时有用)

5.4 类型系统

基本类型

int8, int16, int32, int64
const[123, int32]  # 常量
bool8, bool32      # 布尔类型

指针类型

ptr[in, struct_name]  # 输入指针
ptr[out, buffer]      # 输出指针

数组

array[int32, 4]    # 固定长度数组
array[int8, VAR]   # 动态数组

联合体(Union)

union my_union [
  type1
  type2
  type3
]

结构体(Struct)

my_struct {
  field1 int32
  field2 ptr[in, buffer]
  ...
}

5.5 常量和标志

常量定义

define SOME_CONST 0x1000

标志定义

flags open_flags = O_RDONLY, O_WRONLY, O_CREAT, O_APPEND

位掩码

bitmask prot_flags = PROT_READ, PROT_WRITE, PROT_EXEC

5.6 资源类型

用于管理系统资源(如文件描述符、socket等):

resource fd[int32]: 0xffffffffffffffff, AT_FDCWD

open(...) fd
read(fd fd, ...)
close(fd fd)

5.7 高级特性

对齐约束

my_struct {
  field1 int32
  field2 ptr[in, buffer]
} [align[8]]

修饰符

  • [packed]:紧凑布局,取消默认padding
  • [varlen]:用于描述变长结构体或联合体的尾部

5.8 编写技巧

  1. 命名规范:遵循内核已有命名,不要创造新名字
  2. 资源顺序:in/out/inout决定调用顺序
  3. 特殊值:不要随意添加-1、INT_MAX等未声明值
  4. 标志使用:flag类型可用于枚举、位标志、混合模式
  5. 声明顺序:不要求先声明后使用,推荐按重要性排序

5.9 使用流程

  1. 调研接口,了解相关系统调用
  2. 编写描述文件并放入syzkaller/sys/linux目录
  3. 使用syz-extract和syz-gen生成Go描述代码

六、Headerparser工具

Headerparser是自动化生成syzlang描述的辅助工具,可减轻手动编写工作量。

环境配置

pip3 install pycparser

基本用法

python3 headerparser.py --filenames=./test_headers/th_b.h

输出结果示例:

B { 
  B1 len|fileoff|flags|intN #(unsigned long) 
  B2 len|fileoff|flags|intN #(unsigned long) 
} 

struct_containing_union { 
  something len|fileoff|flags|int32 #(int) 
  a_union.a_char ptr[in|out, string]|ptr[in, filename] #(char*) 
  a_union.B_ptr ptr|buffer|array #(struct B*) 
}

可直接复制Structure Metadata部分内容到syzkaller设备描述文件中。

七、实战案例

7.1 漏洞驱动示例

驱动代码(存在堆溢出漏洞):

#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>

#define MY_DEV_NAME "test"
#define DEBUG_FLAG "PROC_DEV"

static ssize_t proc_read(struct file *proc_file, char __user *proc_user, size_t n, loff_t *loff);
static ssize_t proc_write(struct file *proc_file, const char __user *proc_user, size_t n, loff_t *loff);
static int proc_open(struct inode *proc_inode, struct file *proc_file);

static const struct proc_ops proc_fops = {
  .proc_open = proc_open,
  .proc_read = proc_read,
  .proc_write = proc_write,
};

static int __init mod_init(void) {
  struct proc_dir_entry *test_entry;
  printk(DEBUG_FLAG ": proc init start!\n");
  test_entry = proc_create(MY_DEV_NAME, 0666, NULL, &proc_fops);
  if (!test_entry)
    printk(DEBUG_FLAG ": failed to create /proc entry!\n");
  else
    printk(DEBUG_FLAG ": proc init over!\n");
  return 0;
}

proc_write函数中,kmalloc分配了n+512字节缓冲区,但copy_from_user复制了n+4096字节,导致堆溢出。

7.2 编译进内核

# 将漏洞驱动文件复制到内核目录
mv test.c linux/drivers/char/

# 修改Makefile
echo "obj-y += test.o" >> linux/drivers/char/Makefile

# 编译内核
make -j$(nproc)

7.3 编写Syzlang描述

创建syzkaller/sys/linux/vuln.txt

include <linux/fs.h>

open$proc(file ptr[in, string["/proc/test"]], flags flags[proc_open_flags], mode flags[proc_open_mode]) fd
read$proc(fd fd, buf buffer[out], count len[buf])
write$proc(fd fd, buf buffer[in], count len[buf])
close$proc(fd fd)

proc_open_flags = O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, FASYNC, O_CLOEXEC, O_CREAT, O_DIRECT, O_DIRECTORY, O_EXCL, O_LARGEFILE, O_NOATIME, O_NOCTTY, O_NOFOLLOW, O_NONBLOCK, O_PATH, O_SYNC, O_TRUNC, __O_TMPFILE
proc_open_mode = S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH

生成常量文件

bin/syz-extract -os linux -sourcedir /root/linux-6.12.38 -arch amd64 vuln.txt

重新构建Syzkaller

# 将syscall描述文件转换为go代码结构
bin/syz-sysgen

# 重建syzkaller
make all

7.4 配置和运行Fuzzing

修改test.cfg,添加系统调用限制:

{
  // ... 其他配置不变
  "enable_syscalls": [
    "open$proc",
    "read$proc", 
    "write$proc",
    "close$proc"
  ]
}

开始Fuzzing

syz-manager -config test.cfg -vv 10

7.5 崩溃复现工具

syz-crush(重复执行崩溃程序):

# 构建工具
make crush

# 运行崩溃复现
mkdir workdir
bin/syz-crush -config ./test.cfg ./crashes/736f88e1c13700f40338df50cd9a6364a46963cf/repro.cprog

# 可选参数
bin/syz-crush -config ./test.cfg -debug -infinite=true -strace ./crashes/.../repro.cprog

syz-repro(生成可复现的测试用例):

bin/syz-repro -config=test.cfg ./crashes/736f88e1c13700f40338df50cd9a6364a46963cf/repro.prog

# 生成C语言复现程序
bin/syz-repro -config=test.cfg -crepro=repro.c ./crashes/.../repro.prog

八、崩溃分析

8.1 崩溃报告结构

Syzkaller为每种唯一的内核崩溃保存专属目录:

syzkaller_workdir/crashes/
├── 6e512290efa36515a7a27e53623304d20d1c3e/
│   ├── description     # 崩溃简短描述
│   ├── log0            # 原始内核日志及测试输入(第一次崩溃)
│   ├── report0         # 后处理符号化报告(第一次崩溃)
│   ├── log1            # 原始日志(重复崩溃)
│   ├── report1         # 后处理报告(重复崩溃)
│   ├── report.prog     # 复现crash的程序
│   └── report.cprog    # repro.prog的C可执行复现程序

8.2 特殊崩溃类型

| 崩溃类型 | 说明 |
|---------|------|
| no output from test machine | 测试机无任何输出,通常指内核死锁、严重挂起或崩溃 |
| lost connection to test machine | SSH连接中断,可能内核panic或网络故障导致 |
| test machine is not executing programs | 测试机看似在线,但长时间未执行测试程序,可能挂起或陷入死循环 |

九、总结

Syzkaller不仅是一个内核模糊测试工具,更是一种系统化、闭环化的内核安全研究框架。它通过精心设计的syzlang描述系统调用接口,结合覆盖率驱动(KCOV)和内存检测(KASAN/KCOV/UBSAN)形成反馈闭环,使模糊测试从随机尝试升级为"智能探索"。

关键优势:

  1. 自动化程度高:从测试用例生成到崩溃复现全流程自动化
  2. 反馈驱动:基于覆盖率指导测试方向,提高效率
  3. 系统化设计:完整的工具链和生态系统支持
  4. 多平台支持:支持多种操作系统和架构

这种方法论强调自动化、反馈驱动和系统化设计,让Fuzzing不再是盲目的尝试,而是有策略、有方向的漏洞探索,对内核安全研究具有深远的启发意义。

Syzkaller内核模糊测试技术详解与实战 一、简介 Syzkaller是Google安全研究人员开发并维护的开源内核Fuzz工具,主要由dvyukov维护。该工具使用Go语言编写,包含少量C代码,具有部署快速、使用简便的特点,支持多种操作系统(Linux、Android、Windows、openbsd、darwin等),其中对Linux系统的支持最为全面。 内核通过系统调用进行交互,因此Syzkaller的Fuzzing通过不断构造系统调用序列来驱动内核执行。这些系统调用组合会触发内核中的各种逻辑路径,进而暴露潜在的安全漏洞。为了生成更高效的测试用例,Syzkaller通过内核插桩机制获取覆盖率反馈来引导Fuzzing过程。 二、基本架构 2.1 组件构成 Syzkaller主要分为两个核心组件: syz-manager(主控模块) : 运行在宿主机上,每个虚拟机对应一个syz-manager启动的管理进程 内置fuzzing核心逻辑(包括系统调用生成、变异、语料更新等) 收集并记录覆盖率和崩溃信息 提供Web UI展示统计信息 syz-executor(执行模块) : 运行于每个虚拟机内部 接收syz-manager下发的系统调用程序(syscall sequence) 启动临时子进程执行单一测试输入(一系列系统调用) 收集KCOV覆盖率信息,反馈执行结果 报告崩溃、挂起或异常状态 以C++静态编译方式实现,进程间通过共享内存通信,保证简洁高效 2.2 工作流程 syz-manager生成系统调用序列,封装成二进制文件 通过SSH将测试程序传输到目标虚拟机 syz-executor接收程序,执行系统调用组合以触发内核不同代码路径 利用内核的KCOV插桩收集覆盖率信息,作为反馈引导Fuzz syz-manager监控虚拟机运行状态,遇内核panic自动重启虚拟机(借助虚拟机快照和watchdog机制) 崩溃和覆盖率数据被收集并持久化,便于后续分析和复现 三、环境配置 3.1 硬件要求 CPU虚拟化支持 : 输出 vmx 表示Intel CPU支持虚拟化 输出 svm 表示AMD CPU支持虚拟化 无输出需在BIOS中开启虚拟化功能(Intel VT-x或AMD-V) 内核KVM支持 : 3.2 编译Syzkaller 安装Go编译器 : 安装依赖 : 编译Syzkaller : 编译完成后,执行文件位于 syzkaller/bin/ 目录。 3.3 编译Linux内核 下载并配置内核 (以6.12.38为例): 启用必要配置选项 : 重新生成配置并编译 : 编译后生成的关键文件: bzImage :经过压缩的可启动内核镜像 vmlinux :带有调试符号的未压缩内核镜像 3.4 Qemu配置 安装Qemu : 创建虚拟机镜像 : 脚本运行后生成的文件: bullseye.img :虚拟机硬盘镜像文件 bullseye.id_rsa :SSH私钥 bullseye.id_rsa.pub :SSH公钥 启动虚拟机测试 : 测试SSH连接 : 四、基本用法 4.1 配置文件 创建Syzkaller配置文件 test.cfg : 4.2 启动运行 基本启动 : 调试模式 : 启动后可通过 http://localhost:56741 访问WebUI界面。 4.3 KCOV覆盖率分析 Syzkaller使用KCOV接口收集代码覆盖信息,可通过以下地址查看覆盖率: 覆盖率颜色标注说明 : 已覆盖:黑色 部分覆盖:橙色 函数未执行:暗红色 未覆盖:红色 未插桩:灰色 生成覆盖率报告 : 五、Syzlang系统调用描述语言 Syzkaller定义了一套声明式语言syzlang,用于描述系统调用的接口和参数格式。 5.1 基本结构 syzlang文件包含以下元素: | 元素 | 示例 | 说明 | |------|------|------| | include | include <linux/fs.h> | 引用头文件(仅标注) | | syscall | open(file filename, flags flags[open_flags], mode flags[open_mode]) fd | 定义系统调用 | | flags | open_flags = O_RDONLY, O_RDWR, O_CREAT | 枚举值集合 | | bitmask | prot_flags = PROT_READ, PROT_WRITE | 按位或组合 | | struct | sock_fprog { len len[filter, int16]; filter ptr[in, array[sock_filter]] } | 定义结构体 | | union | union u [ type1, type2 ] | 定义联合体 | | 别名 | type buffer ptr[in, array[int8]] | 类型模板/别名 | | 注释 | # comment | 单行注释 | 示例 : 5.2 系统调用描述格式 基本格式 : 常用类型 : intN / intptr :普通整数类型(带有可选范围、对齐) flags[flagname] :枚举或位标志 ptr[in, type] :指针(方向可选in/out/inout) array[type, size] :数组(长度可选固定/范围) string[filename] :字符串(如生成文件路径) len[fieldname] / bytesize[fieldname] :指定字段长度 类型模板与别名 : 5.3 调用属性 可选关键字修饰系统调用行为: no_generate :不自动生成调用(用于seed触发) no_minimize :崩溃最小化时跳过该调用 ignore_return :不使用返回值作为反馈路径 timeout[N] , prog_timeout[N] :增加fuzz超时时间 disabled :禁用该系统调用(调试时有用) 5.4 类型系统 基本类型 : 指针类型 : 数组 : 联合体(Union) : 结构体(Struct) : 5.5 常量和标志 常量定义 : 标志定义 : 位掩码 : 5.6 资源类型 用于管理系统资源(如文件描述符、socket等): 5.7 高级特性 对齐约束 : 修饰符 : [packed] :紧凑布局,取消默认padding [varlen] :用于描述变长结构体或联合体的尾部 5.8 编写技巧 命名规范 :遵循内核已有命名,不要创造新名字 资源顺序 :in/out/inout决定调用顺序 特殊值 :不要随意添加-1、INT_ MAX等未声明值 标志使用 :flag类型可用于枚举、位标志、混合模式 声明顺序 :不要求先声明后使用,推荐按重要性排序 5.9 使用流程 调研接口,了解相关系统调用 编写描述文件并放入 syzkaller/sys/linux 目录 使用syz-extract和syz-gen生成Go描述代码 六、Headerparser工具 Headerparser是自动化生成syzlang描述的辅助工具,可减轻手动编写工作量。 环境配置 : 基本用法 : 输出结果示例: 可直接复制Structure Metadata部分内容到syzkaller设备描述文件中。 七、实战案例 7.1 漏洞驱动示例 驱动代码 (存在堆溢出漏洞): 在 proc_write 函数中, kmalloc 分配了n+512字节缓冲区,但 copy_from_user 复制了n+4096字节,导致堆溢出。 7.2 编译进内核 7.3 编写Syzlang描述 创建 syzkaller/sys/linux/vuln.txt : 生成常量文件 : 重新构建Syzkaller : 7.4 配置和运行Fuzzing 修改 test.cfg ,添加系统调用限制: 开始Fuzzing : 7.5 崩溃复现工具 syz-crush (重复执行崩溃程序): syz-repro (生成可复现的测试用例): 八、崩溃分析 8.1 崩溃报告结构 Syzkaller为每种唯一的内核崩溃保存专属目录: 8.2 特殊崩溃类型 | 崩溃类型 | 说明 | |---------|------| | no output from test machine | 测试机无任何输出,通常指内核死锁、严重挂起或崩溃 | | lost connection to test machine | SSH连接中断,可能内核panic或网络故障导致 | | test machine is not executing programs | 测试机看似在线,但长时间未执行测试程序,可能挂起或陷入死循环 | 九、总结 Syzkaller不仅是一个内核模糊测试工具,更是一种系统化、闭环化的内核安全研究框架。它通过精心设计的syzlang描述系统调用接口,结合覆盖率驱动(KCOV)和内存检测(KASAN/KCOV/UBSAN)形成反馈闭环,使模糊测试从随机尝试升级为"智能探索"。 关键优势: 自动化程度高 :从测试用例生成到崩溃复现全流程自动化 反馈驱动 :基于覆盖率指导测试方向,提高效率 系统化设计 :完整的工具链和生态系统支持 多平台支持 :支持多种操作系统和架构 这种方法论强调自动化、反馈驱动和系统化设计,让Fuzzing不再是盲目的尝试,而是有策略、有方向的漏洞探索,对内核安全研究具有深远的启发意义。