Healer的安装和初步使用

Healer的安装和初步使用

简介

​ Healer 是受 Syzkaller 启发的内核模糊测试器。
​ 与 Syzkaller 类似,Healer 使用 Syzlang 描述提供的 syscall 信息生成确认参数结构约束和部分语义约束的系统调用序列,并通过不断执行生成的调用序列导致内核崩溃,从而发现内核错误。
​ 与 Syzkaller 不同,Healer 不使用经验选择表,而是通过动态移除最小化调用序列中的调用并观察覆盖变化,来检测系统调用之间的影响关系,并利用影响关系来指导调用序列的生成和变异。 此外,Healer 还使用了与 Syzkaller 不同的架构设计。

构建Healer

  • 除了一些修补代码之外,Healer 是用纯rust编写的。 因此,首先应安装 rust 工具链。

    1
    2
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 
    rustc --version # check install

    检查安装结果:

    image-20211129084016844

  • 为了使用 Syzlang 描述,Healer 的构建脚本会自动下载 Syzkaller 并在源代码中添加补丁并构建 Syzkaller,这可能会增加构建时间。 因此,需要安装Syzkaller 所需的构建工具,例如:GO111MODULE开启的golang 编译器,GCC 6.1.0 或更高版本。

    image-20211129083949436

    • GO111MODULE的开启命令:

      1
      2
      go env -w GO111MODULE="on"
      go env #check
  • 一旦安装了所有必需的工具,就可以使用以下命令轻松构建 Healer:

    1
    cargo build --release
  • 最后,可以在 target/release目录中找到 Healer 本身和打补丁的 Syzkaller 二进制文件 (syz-bin)。

    image-20211129083924376

使用 Healer 对 Linux 内核进行模糊测试

​ 总的来说,使用 Healer 对 Linux 内核进行模糊测试需要三个步骤:(1) 准备磁盘映像,(2) 编译内核, (3) 启动 Healer。

​ Healer 使用 qumu 来引导内核,所以需要准备磁盘镜像和内核镜像。启动后的 qemu 需要能够通过 ssh 密钥登录,内核至少需要具备 kcov 功能。(可以参照Syzkaller文档的详细介绍)

先决条件

1
2
sudo apt update 
sudo apt install make gcc flex bison libncurses-dev libelf-dev libssl-dev

准备磁盘映像

安装 debootstrap

1
sudo apt install debootstrap

创建 Debian Stretch Linux 映像

1
2
3
4
5
mkdir $IMAGE 
cd $IMAGE/
wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh
chmod +x create-image.sh
./create-image.sh
  • 注意将$IMAGE替换为自己的路径。

附加工具

1
2
./create-image.sh --feature full
./create-image.sh --add-perf

编译内核

获取内核源码

1
git clone --branch v5.14 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $KERNEL
  • 建议从最新的稳定版本开始。V5.14是一个示例。
  • 在虚拟机中git clone运行时间较长。在较好的网络环境下,可以选择在物理机中前往https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/下载内核源码的压缩包,然后拖入虚拟机解压

生成默认配置

1
2
3
cd $KERNEL
make defconfig
make kvm_guest.config
  • 同样注意将$IMAGE替换为自己的路径。

启用所需的配置选项

  • 手动编辑.config文件来启用它们:
1
2
3
4
5
6
7
8
9
10
11
12
13
# Coverage collection.
CONFIG_KCOV=y

# Debug info for symbolization.
CONFIG_DEBUG_INFO=y

# Memory bug detector
CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y

# Required for Debian Stretch
CONFIG_CONFIGFS_FS=y
CONFIG_SECURITYFS=y
  • 重新生成配置:

    1
    make olddefconfig

编译内核命令

1
make -j`nproc`

编译内核时make -jnproc的含义是使用多线程编译,加快编译速度。其中,-j选项指定了同时运行的任务数,而nproc是一个命令,用于返回当前系统的处理器数1

  • 检查:

    1
    2
    3
    4
    ls $KERNEL/vmlinux
    # sample output - $KERNEL/vmlinux
    ls $KERNEL/arch/x86/boot/bzImage
    # sample output - $KERNEL/arch/x86/boot/bzImage

    image-20211129091321934

