从源码的角度学习 boofuzz 函数的使用
字数 3215 2025-08-22 18:37:14
Boofuzz 源码分析与使用详解
1. Boofuzz 概述
Boofuzz 是一款流行的网络黑盒模糊测试工具,主要用于生成网络协议数据包进行模糊测试。与基于变异的模糊测试不同,Boofuzz 采用基于生成的测试方法,这意味着:
- 不需要收集目标程序的反馈信息(如代码覆盖率)
- 测试用例生成是独立的,新用例与旧用例无直接关系
- 属于纯黑盒测试方法
2. Boofuzz 基本组成结构
Boofuzz 测试用例由三个核心元素构成:
2.1 Request(请求)
- 代表一个完整的测试用例(数据包)
- 使用
self.stack列表存储所有 Block 和 Primitive - 使用
self.block_stack存储当前"打开"的 Block - 使用
self.names字典存储所有 Block 和 Primitive(key 为 qualified_name)
2.2 Block(块)
- 表示多个字段的集合
- 用于对字段组进行统一操作(如计算长度、校验和等)
- 可以嵌套包含其他 Block 或 Primitive
2.3 Primitive(原语)
- 代表数据包中的最小字段单元
- 是测试用例生成的基本单位
- 有多种类型,每种类型有不同的生成策略
三者关系:Request > Block > Primitive
3. Primitive 类型及生成策略
3.1 BitField
- 参数:
width:bit 位宽度(默认8)max_num:最大值(默认None)full_range:是否使用全量数据(默认False)
- 生成策略:
- 全量数据:生成0到指定width能表示的最大值
- 非全量:使用特殊边界值
- 快捷函数:
s_byte/s_char(8位)s_word/s_short(16位)s_dword/s_int/s_long(32位)s_qword/s_double(64位)
3.2 Bytes
- 参数:
size:字节数(None表示任意长度)padding:填充字节(默认\x00)max_len:最大长度(size为None时使用)
- 生成策略:
- 使用特殊值测试溢出
- 重复默认值
- 特殊值替换原始值每个位置
- 根据size和max_len限制长度
3.3 Delim
- 生成策略:
- 重复默认值
- 使用特殊值
3.4 Float
- 参数:
s_format:格式化字符串(默认".1f")f_min:最小值(默认0.0)f_max:最大值(默认100.0)max_mutations:最大生成次数(默认1000)
- 生成策略:
- 使用默认值
- 从f_min到f_max随机取值
3.5 FromFile
- 参数:
filename:文件通配符(如*.txt)max_len:最大长度(默认0)
- 生成策略:
- 使用文件内容
- 根据max_len过滤
3.6 Mirror
- 参数:
primitive_name:目标原语名称
- 生成策略:
- 与目标原语保持一致
3.7 RandomData
- 参数:
min_length:最小长度(默认0)max_length:最大长度(默认1)max_mutations:最大生成次数(默认25)step:长度变化步长(默认None)
- 生成策略:
- 根据长度随机生成0-255字节
3.8 String
- 参数:
size:长度(None表示随机)padding:填充字节(默认\x00)encoding:编码方式(默认ascii)max_size:最大长度
- 生成策略:
- 使用特殊值测试命令注入
- 重复默认值(2、10、100次)
- 使用边界长度
- 特殊长度插入\x00
- 根据max_len和size限制长度
- 快捷函数:
s_cstring:字符串后加\x00
3.9 Group & Simple
- Group参数:
values:取值列表encoding:编码方式(默认ascii)
- Simple参数:
fuzz_values:取值列表
- 生成策略:
- 从列表中顺序取值
- 区别:
- Group用于bytes,Simple用于字符串
3.10 Static
- 固定值,不参与模糊测试
- 快捷函数:
s_statics_raws_unknowns_dunno
3.11 绑定Block的原语
Checksum
- 参数:
block_name:绑定Block名称algorithm:算法(crc32, crc32c, adler32, md5, sha1, ipv4, udp)length:自定义算法时需要endian:大小端ipv4_src_block_name:udp算法需要ipv4_dst_block_name:udp算法需要
- 功能:计算指定Block的校验和
Repeat
- 参数:
block_name:绑定Block名称min_reps:最小重复次数max_reps:最大重复次数step:变化步长(默认1)
- 功能:重复指定Block
Size
- 参数:
block_name:绑定Block名称offset:起始偏移(默认0)length:描述长度的字节数(默认4)endian:大小端output_format:输出格式(bytes或ascii)inclusive:是否包含自身
- 功能:计算指定Block的长度
- 快捷函数:
s_sizes_sizer
4. 核心函数详解
4.1 Request 操作函数
s_initialize
- 定义一个新的Request
- 存储在全局字典
blocks.REQUEST中 - 设置
blocks.CURRENT为当前Request
s_switch
- 切换当前使用的Request
- 修改
blocks.CURRENT
s_get
- 根据name从
blocks.REQUEST获取Request - name为None时返回
blocks.CURRENT
s_update
- 参数:
name:qualified_namevalue:替换值
- 功能:替换指定Primitive的default_value
4.2 Block 操作函数
s_block_start & s_block_end
- 管理
self.block_stack - 用于生成context_path和qualified_name
s_block
- 定义Block
- 支持with语法(自动调用start/end)
- 重要参数:
group:绑定其他Primitive实现联动变化
s_align
- 参数:
modulus:对齐字节数pattern:填充字节
- 功能:使Block按指定字节对齐
- 支持with语法
4.3 其他实用函数
s_binary
- 将16进制字符串转换为字节
- 定义为Static原语
s_lego
- 未文档化,不建议使用
s_hexdump
- 返回字符串的16进制表示
5. 使用示例
HTTP请求示例
s_initialize(name="Request")
with s_block("Request-Line"):
s_group("Method", ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE"])
s_delim(" ", name="space-1")
s_string("/index.html", name="Request-URI")
s_delim(" ", name="space-2")
s_string("HTTP/1.1", name="HTTP-Version")
s_static("\r\n", name="Request-Line-CRLF")
s_string("Host:", name="Host-Line")
s_delim(" ", name="space-3")
s_string("example.com", name="Host-Line-Value")
s_static("\r\n", name="Host-Line-CRLF")
s_static("Content-Length:", name="Content-Length-Header")
s_delim(" ", name="space-4")
s_size("Body-Content", output_format="ascii", name="Content-Length-Value")
s_static("\r\n", "Content-Length-CRLF")
s_static("\r\n", "Request-CRLF")
with s_block("Body-Content"):
s_string("Body content ...", name="Body-Content-Value")
Block绑定Group示例
s_initialize("example")
s_simple("simple_field1", fuzz_values=["a", "b"])
s_group("group_field1", values=[b"\x01", b"\x02"])
with s_block("block1", group="group_field1"):
s_bit_field(0xff, width=8, name="bit_field1")
s_simple("simple_field2", fuzz_values=["x", "y"])
6. 总结
Boofuzz 提供了丰富的原语类型和灵活的测试用例构建方式,通过Request-Block-Primitive的三层结构,可以方便地描述各种网络协议数据包。关键点包括:
- 理解基于生成的模糊测试与基于变异的区别
- 掌握三种核心元素的关系和使用方法
- 熟悉各种Primitive的生成策略和参数
- 善用Block的group参数实现联动变化
- 合理使用校验和、长度计算等绑定Block的原语
通过深入理解这些概念和函数,可以更有效地使用Boofuzz进行网络协议模糊测试。