Syzkaller实战教程10: MoonShine复现&Trace2syz功能演示

Moonshine 是 Syzkaller 的改进项目,由哥伦比亚大学团队开发,是一种为操作系统模糊测试工具提供紧凑且多样化种子的策略与工具,旨在提升模糊测试的效率和效果,更好地发现内核级别的漏洞。相关内容如下:

  1. 核心功能:通过分析现实世界程序的系统调用跟踪来生成种子。它利用轻量级静态分析检测不同系统调用之间的依赖关系,能够移除不必要的调用,保留最有可能触发漏洞的部分,从而生成更高效的测试种子。
  2. 实现方式:通过扩展 strace 实现了 tracer,以捕捉系统调用的名称、参数和返回值,并采用 kcov 进行代码覆盖率测量。同时,使用 smatch,一个对 C 进行静态分析的框架,来进行控制流分析,通过注册不同的 hook 来检测条件语句和赋值语句,以此确定系统调用之间的显式依赖(explicit dependencies)和隐式依赖(implicit dependencies)。
  3. 效果:从包含 280 万个系统调用的 3220 个真实世界程序跟踪中,可将其精炼到 14000 个左右的调用,同时保留 86% 的原始代码覆盖率。基于这些精炼的种子系统调用序列,Moonshine 平均可将 Syzkaller 对 Linux 内核的代码覆盖率提高 13%,还发现了 17 个 Syzkaller 未发现的 Linux 内核新漏洞。
  4. 技术栈:主要使用 Go 语言开发,借助 Ragel(状态机编译器)和 Goyacc(解析器生成器)将原始的跟踪数据转换为可用的格式。
  5. 使用限制:目前 Moonshine 只能为 Linux 上的 Syzkaller 生成种子,且只能解析通过 strace 收集的跟踪,建议使用版本大于等于 4.16 的 strace。

**.Moonshine** 复现

|---------------------------------------------------------------------------------------------------------------------|
| SQL # 本机复现采用环境配置版本 Moonshine:最新版 Syzkaller: commit f48c20b8f9b2a6c26629f11cc15e1c9c316572c8 Ubuntu 20.04 Go 1.11.13 |

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |

安装tips:

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL 1. 保证moonshine和syzkaller的相对路径为如下: # moonshine路径 /home/ubuntu2004/go_projects/src/github.com/shankarapailoor/moonshine # syzkaller路径 /home/ubuntu2004/go_projects/src/github.com/google/syzkaller 2.moonshine 和syzkaller的版本应该匹配 :如旧版moonshine配合旧版syzkaller 本机采用moonshine配合18年syzkaller 3.moonshine和syzkaller均合适版本go编译(本机采用go1.11.13编译,采用高版本go会报错(go1.22.1)) 4.安装trace2syz工具的注意事项和上述一样,git clone在moonshine相同文件夹下即可。 trace2syz 和moonshine转换的效果并不相同,trace2syz更加简短 |

**1.**安装 Go

MoonShine主要是用Go编写的,所以需要先安装Go。请按照以下步骤进行:

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash 1. 安装Go,在go_projects路径下下载解压指定版本的Go # 此版本的Go采用go.mod安装依赖,适合新版sykzlaller(20年以后),本机命名为goroot wget https://dl.google.com/go/go1.22.1.linux-amd64.tar.gz sudo tar -C /usr/local -xzf go1.22.1.linux-amd64.tar.gz # 此版本的Go未采用go.mod管理依赖,适合旧版syzkaller(20年以前),本机命名为go wget https://dl.google.com/go/go1.11.13.linux-amd64.tar.gz tar -xzf go1.11.13.linux-amd64.tar.gz 2.配置go工作目录路径 # 适用于新版syzkaller的1.22.1Go的路径: export GOROOT=~/go_projects/go export PATH=GOROOT/bin:PATH # 旧版syzkaller和moonshine需要安装1.11.13Go路径,复现moonshine采用这版 # 这些命令只是让当前路径的环境变量做修改,是一次性的,重启或者更换到其它路径,都会 # 采用配置文件的默认设置,因此时刻注意此时的go版本是哪一个 export GOROOT=~/go_projects/go export GOPATH=~/go_projects export PATH=GOROOT/bin:GOPATH/bin:$PATH source ~/.bashrc # 验证 Go 安装成功 go version |