安装QEMU

命令

1
sudo apt install qemu-system-x86

核查

  • 先确定虚拟机的处理器开启虚拟化引擎-虚拟化Intel VT-x/EPT或AMD-V/RVI (我使用的是VMware Workstation)

    image-20211129092011086
  • 确认sshd开启

    1
    ps -e |grep ssh

    image-20211129092306518

    • 如果没有出现sshd,则输入命令:

      1
      /etc/init.d/ssh start
  • 正式启动QEMU:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    qemu-system-x86_64 \
    -m 2G \
    -smp 2 \
    -kernel linux/arch/x86/boot/bzImage \
    -append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \
    -drive file=./stretch.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 |
    • 同样注意路径替换

    image-20211129093353035

    • 输入root即可登录

    image-20211129093430583

  • 此后,可以在另一终端中测试ssh能否工作

    1
    ssh -i $IMAGE/stretch.id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost

    image-20211129093824085

运行Healer

  • 一旦stretch.img$IMAGE/stretch.img)、ssh-stretch.id_rsa$IMAGE/ssh-stretch.id_rsa)、bzImage$KERNEL/linux-5.14/arch/x86/boot/bzImage准备就绪,建议是创建一个工作目录workdir。 然后,在 workdir 中创建一个 bin 目录,并将修补后的 Syzkaller 二进制文件和Healer二进制文件复制到该目录中(healer/target/release/syz-bin),注意不要更改 syz-bin 目录结构。 最终的工作目录需要有以下文件。

    1
    2
    3
    4
    cd path/to/workdir && ls  
    bin bzImage stretch.id_rsa stretch.img
    ls ./bin
    healer linux_amd64 syz-repro syz-symbolize syz-sysgen
  • 最后,在workdir执行以下命令开始模糊测试,其中 -d 指定磁盘映像的路径,-k 指定内核映像的路径,–ssh-key 指定 ssh 密钥的路径。

    1
    sudo ./bin/healer -d stretch.img -s stretch.id_rsa -k bzImage 
  • 若正常运行,界面如下: image-20211129150723525

遇到的错误

1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ sudo ./bin/healer -d stretch.img --ssh-key stretch.id_rsa -k bzImage

___ ___ ______ ________ __ ______ ______
/__/\ /__/\ /_____/\ /_______/\ /_/\ /_____/\ /_____/\
\::\ \\ \ \\::::_\/_\::: _ \ \\:\ \ \::::_\/_\:::_ \ \
\::\/_\ .\ \\:\/___/\\::(_) \ \\:\ \ \:\/___/\\:(_) ) )_
\:: ___::\ \\::___\/_\:: __ \ \\:\ \____\::___\/_\: __ `\ \
\: \ \\::\ \\:\____/\\:.\ \ \ \\:\/___/\\:\____/\\ \ `\ \ \
\__\/ \::\/ \_____\/ \__\/\__\/ \_____\/ \_____\/ \_\/ \_\/

[2021-11-28T05:20:10Z INFO healer_fuzzer] loading target linux/amd64...
[2021-11-28T05:20:15Z INFO healer_fuzzer] pre-booting one vm...
Error: failed to boot qemu

