问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
AFL++工具运行原理与实战分析
硬件与物联网
AFL++(American Fuzzy Lop ++)是一款开源的模糊测试工具,用于发现软件中的漏洞。模糊测试(Fuzzing)是一种自动化的测试技术,旨在通过向软件输入大量随机或伪随机的数据,来发现潜在的安全漏洞或程序崩溃。AFL 是由 Michał Zalewski 开发的,被认为是最流行和有效的模糊测试工具之一。
什么是AFL++ ======== AFL++(American Fuzzy Lop ++)是一款开源的模糊测试工具,用于发现软件中的漏洞。模糊测试(Fuzzing)是一种自动化的测试技术,旨在通过向软件输入大量随机或伪随机的数据,来发现潜在的安全漏洞或程序崩溃。AFL 是由 Michał Zalewski 开发的,被认为是最流行和有效的模糊测试工具之一。 环境安装 ==== 由于 AFL++ 在进行模糊测试时可能对测试环境产生影响,因此推荐在隔离的环境中运行,如 Docker 容器或虚拟机。这种隔离能够有效防止因模糊测试导致的系统不稳定或崩溃等问题,确保主系统的安全性和稳定性。如果使用虚拟机进行测试,建议定期创建快照,以便在测试过程中出现异常时快速恢复到先前的状态。 安装环境: ```php apt-get update && apt-get install -yq gcc make wget curl git vim gdb clang llvm python3 python3-pip bsdmainutils ``` afl++ 下载地址: ```php https://github.com/AFLplusplus/AFLplusplus ``` 如果在解压 ZIP 文件时遇到权限不足的问题,可以将 ZIP 文件转移到 Linux 环境下,使用 `sudo unzip [文件名.zip]` 命令进行解压。这种方法可以有效绕过权限限制。 下载完成后,进入 AFL 文件夹,直接运行命令编译文件。 ```php make && make install ```  当按下 Tab 键时,如果能够正确补全并显示工具名称,则表明编译已成功完成。 AFL++ 设置与编译 =========== 这里实战用nmap程序来演示,如果你要用AFL++去fuzz一个程序,那么就需要下载对应程序的源代码,nmap的源代码在github可以找到 ```php https://github.com/nmap/nmap ``` 解压完后,进入文件夹,这里讲一下特殊的文件  `configure` 文件通常存在于许多开源软件的源代码目录中,是自动配置脚本的一部分,用于准备构建软件。它是使用 GNU Autotools(例如 `autoconf`)生成的脚本,目的是在不同的系统环境下自动配置软件包的编译和安装,afl++会利用这个文件,编译程序时插桩,具体细节在AFL++模糊测试原理处会详细展开说明 使用afl-gcc编译程序 ```php CC=afl-clang-fast ./configure --disable-shared ``` `CC=afl-clang-fast` 表示在运行 `./configure` 时,将使用 `aflafl-clang-fast` 代替系统默认的 C 编译器执行configure文件,`afl-clang-fast` 是 AFL++ 的一个编译器包装器,基于 LLVM 的 `clang` 编译器。相比于 `afl-gcc`,`afl-clang-fast` 使用了更现代的插桩技术,提供了更高效的性能和更精确的代码覆盖率监控 ,`--disable-shared` 选项,可以确保目标程序只编译成静态链接的二进制文件。所有的代码都会被直接链接到生成的二进制文件中,AFL++ 能够插桩并跟踪所有代码的执行路径,而不会遗漏掉因为动态链接而无法插桩的部分 如果之后make编译失败,也可以使用afl-gcc ```php CC=afl-gcc ./configure --disable-shared ```  然后执行make,`make` 是一个构建自动化工具,用于根据 `Makefile` 中的指令来编译和构建程序   如何Fuzz程序命令行参数 ------------- 现在编译完成后,可以使用 AFL++ 进行模糊测试。但需要注意的是,如果不在目标程序中引入 `argv-fuzz-inl.h` 头文件,AFL++ 将默认对程序的标准输入(stdin)进行模糊测试,而不是针对命令行(argv)参数。因此,AFL++ 只会测试程序运行后等待用户输入的部分。如果希望对程序的命令行参数进行模糊测试(例如测试 `nmap` 的 `-iL` 参数),则必须在目标程序的源码中包含 `argv-fuzz-inl.h` 头文件,并对相应代码进行调整,以便 AFL++ 能够正确生成并测试不同的命令行参数组合 argv-fuzz-inl.h文件下载地址: ```php https://github.com/google/AFL/blob/master/experimental/argv_fuzzing/argv-fuzz-inl.h ``` 原理:  这里调用了`afl_init_argv`函数来覆盖`argv`。`argv`是传递给`main`函数的字符串数组,包含程序的命令行参数。因此,无论`afl_init_argv`函数执行了何种操作,最终结果都会覆盖`argv`  随后调用了`read`函数,从标准输入中读取了大量数据  `ptr`是一个指向缓冲区的指针,用于将数据读入其中。接下来,通过`while`循环检查指针所指向的内容是否为非零值。在循环中,指针会递增,并向前移动以处理接下来的数据  在这个循环中还有一个名为`rc`的计数器,它从1开始并在每次迭代时递增。循环开始时,当前指针的位置会被存储在`ret`数组中,以便后续使用  在`while`循环内还有一个嵌套的`while`循环,这个内层循环的作用是检查是否存在空字节,并在发现空字节时递增指针。同时,它会将数据存储在`ret`数组中,继续处理接下来的内容   接下来,函数会创建一个伪造的`argv`结构,并将其返回给主函数。这意味着在`main`函数中获取的`argv`将全部使用由AFL++生成的数据,从而替换原有的命令行数据 下载 `argv-fuzz-inl.h` 文件后,打开目标程序的源代码文件,并在代码的头部加入以下代码行,引入该头文件: nmap的源代码为nmap.cc ```php #include "/{path}/argv-fuzz-inl.h" ``` 其中,`{path}` 应替换为 `argv-fuzz-inl.h` 文件的实际路径。如果文件已放在同一目录下,可以直接使用相对路径,如 `#include "argv-fuzz-inl.h"`  ps:如果需要不fuzz程序的参数,而是直接对 `argv[0]` 进行模糊测试,需要修改argv-fuzz-inl.h源内容 ```php int rc = 0 ```  回到正题,在被fuzz测试程序的main函数第一行加入: ```php AFL_INIT_ARGV(); ```  重新编译文件 ```php CC=afl-gcc ./configure --disable-shared & make ```  编译好的nmap程序就在当前目录下 AFL++进行FUZZ =========== 设置fuzz时输入输出文件夹 ```php mkdir /tmp/in mkdir /tmp/out ``` 在/tmp/in文件夹下是要测试的参数,这里只测试nmap的-iL参数 ```php echo -en "-iL\x00" > /tmp/in/1 ``` `-en` 选项用于确保 `echo` 不添加额外的换行符,并且 `\x00` 表示字符串的结束符(null 终止符) 开始进行fuzz ```php afl-fuzz -i/tmp/in -o /tmp/out ./nmap ``` `-i` 指定输入目录,`-o` 指定输出目录,最后是需要fuzz的程序  如果提示这个,直接输入echo core >/proc/sys/kernel/core\_pattern,然后重新运行即可   最重要的一个区域是findings in depth ```php favored paths: 表示被认为最有可能找到新路径或错误的路径数量,以及占总路径数量的百分比。 new edges on: 显示新路径中发现的边缘数量及其占比。 total crashes: 显示发现的崩溃数量以及其中独特崩溃的数量。 total tmouts: 显示发现的超时数量及其中独特超时的数量。 ``` 如果出现total crashes,那么意味着程序中存在潜在的漏洞 , AFL++会将导致崩溃的输入文件保存到`/tmp/out`目录下,随后可以结合GDB进行调试,以进一步分析并定位问题 多线程可以让fuzz效率变高,在不同的终端里执行以下命令: ```php afl-fuzz -i /tmp/in -o /tmp/out -M f1 ./nmap afl-fuzz -i /tmp/in -o /tmp/out -S f2 ./nmap afl-fuzz -i /tmp/in -o /tmp/out -S f3 ./nmap …… ```  fuzz一次时间比较久,1天都是常见的事 AFL++模糊测试原理 =========== 现在将使用正常gcc编译的nmap和afl-gcc编译的nmap进行对比,这是正常编译的nmap main函数  这是使用afl-gcc编译的nmap main函数  在每个跳转分支中,AFL++插入了`afl_maybe_log`函数。在调用`afl_maybe_log`之前,还存在一个`mov`指令,该指令的作用是设置校准参数。当执行`afl_maybe_log`时,AFL++会记录程序采用了哪个分支。如果在大多数情况下分支指令都是向左执行时,突然发现有一个输入可以触发向右分支,AFL++就知道到达了程序的新路径或功能点,继续对程序进行模糊测试。
发表于 2025-01-13 10:00:00
阅读 ( 825 )
分类:
二进制
0 推荐
收藏
0 条评论
请先
登录
后评论
cike_y
8 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!