确保Go已正确安装并运行go version来确认版本。

**2.**安装 Ragel

Ragel用于扫描和解析MoonShine中的trace。通过以下命令安装Ragel:

|---------------------------------------------------------------------|
| Bash sudo apt-get update sudo apt-get install ragel ragel --version |

**3.**安装 Goyacc

MoonShine使用Goyacc来解析trace。安装Goyacc:

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash # 本机设置ssh连接github仓库后 # 使用ssh克隆仓库,采用http可能导致错误 git clone git@github.com:golang/tools.git # 或者在go1.22.1版本下直接安装 go install golang.org/x/tools/cmd/goyacc@latest export GOPATH=~/go_projects export PATH=GOPATH/bin:PATH |

然后确保Goyacc所在目录在你的PATH中,完成安装:

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash export GOPATH=HOME/go export PATH=GOPATH/bin:PATH echo PATH echo GOPATH export PATH=PATH:HOME/go/bin # 进入 Goyacc 目录,编译并安装 goyacc cd \~/go_projects/tools/cmd/goyacc # 将项目放入 GOPATH/src 下 mkdir -p GOPATH/src/golang.org/x mv \~/go_projects/tools GOPATH/src/golang.org/x/ # 进入新路径下的 goyacc 目录并安装: cd GOPATH/src/golang.org/x/tools/cmd/goyacc go install # 以下三种方法查看是否安装成功,注意goyacc并不提供版本号 goyacc --version which goyacc goyacc # 未查询到路径时,添加GOPATH/bin 是否包含在 PATH # 1.**确认 goyacc 是否安装在 GOPATH/bin** : ls GOPATH/bin/goyacc # 2.添加路径: export PATH=PATH:~/go/bin echo 'export PATH=PATH:\~/go/bin' source \~/.bashrc # 检查是否已经添加 echo PATH # 验证: goyacc # 2. 使环境变量永久生效:将上述环境变量的配置添加到你的 ~/.profile 文件中,以确保在每次重启系统后,环境变量都能自动加载。 # 编辑 ~/.profile 文件: nano ~/.profile # 在文件末尾添加同样的内容: export GOROOT=/usr/local/go export GOPATH=HOME/go export PATH=PATH:GOROOT/bin:GOPATH/bin # 保存文件并退出,之后再执行一次 source ~/.profile 让配置立即生效。 source ~/.profile |

**4.**下载和编译 MoonShine

获取MoonShine的代码并构建:

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash # 调整代理 go env -w GOPROXY=https://goproxy.cn # 克隆 MoonShine 项目 mkdir -p github.com/shankarapailoor/ git clone git@github.com:shankarapailoor/moonshine.git cd $GOPATH/src/github.com/shankarapailoor/moonshine make |

克隆syzkaller项目到本地并指定版本:

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL # 克隆 Syzkaller : mkdir -p ~/go/src/github.com/google # ssh获取,http容易失败 git clone git@github.com:google/syzkaller.git GOPATH/src/github.com/google/syzkaller/ # 验证 ls \~/go/src/github.com/google/syzkaller # 进入克隆的 **Syzkaller** 项目目录,并切换到指定的提交版本 《f48c20b8f9b2a6c26629f11cc15e1c9c316572c8》 cd GOPATH/src/github.com/google/syzkaller/ git checkout f48c20b8f9b2a6c26629f11cc15e1c9c316572c8 go mod edit -require=github.com/google/syzkaller@v0.0.0-20180519084834-f48c20b8f9b2 # 确认切换成功,可以运行以下命令查看当前版本: git log -1 |

编译moonshine

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL # 返回 moonshine 项目目录并再次运行 make cd ~/go/src/github.com/shankarapailoor/moonshine # 初始化 Go Modules export GO111MODULE=auto go mod init github.com/shankarapailoor/moonshine go mod init github.com/google/syzkallerOLD # 下载并解析项目的所有依赖: go mod tidy go mod vendor make -j4 |

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL "github.com/google/syzkaller/prog" "github.com/google/syzkallerOLD/prog" # 使用 sed 进行全局替换: 在项目根目录下执行以下命令 find . -type f -exec sed -i 's|github.com/google/syzkaller|github.com/google/syzkallerOLD|g' {} + |

