AFL++ 的测试入口写法,会影响哪些缺陷能被发现。一份针对 glibc Linux、可取得源码的 C/C++ 程序的技术清单,把关键点分成了几层: ① 检… · @BaiBtw · TwKit
@BaiBtw
AFL++ 的测试入口写法,会影响哪些缺陷能被发现。一份针对 glibc Linux、可取得源码的 C/C++ 程序的技术清单,把关键点分成了几层: ① 检测器的覆盖范围 ASan 与 UBSan 配合断言使用。示例用 -fsanitize=address,undefined,并把错误设为中止、停止,关闭符号化以适配测试。 detect_stack_use_after_return=1 增加返回后栈访问检测,但会增加开销。文中还把新分配内存的模式填充上限从默认 4 KiB 提高到 1 GiB,避免更大区域的未初始化内容掩盖问题。这会让部分未初始化读取更易暴露,不等于 ASan 能检测所有未初始化读取。 libstdc++ 的调试断言能补充越过容器逻辑大小、却仍落在已分配容量内的访问等 ASan 不易看出的错误,但 -D_GLIBCXX_DEBUG 会改变 ABI。 ② 持续运行与用例隔离 persistent mode 在同一进程内循环处理多份输入,减少重复启动开销;示例 __AFL_LOOP(10000) 设置循环上限。 代价是必须处理前一次测试留下的状态:全局变量、strtok 内部状态、未初始化的堆或栈内容。若程序行为依赖地址,分配地址变化也可能让故障难以复现。输入相关内存清零或填入固定模式,是隔离的一部分。 ③ 输入长度不等于底层分配长度 AFL++ 提供的缓冲区可能大于本次 len。直接把它传给目标,读出本次输入边界却仍落在底层分配内,可能躲过 ASan。 示例先复制到按本次长度分配的区域;需要 C 字符串时另留终止零字节。std::string 这类拥有存储的类型,与 std::string_view 这类非拥有视图,不能按同一种内存边界处理。 ④ 缩小并暴露测试入口 把相关 .c 源文件直接纳入测试入口所在的编译单元,可以访问 static 函数及状态,不必只测公开接口;示例还用宏临时改名原 main。它简化了测试用构建,不等于要求生产工程全部采用这种组织方式。 固定缓冲区也可在测试配置里缩小,例如 65536 改为 16,让边界路径更快出现;小配置下的崩溃仍需回到原尺寸构造、验证,不能直接当成原构建已复现。 ⑤ 分清可省略的工作与必须清理的资源 在进程会定期重置、内存开销可控时,测试入口可以省去与目标无关的释放/析构工作;若析构本身就是测试对象,则不能省略。文件描述符等非内存资源仍可能提前耗尽。 arena 统一重置有利于隔离,但前提是相关状态也确实被重置,而不是只清了部分内存。 ⑥ 只有文件路径接口时 Linux 的 memfd_create 可建立内存文件,再通过 /proc/self/fd/<fd> 交给只接收路径的目标。每轮先截断、再用 pwrite 从偏移 0 写入,避免推进文件描述符自身的偏移。相同路径写法在不同进程中指向各自的文件。 示例假定 fd 为 3 并断言;也可以根据实际 fd 构造路径,不能把 3 当成系统保证。 这套方法的共同目标,是让输入边界更可见、用例更独立、测试入口更小。它是特定环境下的测试工程方法,不是通用性能承诺,也不能用“暂时没崩溃”证明程序没有缺陷。
曝光 161 · 评论 2 · 点赞 1 · 书签 0
查看原帖