文章

《软件安全》上机实验二

《软件安全》上机实验二

第二次上机作业:课本239页第15题

一、实验内容

综合实验:使用AmericanFuzzy Lop(http://Icamtuf.coredump.cx/afl/)工具挖掘 C/C++程序漏洞。完成实验报告。

二、实验环境

  • 操作系统:Linux
  • 分析工具版本:afl-2.52b

三、实验原理

1.模糊测试

模糊测试是一种自动化的软件测试技术,它的核心思想是向目标程序提供大量非预期的、无效的或随机的输入数据,然后监控程序是否会发生异常,例如崩溃(C rash)、断言失败(Assertion Failure)或内存泄漏(Memory Leak)。这些异常情况通常暗示着程序中存在潜在的安全漏洞,如缓冲区溢出、空指针解引用等。

可以将模糊测试通俗地理解为,像一个“淘气的用户”一样,胡乱地操作软件,看它会不会在某个奇怪的输入下崩溃。

2.American Fuzzy Lop (AFL)

American Fuzzy Lop (AFL)是一种模糊测试(Fuzzing)工具。

传统的模糊测试,是一种黑盒测试,它完全是随机的,效率很低。而AFL是一种覆盖率引导的灰盒模糊测试工具,它并非“盲目”地进行测试,而是有策略地、“聪明”地生成输入数据。AFL工具主要通过两项关键技术编译时插桩和遗传算法实现:

  • 编译时插桩:编译测试程序时,AFL向程序的汇编代码中插入了大量的“探针”,这些探针并不会改变程序的原有逻辑,但它们会记录每一份输入数据执行了程序中的哪些代码路径。当程序运行时,AFL会根据这些探针收集到的信息,绘制出一张“代码覆盖率地图”,AFL由此可以知道,某个输入A覆盖了路径1、2、3,而另一个输入B覆盖了路径 1、3、5。

  • 遗传算法:AFL的测试过程遵循一种类似生物进化的“优胜劣汰”策略:

    1
    2
    3
    4
    
      1. 初始种群:AFL从我们提供的种子文件(afl_in目录)开始。                                                                                     
      2. 变异 (Mutation):对种子文件进行各种微小的、随机的修改(如位翻转、字节替换、数据块的增删改等),产生一批新的输入。                         
      3. 评估 (Evaluation):用新输入去运行被插桩的程序,并利用“眼睛”(插桩代码)观察代码覆盖率。                                                   
      4. 选择(Selection):如果一个新输入能够触发一条前所未见的代码路径,AFL就认为它是一个“有价值的”输入。它会将这个输入保存下来,加入到种子队列中,作为下一轮变异的基础。如果一个输入没有产生任何新路径,它就会被丢弃。
    

    通过这种“发现新路径–>保留–>在此基础上继续变异”的正反馈循环,AFL能够像一个有经验的黑客一样,逐步渗透到程序的深层逻辑中,从而高效地发现隐藏在代码深处的漏洞。

四、实验步骤

1.准备测试项目

MD4C (Markdown for C) 是一个高性能、高符合度的开源Markdown解析器库,完全由C语言编写。它作为一个用C语言实现的复杂文本格式解析器,其代码中包含了大量处理边界情况和复杂逻辑的分支,是检验模糊测试工具(AFL)在真实世界项目中发现潜在漏洞能力的理想案例。

1
2
# 克隆md4c源码仓库
git clone https://github.com/mity/md4c.git

2.配置AFL

步骤1:安装AFL编译依赖

步骤2:下载、解压并编译AFL

3.使用afl编译md4c项目

步骤1:进入md4c目录并创建build目录

步骤2:运行cmake来配置项目

步骤3:执行编译

4.运行模糊测试

步骤1:准备测试用例和目录

AFL需要一个输入目录afl_in,里面放一些“种子”文件(合法的输入),它会基于这些种子进行变异;同时,它还需要一个输出目录afl_out,用来存放测试结果。

1
2
3
4
5
6
7
# 创建输入目录和输出目录
mkdir afl_in 
mkdir afl_out

# 创建一个简单的Markdown测试用例,放入输入目录
echo "# Heading" > afl_in/seed1.md
echo "*bold text*" > afl_in/seed2.md

步骤2:执行AFL模糊测试器

1
2
3
4
5
# afl-fuzz: 启动AFL的主程序                        
# -i afl_in: 指定我们刚创建的输入目录
# -o afl_out: 指定我们刚创建的输出目录      
# ./md4c/build/md2html/md2html: 要测试的、已经被插桩的目标程序# @@: 占位符,AFL在运行时会自动替换成它当前正在测试的文件名
afl-fuzz -i afl_in -o afl_out ./md4c/build/md2html/md2html @@

步骤3:执行结果

经过一个多小时的测试,并未发现崩溃,如下图所示total crashes:0

image-20251204214341498

本文由作者按照 CC BY 4.0 进行授权