**5.**运行 MoonShine

构建完成后,可以参考如下命令模板运行MoonShine并生成Syzkaller所需的种子:

|------------------------------------------------------------------------|
| Bash ./bin/moonshine -dir [tracedir] -distill [distillConfig.json] |

  • -dir [tracedir] :要解析的日志文件目录。目录内应包含使用 strace 生成的系统调用日志文件。
  • -distill [distillConfig.json]:指定配置文件,用于设定提取策略(例如"隐式依赖(implicit)"或"仅显式依赖(explicit)")。
  • 如果日志文件中不包含调用覆盖信息或不需要提取,可以省略此参数,trace2syz 将按原样生成 Syzkaller 程序。
  • 示例配置文件 distill.json 可以在 getting-started/ 目录中找到。
  • 示例trace文件getting-started/sampletraces则需要通过moonshine的github项目给出的google云盘去下载作者提供的示例trace文件,也可以采用作者指定版本和补丁修改后的strace手动捕获示例。如果没有样例日志,可以从 Google Drive 上下载官方提供的样例日志压缩包,将其解压到 getting-started/ 目录中,以便进行示例测试。

google drive

  • 如果指定了 -deserialize 参数,trace2syz 还会将解析的 Syzkaller 程序存储在指定目录下,以便手动检查转换效果。
  • 如果不使用 -distill 参数,则 trace2syz 会直接转换日志内容,无需进行额外提取处理。经测试,不使用参数去蒸馏trace时,corpus.db的大小从80kb上升到360kb

6. 运行实例分析

  1. 运行记录:

