Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
difuze — Linux 内核驱动模糊测试器 | Kitploit
工具/GitHubGitHub/ucsb-seclab/difuze
Android安全漏洞分析模糊测试二进制分析
GitHubucsb-seclab/difuze

difuze

Linux 内核驱动模糊测试器

查看仓库
385854年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

difuze:Linux 内核驱动模糊测试器

License

本仓库包含所有源码(包括设置脚本),你需要这些来让 difuze 正常运行。

测试环境

Ubuntu >= 14.04.5 LTS

0. 通过 Docker 运行 difuze

参考 readme

如我们的论文所述,difuze 包含两个主要组件:接口恢复 和 模糊测试引擎

1. 接口恢复

接口恢复机制基于 LLVM 分析过程。接口恢复的每个步骤都编写为独立的过程。按照以下说明操作,让 接口恢复 正常运行。

1.1 设置

此步骤负责安装 LLVM 和 c2xml:

首先,确保已安装 libxml(c2xml 所需):

root@kitploit:~
sudo apt-get install libxml2-dev
sudo pip install lxml

接下来,我们创建了一个单一脚本,用于下载并构建所有必需的工具。

root@kitploit:~
cd helper_scripts
python setup_difuze.py --help
usage: setup_difuze.py [-h] [-b TARGET_BRANCH] [-o OUTPUT_FOLDER]

optional arguments:
  -h, --help        show this help message and exit
  -b TARGET_BRANCH  Branch (i.e. version) of the LLVM to setup. Default:
                    release_38 e.g., release_38
  -o OUTPUT_FOLDER  Folder where everything needs to be setup.

示例:

root@kitploit:~
python setup_difuze.py -o difuze_deps

要完成设置,你还需要修改本地的 PATH 环境变量。设置脚本会给出你需要做的具体更改。

1.2 构建

此步骤依赖于 设置 的成功完成。 我们有一个能构建所有内容的单一脚本,不用客气。

root@kitploit:~
cd InterfaceHandlers
./build.sh

1.3 运行

此步骤依赖于 构建 的成功完成。 要在内核驱动上运行接口恢复组件,我们首先需要将驱动转换为 LLVM 位码。

1.3.1 构建内核

首先,我们需要一个可构建的内核。这意味着你应该能够使用常规构建设置(即 make)编译内核。 我们首先捕获 make 命令的输出,然后从该输出中提取精确的编译命令。

1.3.1.1 生成 make 的输出
选项 1:使用 Bear(推荐)
  1. 安装 Bear
  2. 使用 Bear 运行 make:
    root@kitploit:~
    bear make <所有 make 选项>
    
    示例:bear make -j8

这将在当前目录中生成一个 compile_commands.json 文件。

选项 2

只需传递 V=1 并将输出重定向到文件。 示例:

root@kitploit:~
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1

注意:不要使用多个进程,即 -j。多进程模式会搞乱输出文件,因为多个进程会尝试写入同一个输出文件。

就这样。接下来,在后续步骤中,我们的脚本会使用生成的 makeout.txt,并在所有已识别的驱动上运行接口恢复。

1.3.2 运行接口恢复分析

接口恢复的所有步骤都封装在单个脚本 helper_scripts/run_all.py 中。 如何运行:

root@kitploit:~
cd helper_scripts
python run_all.py --help

usage: run_all.py [-h] [-l LLVM_BC_OUT] [-a CHIPSET_NUM] [-m MAKEOUT]
                  [-c COMPJSON] [-g COMPILER_NAME] [-n ARCH_NUM] [-o OUT]
                  [-k KERNEL_SRC_DIR] [-isclang] [-clangp CLANG_PATH]
                  [-llvmlinkp LLVMLINK_PATH] [-skb] [-skl] [-skp] [-skP]
                  [-ske] [-skI] [-ski] [-skv] [-skd] [-f IOCTL_FINDER_OUT]

