新闻详情

新闻详情

首页 / 资讯中心 / 详情

针对复杂文件格式的 Fuzzing 驱动开发:以 libpng 图像解析为例

发布时间:2026/9/4 22:20:20来源:尧图网络
针对复杂文件格式的 Fuzzing 驱动开发:以 libpng 图像解析为例
针对复杂文件格式的 Fuzzing 驱动开发以 libpng 图像解析为例在底层二进制安全与漏洞挖掘领域复杂文件格式解析器如图像、音频、PDF 以及容器封装格式始终是高危漏洞的高发区。解析器通常包含复杂的解压缩算法如 Deflate、色彩空间转换、分块Chunk校验与动态内存重分配逻辑。一旦输入被精心畸变的数据流极易触发堆溢出Heap Overflow、空指针解引用、整型溢出以及使用后释放UAF。为了高效挖掘此类缺陷基于反馈驱动的内存模糊测试In-Memory Feedback-Driven Fuzzing是目前最高效的工程手段。本文以开源图像解析库libpng为例深入探讨如何编写高性能的 Fuzzing 驱动Harness并配合 Sanitizer 实现高覆盖率测试。文件解析器 Fuzzing 的核心瓶颈与破局思路如果直接采用黑盒命令行模糊测试如通过afl-fuzz调用包含main()的可执行文件测试吞吐量通常只有几十次/秒。其主要性能损耗来自以下三个方面进程创建开销每次测试都要经历fork()与execve()消耗大量系统调用时间。磁盘 I/O 阻塞将变异数据写入物理磁盘或临时文件再由解析器读取磁盘 I/O 成为绝对瓶颈。状态未完全重置如果驱动中存在全局变量残留可能导致前后测试用例相互污染产生难以复现的假崩溃Flaky Crashes。因此现代 Fuzzing 必须采用基于libFuzzer或AFL LLVM Persistent Mode的内存 Harness将每秒执行速度Exec/s提升至数万次。libpng 格式特征与目标解析路径标准 PNG 文件以固定的 8 字节文件签名\x89PNG\r\n\x1a\n开头随后由多个独立 Chunk 组成包括核心关键块IHDR,IDAT,PLTE,IEND以及辅助块tEXt,zTXt,pHYs等。在设计 Harness 时我们的目标是让输入数据流能够尽可能深入地遍历png_read_info、png_read_image以及png_read_end等深层解码逻辑同时避免因浅层格式错误过早退出。高性能内存 Harness 实现libpng 默认提供了通过自定义回调读取内存数据的接口png_set_read_fn。利用该机制我们可以彻底摆脱文件系统直接将 Fuzzer 提供的变异字节切片送入解析器。以下是一个生产级的 libFuzzer 驱动完整实现代码#include stdint.h #include stdlib.h #include string.h #include png.h // 自定义内存读取上下文结构体 struct MemoryReader { const uint8_t *data; size_t size; size_t offset; }; // 内存读取回调函数替换底层 fread 逻辑 static void user_read_data(png_structp png_ptr, png_bytep dst, png_size_t length) { struct MemoryReader *reader (struct MemoryReader *)png_get_io_ptr(png_ptr); if (!reader) { png_error(png_ptr, Read Error: Invalid reader context); return; } // 检查剩余缓冲区长度 if (reader-offset length reader-size) { png_error(png_ptr, Read Error: Unexpected End of Data); return; } memcpy(dst, reader-data reader-offset, length); reader-offset length; } // libFuzzer 标准入口函数 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // 基础过滤PNG 最小合法长度签名 最小 IHDR if (size 8) { return 0; } // 检查 PNG 魔数签名过滤完全无关的数据以加快变异效率 if (png_sig_cmp(data, 0, 8) ! 0) { return 0; } // 初始化读取上下文 struct MemoryReader reader { data, size, 0 }; // 创建 libpng 核心控制结构体 png_structp png_ptr png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { return 0; } png_infop info_ptr png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(png_ptr, NULL, NULL); return 0; } // 设置错误跳转libpng 内部使用 setjmp 处理异常 if (setjmp(png_jmpbuf(png_ptr))) { // 解码异常时释放资源防止内存泄漏干扰 Fuzzer png_destroy_read_struct(png_ptr, info_ptr, NULL); return 0; } // 绑定自定义内存读取回调 png_set_read_fn(png_ptr, reader, user_read_data); // 解析文件头部元数据 png_read_info(png_ptr, info_ptr); // 获取图像核心尺寸与色彩属性 png_uint_32 width, height; int bit_depth, color_type, interlace_type; png_get_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_type, NULL, NULL); // 防御过大尺寸导致的 OOM 耗时限制测试范围为合理尺寸 if (width 2048 || height 2048) { png_destroy_read_struct(png_ptr, info_ptr, NULL); return 0; } // 触发内部格式转换扩展分支 png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_gray_to_rgb(png_ptr); png_read_update_info(png_ptr, info_ptr); // 分配行指针并触发完整像素解码 png_size_t rowbytes png_get_rowbytes(png_ptr, info_ptr); png_bytep *row_pointers (png_bytep *)malloc(sizeof(png_bytep) * height); if (row_pointers) { for (png_uint_32 i 0; i height; i) { row_pointers[i] (png_bytep)malloc(rowbytes); } // 核心目标函数执行逐行解码 png_read_image(png_ptr, row_pointers); // 释放行内存 for (png_uint_32 i 0; i height; i) { free(row_pointers[i]); } free(row_pointers); } // 读取结尾 Chunk 并清理环境 png_read_end(png_ptr, info_ptr); png_destroy_read_struct(png_ptr, info_ptr, NULL); return 0; }编译插桩与 Sanitizer 联动为了能够精确捕捉越界访问OOB与未定义行为必须在编译 Harness 时启用 Clang 提供的 AddressSanitizerASan与 UndefinedBehaviorSanitizerUBSan。1. 编译命令# 编译并开启 ASan、UBSan 与 libFuzzer 支持 clang -O1 -g -fsanitizeaddress,undefined,fuzzer \ -I/path/to/libpng/include \ harness_png.c /path/to/libpng/lib/libpng.a -lz \ -o png_fuzzer2. 种子语料库构建与精简高质量的初始语料Seed Corpus能大幅降低变异引擎探索分支的成本从 libpng 自带的测试套件及公开图片集中提取 50~100 张覆盖各种颜色类型灰度、RGB、索引色、Alpha 通道的合法小尺寸 PNG。使用libFuzzer的-merge1选项对语料库进行覆盖率去重与精简mkdir -p min_corpus ./png_fuzzer -merge1 min_corpus/ raw_seeds/3. 启动并行 Fuzzing# 启动 8 个并行 Worker 开展压力模糊测试 ./png_fuzzer min_corpus/ -workers8 -jobs8 -max_len65536驱动开发避坑指南严格捕获setjmplibpng 遇到非法数据时默认通过longjmp抛出错误。如果 Harness 缺少setjmp错误处理一旦触发解析错误进程会直接异常中止导致 Fuzzer 误判为崩溃。规避全局分配陷阱确保每次进入LLVMFuzzerTestOneInput时所使用的上下文都是局部独立的并在所有退出分支彻底调用释放函数杜绝内存泄漏导致的虚假 OOM。尺寸边界硬约束在 Harness 中显式限制图片分辨率上限如宽/高不超过 2048避免 Fuzzer 生成超大分辨率参数导致测试进程在无意义的巨大数组分配中陷入卡死。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Java工业数据采集实战:JEasyOpc OPC DA客户端开发与避坑指南 2026/9/4 23:08:43

