堆利用入门:从 Exploitarium libssh2 publickey PoC 学任意 free 到 calc

发布时间:2026/9/17 16:07:22
堆利用入门:从 Exploitarium libssh2 publickey PoC 学任意 free 到 calc 堆利用入门从 Exploitarium libssh2 publickey PoC 学任意 free 到 calc【免费下载链接】exploitariumA single archive of public exploit PoCs and vulnerability research writeups. At the time I post these, none have been reported. Feel free to report them yourself and take credit for the CVE if handed out lulz. Please do not abuse these. I do this so to allure people into the field, and Ive always found this is the most efficient way.项目地址: https://gitcode.com/GitHub_Trending/ex/exploitariumlibssh2 publickey 漏洞的堆利用教学本文带你读懂 Exploitarium 仓库里这套 libssh2-publickey-list-calc-poc PoC看它如何一步步把任意 free变成启动 calc.exe 的 RCE。为什么选 libssh2 publickey PoC 当堆利用入门对于想入门**堆利用heap exploitation**的新手最缺的往往不是原理名词而是一个每一步都能对上源码的完整链条。这套 PoC 恰好满足三个条件靶子真实验证目标是 libssh2/libssh2 master 分支的libssh2_publickey_list_fetch()解析器提交e75b4bae3c68a9bde71de1fb6b0fba5b0c716020属于 SSH 公共密钥子系统这条真实数据通路两条链覆盖两类原语32 位演示分配大小回绕64 位演示任意 free 悬挂对象回收正好对应堆利用的两大基本功自带对照组每个 vulnerable 版本都配一个 checked 版本打上修复补丁编译跑一遍就知道补丁为什么有效。⚠️ 本仓库作者声明所有 PoC 均未向厂商报告仅供学习与研究。请勿用于任何未经授权的攻击测试。PoC 目录结构一览打开 libssh2-publickey-list-calc-poc 目录文件分工非常清晰文件作用poc/publickey_win32_heap_groom_calc_repro.cWin32 分配回绕链 harness伪造 SSH 应答流驱动解析器poc/publickey_win64_arbitrary_free_calc_repro.cWin64 任意 free 链 harness本教程主角poc/live_publickey_server.py真实 SSH 服务端Paramiko在真实传输层复现同一原语poc/live_publickey_client_win64.c走真实 SSH 连接的 Win64 客户端replay-calc-poc.py一键回放脚本编译 4 个可执行文件并依次运行evidence/2026-06-25-local-calc-replay.txt本地回放证据calc_launchsuccess等信号SHA256SUMS.txt产物校验和回放时只需设置LIBSSH2_SRClibssh2 源码目录和LIBSSH2_OBJDIR预编译对象目录然后运行python3 replay-calc-poc.pyWindows 直接跑、Linux/macOS 走 Wine。成功信号非常直白x64_vulnerable_calc_exit77、victim_freed1、calc_launchsuccess。漏洞背景publickey 列表解析器做了什么libssh2_publickey_list_fetch()会持续接收 SSH 服务器 publickey 子系统的应答包每收到一条publickey应答就用SSH2_REALLOC()把libssh2_publickey_list数组原地增长一格并把新条目的属性attrs按num_attrs * 20 字节申请一块缓冲区然后循环往里面写字段。问题出在状态机的两个缺口REALLOC 出来的新条目在解析完成前没有清零——里面残留的是堆上旧字节清理函数libssh2_publickey_list_free()盲目信任每个条目的attrs指针一路走到哨兵条目才停。只要攻击者能控制哪条应答先被解析和解析在哪里失败清理路径就会按攻击者摆好的指针释放内存。Win32 链速览分配大小回绕32 位下sizeof(libssh2_publickey_attribute)是 20 字节作者选中num_attrs 0x0ccccccd0x0ccccccd × 20 0x100000004 → 32 位截断后 4 字节一次本该 256MB 的分配回绕成了4 字节的小分配随后的属性循环把name_len / name 指针 / value_len / value 指针 / mandatory 字节一路写到缓冲区外面。harness 只消在偏移 64 字节处预先埋一个受害者回调字溢出把它改写成恶意函数地址回调一执行calc 就起来了。证据文件里attrs_alloc requested4一行就是这条链的铁证。主线Win64 任意 free 链四步拆解64 位下同样的数值不再回绕分配尺寸变 64 位于是作者换用列表清理路径拿到任意 free。整条链可以拆成四步每步都能在上面 Win64 PoC 源码 里找到对应物。第 1 步发送整形version 应答摆好受害者harness 通过自定义的分配回调源码里LIBSSH2_ALLOC_FUNC(app_alloc)那一组接管 libssh2 的 malloc/free每次分配都记进一张指针登记表。随后发送一个大小刻意等于未来 list 分配大小的 version 应答——它会被解析器释放但在堆里留下一个形状正确的空槽槽里残留的旧字节正好像一条 list 条目。第 2 步畸形 publickey 应答触发错误路径再发一条畸形publickey应答让解析在新条目和哨兵初始化之前失败。此时 list 数组刚刚 REALLOC 增长新增条目的attrs字段还躺在上面那个槽的残留字节上——攻击者通过 version 应答的 27 字节偏移处把受害者对象地址精确写进了这个attrs槽位。第 3 步清理函数替你执行任意 free解析失败后libssh2_publickey_list_free()开始遍历条目它读到攻击者摆好的attrs指针于是free(受害者地址)。证据日志里的关键行就是这一步free ptr000001DE60380860 fetch rc-1 num_keys0 victim_freed1注意victim_freed1受害者不是可能被 free而是确凿地被 free 了——这正是任意 free 原语。第 4 步同尺寸分配回收空槽启动 calc空槽释放后harness 发起一次相同尺寸的分配。在演示用的 Windows 进程堆上分配器把这块内存原样还了回来日志中replacement…860与victim地址一致same_as_victim1。harness 把 calc 启动回调写进这块被回收的旧对象等受害者结构里的旧回调再被执行时跳到的就是CreateProcessA(calc.exe)calc_payload_reached callback00007FF76A5118A5 calc_launchsuccess这就是任意 free → UAF 回收 → 回调劫持 → RCE的经典堆利用闭环只是每一步的驱动点全部来自解析器自己的状态机而不是攻击者直接写内存。从本地回放到真实 SSH 传输最能体现教学价值的部分是 live_publickey_server.py 和 live_publickey_client_win64.c前者是一个 Paramiko SSH 服务端接受密码认证、打开 publickey 子系统的同时按剧本发送 version 整形应答和畸形应答后者是一个 Win64 libssh2 客户端只用公开 API连接服务器唯一特殊之处是同样把分配回调接到追踪堆包装器上。客户端把受害者对象钉在0x0000013370000000服务端默认把该地址写入 27 字节偏移恰好对应首条未来 list 条目的attrs字段。握手、认证、清理、回收、calc_launchsuccess全部走的是真实 SSH 传输层——说明原语不依赖伪造的网络环境。修复只有两行却是最好的防御教材对照版 checked 二进制只多了两处硬ening却把两条链同时掐死list 增长成功后memset(list[keys], 0, sizeof(list[keys])) // 新条目先清零 attrs 分配前 num_attrs 超过 SIZE_MAX / sizeof(attr) 时直接拒绝 // 防乘法溢出清零让清理函数拿到的attrs是 NULL 而非残留指针溢出检查让 4 字节回绕分配在入口就被拒。证据文件里x86_checked_calcno_hit、x64_checked_calc_exit0、victim_freed0三行就是这两行代码的价值证明。新手行动清单先读 README 的 Summary 与 Affected code areas 小节对照 libssh2 源码src/publickey.c的 895-908、1049-1110、1158-1161 行区域把 REALLOC、attrs 分配、list_free 三处读通用 replay-calc-poc.py 在本地跑通 vulnerable/checked 四组对照逐行对照 evidence/2026-06-25-local-calc-replay.txt 理解victim_freed、same_as_victim、calc_launch的含义精读 Win64 PoC 里victim结构、track_ptr/untrack_ptr登记表与launch_calc_callback把任意 free 之后谁把空槽拿回来想清楚挑战题把 live 服务端/客户端在本地127.0.0.1跑通体会真实传输层与本地 wire 缓冲的区别。堆利用的难点从来不在free 一个指针而在让受害者的形状、位置和生命周期都落在剧本里——这套 PoC 把这三件事分别演示了一遍是很好的第一块基石。 再次提醒本 PoC 仅供漏洞研究与学习请勿对任何未授权目标使用。【免费下载链接】exploitariumA single archive of public exploit PoCs and vulnerability research writeups. At the time I post these, none have been reported. Feel free to report them yourself and take credit for the CVE if handed out lulz. Please do not abuse these. I do this so to allure people into the field, and Ive always found this is the most efficient way.项目地址: https://gitcode.com/GitHub_Trending/ex/exploitarium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考