|---------|------|-------|-------|----------------|-------|
| trace内容 | 文件数量 | 蒸馏策略 | 转换后数量 | 转换后corpus.db大小 | 分析 |
| 样例trace | 346 | 显式+隐式 | 385 | 80kb | 已验证可用 |
| 样例trace | 346 | 无 | 485 | 361kb | |

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | SQL # trace2syz工具提取结果: mmap(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x3, 0x32, 0xffffffffffffffff, 0x0) r0 = open(&(0x7f0000000000)='/etc/ld.so.cache\x00', 0x80000, 0x0) fstat(r0, &(0x7f0000000011)) close(r0) r1 = open(&(0x7f0000000055)='/lib/x86_64-linux-gnu/libc.so.6\x00', 0x80000, 0x0) read(r1, &(0x7f0000000075)=""/833, 0x341) fstat(r1, &(0x7f00000003b6)) close(r1) accept(0x190, &(0x7f00000003fa), &(0x7f000000047a)=0x80) ioctl(0x1, 0x5401, &(0x7f000000047e)) fstat(0x1, &(0x7f000000047e)) r2 = open(&(0x7f00000004c2)='/dev/null\x00', 0x1, 0x0) accept(r2, &(0x7f00000004cc), &(0x7f000000054c)=0x80) r3 = socketinet_tcp(0x2, 0x1, 0x0) bindinet(r3, &(0x7f0000000550)={0x2, 0x0, @rand_addr}, 0x10) acceptinet(r3, \&(0x7f0000000560), \&(0x7f0000000570)=0x10) close(r3) r4 = socketinet_tcp(0x2, 0x1, 0x0) bindinet(r4, \&(0x7f0000000574)={0x2, 0x0, @rand_addr}, 0x10) acceptinet(r4, &(0x7f0000000584), &(0x7f0000000594)=0x10) close(r4) r5 = socketinet_tcp(0x2, 0x1, 0x0) bindinet(r5, &(0x7f0000000598)={0x2, 0x0, @rand_addr}, 0x10) acceptinet(r5, \&(0x7f00000005a8), \&(0x7f00000005b8)=0x10) close(r5) r6 = socketinet_tcp(0x2, 0x1, 0x0) bindinet(r6, \&(0x7f00000005bc)={0x2, 0x0, @rand_addr}, 0x10) ioctlint_in(r6, 0x5421, &(0x7f00000005cc)=0x1) acceptinet(r6, \&(0x7f00000005d4), \&(0x7f00000005e4)=0x10) close(r6) r7 = socketinet_udp(0x2, 0x2, 0x0) bindinet(r7, \&(0x7f00000005e8)={0x2, 0x0, @rand_addr}, 0x10) acceptinet(r7, &(0x7f00000005f8), &(0x7f0000000608)=0x10) close(r7) exit_group(0x0) | | |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | SQL # moonshine提取结果: mmap(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x3, 0x32, 0xffffffffffffffff, 0x0) mmap(&(0x7f0000001000/0x4000)=nil, 0x4000, 0x3, 0x32, 0xffffffffffffffff, 0x0) r0 = open(&(0x7f0000000000)='/etc/ld.so.cache\x00', 0x80000, 0x0) fstat(r0, &(0x7f0000000011)) mmap(&(0x7f0000005000/0x4000)=nil, 0x4000, 0x1, 0x12, r0, 0x0) close(r0) r1 = open(&(0x7f0000000055)='/lib/x86_64-linux-gnu/libc.so.6\x00', 0x80000, 0x0) read(r1, &(0x7f0000000075)=""/833, 0x341) fstat(r1, &(0x7f00000003b6)) mmap(&(0x7f0000009000/0x39d000)=nil, 0x39d000, 0x5, 0x812, r1, 0x0) mprotect(&(0x7f000019c000/0x1000)=nil, 0x1000, 0x0) mmap(&(0x7f00003a6000/0x7000)=nil, 0x7000, 0x3, 0x812, r1, 0x0) mmap(&(0x7f00003ad000/0x4000)=nil, 0x4000, 0x3, 0x32, 0xffffffffffffffff, 0x0) close(r1) mmap(&(0x7f00003b1000/0x3000)=nil, 0x3000, 0x3, 0x32, 0xffffffffffffffff, 0x0) mprotect(&(0x7f00003a6000/0x1000)=nil, 0x1000, 0x1) mprotect(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x1) mprotect(&(0x7f0000004000/0x1000)=nil, 0x1000, 0x1) munmap(&(0x7f00003b3000/0x1000)=nil, 0x1000) accept(0x190, &(0x7f00000003fa), &(0x7f000000047a)=0x80) ioctlTCGETS(0x1, 0x5401, \&(0x7f000000047e)) fstat(0x1, \&(0x7f00000004a2)) r2 = open(\&(0x7f00000004e6)='/dev/null\\x00', 0x1, 0x0) accept(r2, \&(0x7f00000004f0), \&(0x7f0000000570)=0x80) r3 = socketinet(0x2, 0x1, 0x0) bindinet(r3, \&(0x7f0000000574)={0x2}, 0x10) acceptinet(r3, &(0x7f0000000584), &(0x7f0000000594)=0x10) close(r3) r4 = socketinet(0x2, 0x1, 0x0) bindinet(r4, &(0x7f0000000598)={0x2}, 0x10) acceptinet(r4, \&(0x7f00000005a8), \&(0x7f00000005b8)=0x10) close(r4) r5 = socketinet(0x2, 0x1, 0x0) bindinet(r5, \&(0x7f00000005bc)={0x2}, 0x10) acceptinet(r5, &(0x7f00000005cc), &(0x7f00000005dc)=0x10) close(r5) r6 = socketinet(0x2, 0x1, 0x0) bindinet(r6, &(0x7f00000005e0)={0x2}, 0x10) ioctlint_in(r6, 0x5421, \&(0x7f00000005f0)=0x1) acceptinet(r6, &(0x7f00000005f8), &(0x7f0000000608)=0x10) close(r6) r7 = socketinet(0x2, 0x2, 0x0) bindinet(r7, &(0x7f000000060c)={0x2}, 0x10) accept$inet(r7, &(0x7f000000061c), &(0x7f000000062c)=0x10) close(r7) exit_group(0x0) | |

1. 运行如下命令来处理作者提供的示例trace:

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash # 不蒸馏 ./bin/moonshine -dir getting-started/sampletraces/ ./bin/trace2syz -dir getting-started/sampletraces/ # 蒸馏策略:显示+隐式 ./bin/moonshine -dir getting-started/sampletraces/ -distill getting-started/distill.json |

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |

成功执行后,trace2syz 将输出类似以下内容:

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text Total number of Files: 346 Parsing File 1/346: ltp_accept4_01 Parsing File 2/346: ltp_accept_01 ... Total Distilled Progs: 385 Average Program Length: 10 Total contributing calls: 639 out of 43480 in 383 implicitly-distilled programs. Total calls: 3342 |

生成的corpus.db文件可以用于Syzkaller进行模糊测试,deserialize保存了反序列后的文本格式的系统调用序列。

转换前后的结果如下:

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |

2. 若采用非指定strace(为进行trace2syz的转换,作者对strace进行了修改,指定了采用的strace版本和补丁号)获取的trace实例:

|----------------------------------------------------------------------------------------------------------------------------------|
| SQL ./bin/moonshine -dir getting-started/test1 ./bin/moonshine -dir getting-started/test1/ -distill getting-started/distill.json |

转换后的结果如下:

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |

3. 使用 strace 跟踪 ls 命令 : 在终端中运行以下命令,以生成系统调用跟踪文件 trace:

|------------------------------------------------------|
| SQL strace -o trace -a 1 -s 65500 -v -xx -f -Xraw ls |

这个命令将会跟踪 ls 命令的系统调用,并将结果保存到 trace 文件中。

运行 syz-trace2syz 转换 trace 文件 : 假设 syz-trace2syz 已编译完成并可以执行,请运行以下命令以将 trace 文件转换为 Syzkaller 格式:

|-------------------------------------------------------------------------|
| SQL ./bin/moonshine -file trace ./bin/moonshine -dir getting-started/ls |

此命令会解析 trace 文件,并将其转化为 Syzkaller 测试用例格式,适合作为 Syzkaller 的种子输入。

7. 收集带有覆盖率 trace

|--------------------------------------------------------------------------------------------------|
| SQL 此步骤是为了完成moonshine的蒸馏,所以需要带有覆盖率的trace。如果只是为了转换格式,不需要采用特意的strace工具收集带有覆盖率的trace。使用默认的strace即可。 |

1. 安装Strace并应用补丁。克隆strace仓库并切换到指定的commit:

|------------------------------------------------------------------------------------------------------------------------------|
| Bash cd ~ git clone https://github.com/strace/strace strace cd strace git checkout a8d2417e97e71ae01095bee1a1e563b07f2d6b41 |

2. 应用MoonShine的kcov补丁:

|-----------------------------------------------------------------------------------|
| Bash git apply $GOPATH/src/github.com/shankarapailoor/moonshine/strace_kcov.patch |

3. 构建strace:

|--------------------------------------------------------------------------------|
| Bash # 初始化项目的构建环境,它会生成必要的配置文件和脚本 ./bootstrap # 配置项目以适应当前系统的环境 ./configure make |

4. 使用Strace采集trace

通过以下命令来使用patched strace采集带有覆盖率的trace:

|--------------------------------------------------------------------------------------|
| Bash strace -o tracefile -s 65500 -v -xx -f -k /path/to/executable arg1 arg2 .. argN |

采集不带有覆盖率的trace,即仅进行格式转换,去掉-k参数:

|----------------------------------------------------------------------------------|
| SQL strace -o tracefile -s 65500 -v -xx -f /path/to/executable arg1 arg2 .. argN |

-o tracefile: 将输出写入到指定的文件中。

/path/to/executable arg1 arg2 .. argN: 指定要跟踪的可执行文件及其参数。

必需参数

① -s [val]:

  • 作用:指定每个调用的最大数据写入量。
  • 默认值:通常设置为 65500 字节。
  • 意义:控制输出的字节数,以防止过多数据导致输出难以处理。

② -v:

  • 作用:要求 strace 输出未缩写的参数信息。
  • 意义:提供更详细的输出,便于分析每个系统调用的参数。

③ -xx:

  • 作用:以十六进制格式输出字符串。
  • 意义:有助于以更可读的形式查看二进制数据和字符串,适合调试。

可选参数

① -f:

  • 作用:捕获子进程的跟踪信息(支持在 fork 后继续跟踪)。
  • 意义:对于需要分析多进程应用的情况非常有用,可以提供完整的执行跟踪。

