【时间】2026 年 9 月 23 号,搭 CVE 复现管线
Alpine 3.20.3 chroot 环境(Docker Hub 拉 rootfs 层),clang 17 + compiler-rt ASan 已验证可触发 heap-buffer-overflow。每例四步:chroot 构建 → 运行 PoC → Agent 判定 → 记录结果。
md4c 的 PoC 在 chroot 里构建成功,但 ASan 二进制退出时 rc=134,TimeoutExpired 把整个管线崩了。
坑:LeakSanitizer 的 Die() 调用
ASAN_OPTIONS=detect_leaks=0 无效——LSan 的 fatal 是退出期噪声,ASan 报告本身正常。问题出在 LSan 在进程启动期就读 /proc/<pid>/task(数字 PID 路径),chroot 内不存在。
试过的路线:
detect_leaks=0— 无效,LSan preinit 的 atexit 检查受LSAN_OPTIONS控制,不是ASAN_OPTIONSLD_PRELOAD重定向 shim — 无效,LSan 用的是裸 syscall,不是 libc 函数- proot(ptrace 模拟 chroot + 真实 /proc 透传)— Alpine 无 proot 包,宿主有 gcc+make 但构建 proot 太重
- bind mount 宿主
/proc进 chroot — 被拒,容器无CAP_SYS_ADMIN
修复:二进制补丁
定位 lsan_common.cpp.o 里 CheckForLeaks 的 Die() 调用。字节确认:file offset 0x1674 处 6 字节 ff 15 00 00 00 00 = call Die。
补丁:31 c0 c3 90 90 90(xor eax,eax; ret → CheckForLeaks 返回 false)。
还有一层坑:.rela 里 0x386 处有个过期重定位项会覆盖 ret 字节。修复:把该项设为 R_X86_64_NONE。
补丁固化进 base rootfs,所有后续用例继承。
其他踩的坑
test -x X && X --version在set -e下,当 X 不存在时“侥幸通过”(&&列表中的失败命令不会触发 exit)。IM6 的bin/convert不存在,真正二进制是utilities/magick,但 build_check 判通过。拆成两行修复。- JSON 抽取用
rfind("{")取到最后一个花括号,嵌套对象被截断。改为find("{")+rfind("}")(首个{到末个})。 grep -v空输出退出码 1,mv没执行,清理根本没生效。
经验
- chroot 里跑 ASan,
detect_leaks=0不一定有效——LSan 的 fatal 是/proc读取失败触发的Die(),不是 leak 检测本身。 LD_PRELOAD拦不住裸 syscall,LSan 直接syscall(SYS_...)。- 对编译器生成的
.o文件做定点 NOP 补丁是最后手段,但要先确认.rela里没有过期重定位项会覆盖补丁字节。
🎵 Listening companion