Caused by:
boot: failed to boot in 0s: "qemu-system-x86_64" "-display" "none" "-serial" "stdio" "-no-reboot" "-snapshot" "-device" "virtio-rng-pci" "-enable-kvm" "-cpu" "host,migratable=off" "-m" "4096" "-smp" "2" "-device" "e1000,netdev=net0" "-netdev" "user,id=net0,host=10.0.2.10,hostfwd=tcp::1025-:22" "-drive" "file=/home/yuhan/workdir/stretch.img,index=0,media=disk" "-kernel" "/home/yuhan/workdir/bzImage" "-append" "root=/dev/sda console=ttyS0 kvm-intel.nested=1 kvm-intel.unrestricted_guest=1 kvm-intel.vmm_exclusive=1 kvm-intel.fasteoi=1 kvm-intel.ept=1 kvm-intel.flexpriority=1 kvm-intel.vpid=1 kvm-intel.emulate_invalid_guest_state=1 kvm-intel.eptad=1 kvm-intel.enable_shadow_vmcs=1 kvm-intel.pml=1 kvm-intel.enable_apicv=1 earlyprintk=serial oops=panic nmi_watchdog=panic panic_on_warn=1 panic=1 ftrace_dump_on_oops=orig_cpu vsyscall=native net.ifnames=0 biosdevname=0" "-device" "ivshmem-plain,memdev=hostmem0" "-object" "memory-backend-file,size=4194304,share,mem-path=/dev/shm/healer-in_shm-0-35410,id=hostmem0" "-device" "ivshmem-plain,memdev=hostmem1" "-object" "memory-backend-file,size=16777216,share,mem-path=/dev/shm/healer-out_shm_0-35410,id=hostmem1"
stderr:
failed to boot, qemu exited with: signal: 6 (core dumped)
cmdline: "qemu-system-x86_64" "-display" "none" "-serial" "stdio" "-no-reboot" "-snapshot" "-device" "virtio-rng-pci" "-enable-kvm" "-cpu" "host,migratable=off" "-m" "4096" "-smp" "2" "-device" "e1000,netdev=net0" "-netdev" "user,id=net0,host=10.0.2.10,hostfwd=tcp::1025-:22" "-drive" "file=/home/yuhan/workdir/stretch.img,index=0,media=disk" "-kernel" "/home/yuhan/workdir/bzImage" "-append" "root=/dev/sda console=ttyS0 kvm-intel.nested=1 kvm-intel.unrestricted_guest=1 kvm-intel.vmm_exclusive=1 kvm-intel.fasteoi=1 kvm-intel.ept=1 kvm-intel.flexpriority=1 kvm-intel.vpid=1 kvm-intel.emulate_invalid_guest_state=1 kvm-intel.eptad=1 kvm-intel.enable_shadow_vmcs=1 kvm-intel.pml=1 kvm-intel.enable_apicv=1 earlyprintk=serial oops=panic nmi_watchdog=panic panic_on_warn=1 panic=1 ftrace_dump_on_oops=orig_cpu vsyscall=native net.ifnames=0 biosdevname=0" "-device" "ivshmem-plain,memdev=hostmem0" "-object" "memory-backend-file,size=4194304,share,mem-path=/dev/shm/healer-in_shm-0-35410,id=hostmem0" "-device" "ivshmem-plain,memdev=hostmem1" "-object" "memory-backend-file,size=16777216,share,mem-path=/dev/shm/healer-out_shm_0-35410,id=hostmem1"
STDERR:
qemu-system-x86_64: error: failed to set MSR 0x48f to 0x7fffff00036dfb
qemu-system-x86_64: /build/qemu-A1914X/qemu-4.2/target/i386/kvm.c:2691: kvm_buf_set_msrs: Assertion `ret == cpu->kvm_msr_buf->nmsrs' failed.

解决方案

找到healer-main/healer_utils/healer_vm/src/qemu.rs,这是healer中关于qemu的配置文件。将“linux/amd64”的对应参数args改为:"-enable-kvm"(下图中的第487行)。

image-20211129152303710

参考链接

  1. https://github.com/SunHao-0/healer
1
ssh -F /dev/null -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=3s -i /home/yuhan/Desktop/myFuzzer/image/stretch.id_rsa -p 7401 root@127.0.0.1 ~/syz-executor check

ssh -F /dev/null -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=3s -i /home/yuhan/Desktop/FuzzerWork/stretch.id_rsa -p 14605 root@127.0.0.1 pkill syz-executor


本博客所有文章除特别声明外,均为博客作者本人编写整理,转载请联系作者!