② -k:

  • 作用:捕获每个调用的覆盖率。
  • 限制:仅在经过补丁的 strace 中支持,需要内核编译时启用 CONFIG_KCOV=y。
  • 意义:用于分析测试覆盖率,特别是在调试或性能分析时。

**.trace2syz** 复现

1. 蒸馏与Syzkaller模糊器最小化程序有何不同?

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 乍一看,他们也是这样做的:拿一个大项目,然后制作一个或多个 较小的项目来保持覆盖率。 作者有两个主要好处: 1) 它允许我们将来自真实程序的非常大的跟踪序列化为紧凑的 Syzkaller 跟踪。即使是几秒钟的跟踪(比如 Chrome?)也太大了,甚至无法序列化为有效的 Syzkaller 程序。蒸馏可以预先创建紧凑而有趣的种子。 2) 现有的 fuzzer 最小化效果很好,因为 Syzkaller 自然会生成紧凑的程序;但是,根据我的经验,这无法有效地扩展即使是 100 个调用的程序(例如这些)。例如,Syzkaller 似乎试图预先减少起始种子,对吗?我记得只提供了少数几个这些转换后的程序,在我杀死它之前,最小化还持续了一天半。 |

|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| moonshine作者将trace2syz的过程单独分离为工具集成到了syzkaller官方项目中,可在syzkaller项目的tools文件夹下找到syz-trace2syz,即代表了该工具。可在编译后按照上述流程同样完成trace2syz的过程,但注意,此时的工具没有蒸馏效果,只能进行格式转换。 |

|--------------------------------------------------------------------------------------------------------------------------------------------|
| moonshine作者提供的单独的trace2syz可按照第一部分的内容正常编译使用,但集成到syzkaller中的trace2syz工具则在编译后无法转换任何trace,且18年到24年的syzkaller版本均会出现相同的错误。错误类型和内容可参考"复现配置记录部分"内容 |

moonshine工具被分为 2 个独立的工具:

一个将 strace 转换为 syzkaller 程序,一个用于实现trace的蒸馏。

第一个工具被重构为两个包:parser 和 proggen。parser 只是将 strace 输出转换为中间表示,而 proggen 将 IR 转换为 syzkaller 程序。

使用步骤:

要运行 trace2syz 并生成 Syzkaller 的种子,可以按照以下步骤操作:

**2.**编译 trace2syz

trace2syz已经被合并至syzkaller项目tools文件夹内,该文件夹内包含了多种syzkaller扩展工具,例如syz-db用户管理corpus.db。

1.首先,需要构建 syz-trace2syz 工具,步骤如下:

切换到 syzkaller 的源代码目录。

第一种方法:使用 make trace2syz 命令构建 trace2syz 工具:

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash # 临时配置路径 export PATH=~/go_projects/goroot/bin:PATH # 永久配置路径 # 打开 \~/.bashrc 文件 nano \~/.bashrc # 在文件末尾添加以下行,设置 GOROOT 为你的 Go 安装路径 export GOROOT=/home/ubuntu2004/go_projects/goroot export PATH=GOROOT/bin:$PATH # 保存并退出编辑器。让配置立即生效: source ~/.bashrc # 依据Makefile中的定义的 trace2syz 伪目标编译,完成在bin/目录下出现 make trace2syz -j2 |

第二种方法:手动切换到 tools/syz-trace2syz 目录,然后运行:(并未奏效)

|--------------------------------------------------------------------------------------------|
| Bash go mod vendor go mod tidy # 本机给了4G内存不够,增加到8G go build # 内存还不够时: GOMAXPROCS=2 go build |

确保 trace2syz 已经成功构建。trace2syz 应位于 ./bin/trace2syz(采用第二种方式时,需要将可执行文件复制到/bin目录下),并且 distillConfig.json 配置文件也已准备好(在moonshine仓库中的getting_started文件下找到)。

**3.**运行命令

使用以下命令运行 syz-trace2syz 来解析日志目录并生成 Syzkaller 程序种子:

bash 复制代码
./bin/syz-trace2syz -dir tracedir -distill getting-started/distill.json

