uniFuzzer 是一款基于 Unicorn 和 LibFuzzer 对闭源二进制程序进行模糊测试的工具。目前支持对 ARM/MIPS 架构的 32 位 LSB ELF 文件进行模糊测试,这类文件常见于物联网设备中。
callback 目录下创建一个 .c 文件,其中应包含以下回调函数:void onLibLoad(const char *libName, void *baseAddr, void *ucBaseAddr):每次在 Unicorn 中加载依赖库时调用。int uniFuzzerInit(uc_engine *uc):所有二进制文件加载到 Unicorn 后调用。可在此处设置栈/堆/寄存器。int uniFuzzerBeforeExec(uc_engine *uc, const uint8_t *data, size_t len):每轮模糊测试执行前调用。int uniFuzzerAfterExec(uc_engine *uc):每轮模糊测试执行后调用。make,生成名为 uf 的模糊测试工具。uniFuzzer 使用以下环境变量作为参数:
UF_TARGET:目标 ELF 文件的路径UF_PRELOAD:预加载库的路径。请确保该库与目标具有相同的架构。UF_LIBPATH:依赖库所在的路径。多个路径用 : 分隔。然后使用以下命令开始模糊测试:
UF_TARGET=<target> [UF_PRELOAD=<preload>] UF_LIBPATH=<libPath> ./uf
这里提供一个基本用法的演示。演示包含以下文件:
vuln() 的简单函数,存在栈/堆溢出漏洞。printf() 以及简化的 malloc()/free()。vuln() 函数进行模糊测试所需的回调函数。首先,请安装 mipsel 的 gcc(Debian 上为 gcc-mipsel-linux-gnu 包)来构建演示:
# 目标二进制
# '-Xlinker --hash-style=sysv' 告知 gcc 使用 'DT_HASH' 而非 'DT_GNU_HASH' 进行符号查找
# 因为当前 uniFuzzer 不支持 'DT_GNU_HASH'
mipsel-linux-gnu-gcc demo-vuln.c -Xlinker --hash-style=sysv -no-pie -o demo-vuln
# 预加载库
mipsel-linux-gnu-gcc -shared -fPIC -nostdlib -Xlinker --hash-style=sysv demo-libcpreload.c -o demo-libcpreload.so
你也可以直接使用文件 demo-vuln 和 demo-libcpreload.so,它们已用上述命令编译好。
接下来,运行 make 构建 uniFuzzer。请注意,如果你自己编译了 MIPS 演示,那么某些地址可能与预编译的不同,需要相应更新 demo-callback.c。
最后,确保 MIPS 的 libc 库已就绪。在 Debian 上,安装 libc6-mipsel-cross 包后,库位于 /usr/mipsel-linux-gnu/lib/,这就是 UF_LIBPATH 应指向的位置:
UF_TARGET=<path to demo-vuln> UF_PRELOAD=<path to demo-libcpreload.so> UF_LIBPATH=<lib path for MIPS> ./uf
由于这个 问题,Unicorn 会清除 QEMU 的 JIT 缓存,这会降低模糊测试的速度,因为目标二进制文件在每轮执行时都需要重新进行 JIT 编译。
我们可以按照该问题中的说明注释掉 tb_flush(env); 以提升性能。
GNU_HASHIFUNC