optional arguments:
  -h, --help            show this help message and exit
  -l LLVM_BC_OUT        Destination directory where all the generated bitcode
                        files should be stored.
  -a CHIPSET_NUM        Chipset number. Valid chipset numbers are:
                        1(mediatek)|2(qualcomm)|3(huawei)|4(samsung)
  -m MAKEOUT            Path to the makeout.txt file.
  -c COMPJSON           Path to the compile_commands_json generated by Bear.
  -g COMPILER_NAME      Name of the compiler used in the makeout.txt, This is
                        needed to filter out compilation commands. Ex: aarch64
                        -linux-android-gcc
  -n ARCH_NUM           Destination architecture, 32 bit (1) or 64 bit (2).
  -o OUT                Path to the out folder. This is the folder, which
                        could be used as output directory during compiling
                        some kernels.
  -k KERNEL_SRC_DIR     Base directory of the kernel sources.
  -isclang              flag to indicate that clang was used to built the
                        kernel
  -clangp CLANG_PATH    Absolute path to the clang binary (if not provided,
                        the one available in the path will be used)
  -llvmlinkp LLVMLINK_PATH
                        Absolute path to the llvm-link binary (if not
                        provided, the one available in the path will be used)
  -skb                  Skip LLVM Build (default: not skipped).
  -skl                  Skip Dr Linker (default: not skipped).
  -skp                  Skip Parsing Headers (default: not skipped).
  -skP                  Skip Generating Preprocessed files (default: not
                        skipped).
  -ske                  Skip Entry point identification (default: not
                        skipped).
  -skI                  Skip Generate Includes (default: not skipped).
  -ski                  Skip IoctlCmdParser run (default: not skipped).
  -skv                  Skip V4L2 ioctl processing (default: not skipped).
  -skd                  Skip Device name finder (default: not skipped).
  -f IOCTL_FINDER_OUT   Path to the output folder where the ioctl command
                        finder output should be stored.


该脚本会在所有已识别的驱动上构建、链接并运行接口恢复,因此可能需要相当长的时间(45 分钟到 90 分钟)。

该脚本以多处理模式执行以下任务,以充分利用所有 CPU 核心:

1.3.2.1 LLVM 构建
  • 默认启用。

生成的所有位码文件都将放置在通过参数 -l 提供的文件夹中。 此步骤需要相当长的时间,具体取决于你的核心数。 因此,如果你已经完成了此步骤,可以通过传递 -skb 跳过它。

1.3.2.2 将所有驱动位码文件链接到合并的位码文件中
  • 默认启用

此步骤执行链接,它会遍历所有位码文件,识别需要链接的相关位码文件,并将它们(使用 llvm-link)链接到一个合并的位码文件中(该文件将存储在相应的位码文件旁边)。

与上一步类似,你可以通过传递 -skl 跳过此步骤。

1.3.2.3 解析头文件以识别入口函数字段
  • 默认启用。

此步骤在头文件中查找入口点声明,并将其配置存储在 LLVM 构建目录下的 hdr_file_config.txt 文件中。

要跳过:-skp

1.3.2.4 识别所有合并位码文件中的入口点
  • 默认启用

此步骤识别所有驱动合并位码文件中的所有入口点。 输出将存储在 LLVM 构建目录下的 entry_point_out.txt 文件中。

entry_point_out.txt 文件内容示例:

root@kitploit:~
IOCTL:msm_lsm_ioctl:/home/difuze/kernels/pixel/msm/sound/soc/msm/qdsp6v2/msm-lsm-client.c:msm_lsm_ioctl.txt:/home/difuze/pixel/llvm_out/sound/soc/msm/qdsp6v2/llvm_link_final/final_to_check.bc
IOCTL:msm_pcm_ioctl:/home/difuze/kernels/pixel/msm/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c:msm_pcm_ioctl.txt:/home/difuze/pixel/llvm_out/sound/soc/msm/qdsp6v2/llvm_link_final/final_to_check.bc