参数说明:

  1. -dir [tracedir] :要解析的日志文件目录。目录内应包含使用 strace 生成的系统调用日志文件。
  2. -distill [distillConfig.json]:指定配置文件,用于设定提取策略(例如"隐式依赖"或"仅显式依赖")。
  3. 如果日志文件中不包含调用覆盖信息或不需要提取,可以省略此参数,trace2syz 将按原样生成 Syzkaller 程序。
  4. 示例配置文件 distill.json 可以在 getting-started/ 目录中找到。
  5. 如果指定了 -deserialize 参数,trace2syz 还会将解析的 Syzkaller 程序存储在指定目录下,以便手动检查转换效果。
  6. 如果不使用 -distill 参数,则 trace2syz 会直接转换日志内容,无需进行额外提取处理。

**4.**示例

运行示例命令:

bash 复制代码
./bin/syz-trace2syz -dir getting-started/sampletraces/ -distill getting-started/distill.json
./bin/syz-trace2syz -dir getting-started/sampletraces
./bin/syz-trace2syz -dir getting-started/test1

成功执行后,trace2syz 将输出类似以下内容:

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text Total number of Files: 346 Parsing File 1/346: ltp_accept4_01 Parsing File 2/346: ltp_accept_01 ... Total Distilled Progs: 391 Average Program Length: 10 Total contributing calls: 639 out of 43480 in 388 implicitly-distilled programs. Total calls: 3250 |

**5.**生成的输出文件

生成的 corpus.db 文件包含已序列化的 Syzkaller 程序,准备好用于 Syzkaller 的模糊测试。生成的 corpus.db 文件将存放在运行 trace2syz 命令的当前目录下。在运行过程中,trace2syz 会将所有转换生成的 Syzkaller 程序序列化为 corpus.db,默认不支持指定存储位置,因此确保运行命令的工作目录具有写权限,方便保存生成的 corpus.db 文件

https://github.com/google/syzkaller/issues/3508

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL 我使用您的示例 (tools/syz-trace2syz/trace2syz.go) 来调用 strace: strace -o trace -a 1 -s 65500 -v -xx -f -Xraw ./a.out 我在一个简单的脚本上运行它,该脚本启用了环回接口(具有提升的权限): #!/bin/sh ip link set dev lo up |

使用 strace 跟踪 ls 命令 : 在终端中运行以下命令,以生成系统调用跟踪文件 trace:

|------------------------------------------------------|
| SQL strace -o trace -a 1 -s 65500 -v -xx -f -Xraw ls |

这个命令将会跟踪 ls 命令的系统调用,并将结果保存到 trace 文件中。

运行 syz-trace2syz 转换 trace 文件 : 假设 syz-trace2syz 已编译完成并可以执行,请运行以下命令以将 trace 文件转换为 Syzkaller 格式:

|-------------------------------------|
| SQL ./bin/syz-trace2syz -file trace |

此命令会解析 trace 文件,并将其转化为 Syzkaller 测试用例格式,适合作为 Syzkaller 的种子输入。

**6.**复现配置记录

检查它的提交历史

|----------------------------------------------|
| SQL git log --oneline -- tools/syz-trace2syz |

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash ./bin/syz-trace2syz -dir getting-started/sampletraces -distill getting-started/distill.json ./bin/syz-trace2syz -dir getting-started/sampletraces ./bin/syz-trace2syz -dir getting-started/test1 ./bin/syz-trace2syz -dir getting-started/testsample |

两个版本go的路径都在go_projects下,goroot是1.22.1,go是1.11.13.

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL nano ~/.bashrc source ~/.bashrc # 旧版Go配置: # GOROOT 是 Go 安装目录的路径 # GOPATH 是工作空间路径 # PATH 定义了操作系统如何找到可执行程序  export GOROOT=~/go_projects/go export GOPATH=~/go_projects export GOPATH=/home/ubuntu2004/go/src export PATH=GOROOT/bin:PATH export PATH=GOROOT/bin:GOPATH/bin:PATH # 新版Go配置 export GOROOT=\~/go_projects/goroot export GOROOT=/home/ubuntu2004/go_projects/goroot export PATH=GOROOT/bin:$PATH |

参考文献

moonshine仓库

trace2syz仓库