Java工业数据采集实战:JEasyOpc OPC DA客户端开发与避坑指南

简介:本资源是面向Java工业自动化开发者的JEasyOpc OPC通信库完整集成包,专为解决Java应用与OPC服务器(如PLC、SCADA系统)间数据交互难题而设计,适用于过程控制、监控系统开发等场景,尤其适合需快速接入OPC…

阅读更多 →
MATLAB实现SAR成像:从回波信号到雷达图像的完整链路解析 2026/9/4 23:08:43

MATLAB实现SAR成像:从回波信号到雷达图像的完整链路解析

简介:本资源是一份面向雷达信号处理初学者与高校相关专业学生的SAR/ISAR成像算法实践材料,聚焦合成孔径雷达回波建模、多普勒频移分析及逆合成孔径成像核心流程。压缩包仅含1个MATLAB源文件(.m格式),即核心脚本ISAR.m&…

阅读更多 →
3 个场景跑通 FaceFusion:从安装到出片的人脸融合完整实操 2026/9/4 23:08:43

3 个场景跑通 FaceFusion:从安装到出片的人脸融合完整实操

3 个场景跑通 FaceFusion:从安装到出片的人脸融合完整实操 【免费下载链接】facefusion Industry leading face manipulation platform 项目地址: https://gitcode.com/GitHub_Trending/fa/facefusion FaceFusion 是一个开源的人脸融合(face swap…

阅读更多 →
FastGPT 大 PDF 解析实战指南:三步让 GB 级复杂文档进入知识库 2026/9/4 23:08:43

FastGPT 大 PDF 解析实战指南:三步让 GB 级复杂文档进入知识库

FastGPT 大 PDF 解析实战指南:三步让 GB 级复杂文档进入知识库 【免费下载链接】FastGPT FastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and v…

阅读更多 →
WeChatMsg:15分钟把微信聊天记录导出成能搜索、能打印的文件 2026/9/4 23:08:43

WeChatMsg:15分钟把微信聊天记录导出成能搜索、能打印的文件

WeChatMsg:15分钟把微信聊天记录导出成能搜索、能打印的文件 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we…

阅读更多 →
Grok 4.6发布在即:开发者应如何评估模型价值与搭建接入生态? 2026/9/4 23:05:42

Grok 4.6发布在即:开发者应如何评估模型价值与搭建接入生态?

这两年的大模型竞争,已经从“拼参数”走进了“拼牌桌资格”的阶段。每隔几周就有一个新版本登场,Grok 4.6 这个名字出现在牌桌上,并不让人意外,真正值得讨论的是:xAI 手里除了更强的基础模型,还有什么&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