要跳过:-ske

1.3.2.5 在所有已识别的入口点上运行 Ioctl Cmd Finder
  • 默认启用。

此步骤将在 entry_point_out.txt 文件中的所有入口点上运行主要的接口恢复组件(IoctlCmdParser)。每个入口点的输出将存储在通过选项 -f 提供的文件夹中。

要跳过:-ski

1.4 示例:

现在,我们将展示一个从拥有内核源码到获取接口恢复结果的示例。

我们上传了一个 mediatek 内核 33.2.A.3.123.tar.bz2。 首先下载并解压上述文件。

假设你将上述文件解压到名为 ~/mediatek_kernel 的文件夹中。

1.4.1 构建

安装 Bear 并按照以下步骤操作:

root@kitploit:~
cd ~/mediatek_kernel
source ./env.sh
cd kernel-3.18
# 以下步骤根据内核可能不需要
mkdir out
make O=out ARCH=arm64 tubads_defconfig
# 生成 compile_commands.json
bear make -j8 O=out ARCH=arm64

1.4.2 运行接口恢复

root@kitploit:~
cd <仓库路径>/helper_scripts

python run_all.py -l ~/mediatek_kernel/llvm_bitcode_out -a 1 -c ~/mediatek_kernel/kernel-3.18/compile_commands.json -n 2 -o ~/mediatek_kernel/kernel-3.18/out -k ~/mediatek_kernel/kernel-3.18 -f ~/mediatek_kernel/ioctl_finder_out

上述命令需要一些时间(30 分钟到 1 小时)。

1.4.3 理解输出

首先,所有分析结果都在文件夹 ~/mediatek_kernel/ioctl_finder_out(通过选项 -f 提供的参数) 中,每个入口点会创建一个 .txt 文件,其中包含有关恢复接口的所有信息。

如果你只关心接口的信息而不关心其他内容,我们建议你使用 parse_interface_output.py 脚本。此脚本将接口恢复过程的复杂输出转换为干净的 json 文件,格式统一且清晰。

root@kitploit:~
cd <仓库路径>/helper_scripts
python parse_interface_output.py <ioctl_finder_out_dir> <输出文件夹用于存放 json 文件>

这里的 <ioctl_finder_out_dir> 应该与提供给 -f 选项的文件夹相同,<输出文件夹用于存放 json 文件> 是创建 json 文件的文件夹。

你可以使用对应的 json 文件来恢复相应 ioctl 的接口。

1.4.4 注意事项:

1.4.4.1 选项 -g 的值(仅在使用 makeout.txt 时)

要为选项 -g 提供值,你需要知道用于编译内核的 *-gcc 二进制文件的名称。 一种简单的方法是,在 makeout.txt 中 grep 查找 gcc,你会看到编译器命令,从中可以知道 *-gcc 二进制文件的名称。

对于上面的示例,如果你在示例构建中对 makeout.txt 执行 grep gcc,你会看到很多类似下面的行:

root@kitploit:~
aarch64-linux-android-gcc -Wp,-MD,fs/jbd2/.transaction.o.d  -nostdinc -isystem ...

因此,-g 的值应该是 aarch64-linux-android-gcc。

如果要构建的内核是 32 位的,那么该二进制文件很可能是 arm-eabi-gcc。

对于 Qualcomm(或 msm)芯片组,你可能会看到 *gcc-wrapper.py 而不是 *.gcc,在这种情况下,你应该提供 *gcc-wrapper.py。

1.4.4.2 选项 -a 的值

根据芯片组类型,你需要提供对应的数字。

1.4.4.3 选项 -o 的值

这是在内核构建期间提供给 make 命令的选项 O= 的文件夹路径。

并非所有内核都需要单独的 out 路径。如果你在构建内核时没有提供选项 O,那么在运行 run_all.py 时不应为该选项提供值。

使用 clang 构建的内核

对于使用 clang 构建的内核,除了上述选项外,请指定以下选项(假设你使用了 compile_commands.json):

root@kitploit:~
-isclang -clangp <用于构建内核的 CLANG 路径> -llvmlinkp <LLVM_LINK 路径(将与 clang 位于同一文件夹)>

1.5 后处理

在开始模糊测试之前,我们需要使用我们的研究级别(抱歉)解析器对输出进行一些处理。

这些解析器位于这里。要运行的主脚本是 run_all.py:

root@kitploit:~
$ python run_all.py --help
usage: run_all.py [-h] -f F -o O [-n {manual,auto,hybrid}] [-m M]

run_all options

optional arguments:
  -h, --help            show this help message and exit
  -f F                  Filename of the ioctl analysis output OR the entire
                        output directory created by the system
  -o O                  Output directory to store the results. If this
                        directory does not exist it will be created
  -n {manual,auto,hybrid}
                        Specify devname options. You can choose manual
                        (specify every name manually), auto (skip anything that
                        we don't identify a name for), or hybrid (if we
                        detected a name, we use it, else we ask the user)
  -m M                  Enable multi-device output most ioctls only have one
                        applicable device node, but some may have multiple. (0
                        to disable)

你需要将 -f 传递给 ioctl 分析的输出目录,例如 ~/mediatek_kernel/ioctl_finder_out。

-o 是存储后处理结果的目录。这些将是易于理解的 XML 文件(jpits)。

-n 指定系统在多大程度上依赖我们的设备名称恢复。 如果你不想做任何工作/名称查找,可以指定 auto。 当然,这会导致跳过任何我们未恢复名称的设备。如果你想保持谨慎,不信任我们的任何恢复工作(完全合理),可以使用 manual 选项自行命名每个设备。 hybrid 则是两者的组合——我们会在可能时为你命名设备,并在失败时回退给你。

-m 有时 ioctl 可能对应多个设备(例如 v4l2/subdev ioctl 很常见)。默认情况下支持此功能,但需要用户交互来指定每个设备的设备数量。如果这让你感到烦恼,可以通过传递 -m 0 禁用提示(我们将假定每个 ioctl 对应单个设备)。

运行后,在你的输出文件夹中,每个 ioctl 应该有一个对应的文件夹。

2 模糊测试

2.1 Mango Fuzz

MangoFuzz 是我们的简单原型模糊测试器,基于 Peach(特别是 MozPeach)开发。

它不是一个特别复杂的模糊测试器,但它能发现漏洞。 它也被设计为易于扩展。 该模糊测试器有 2 个组件:模糊引擎和执行器。 执行器可以在这里找到,模糊引擎可以在这里找到。

2.1.1 执行器

执行器在手机上运行,监听模糊引擎将发送给它的数据。

只需为你的手机架构编译它,通过 adb push 推送到手机上,然后使用你想要监听的端口执行即可!

2.1.2 模糊引擎

与 MangoFuzz 交互非常简单。你需要一个 Engine 对象和一个 Parser 对象,将你的引擎传递给 Parser。 然后,使用 Parser 解析 jpits,再运行 Engine。简单吧! 我们提供了一些简单的运行脚本来帮助你入门。

要针对特定驱动程序运行,你可以使用 runner.py,并指定输出目录(由我们的后处理脚本创建)中的一个 ioctl 文件夹。

例如:./runner.py -f honor8/out/chb -num 1000。这将指示 MangoFuzz 对与 chb ioctl/驱动程序相关的所有 ioctl 命令值对运行 1000 次迭代。

如果你想要针对整个设备(手机)运行,可以使用 dev_runner.py。例如:./dev_runner.py -f honor8/out -num 100。 这将持续循环遍历驱动程序文件,每次迭代随机切换,总共运行 100 次迭代。

请注意,在模糊引擎与手机通信之前,你需要使用 ADB 设置端口转发,例如:adb forward tcp:2022 tcp:2022

下载工具