SparkCTF pwn赛题解析:堆栈利用与漏洞利用实战
1. SparkCTF v26-pwn赛题解析与实战复盘上周熬夜打完了SparkCTF的pwn方向题目这次v26版本的赛题设计确实有点东西。作为常年混迹CTF赛场的二进制选手我整理了几道典型题目的解题思路WP重点分享两个堆题和一个栈题的突破过程。这些题目完美覆盖了现代pwn题的主流考点从基础的栈溢出到复杂的堆风水利用特别适合想从脚本小子进阶到漏洞艺术家的选手。2. 环境准备与工具链配置2.1 基础调试环境搭建建议使用Ubuntu 20.04 LTS作为基础系统配合以下工具链sudo apt install gdb peda pwntools checksec patchelf对于glibc版本管理推荐用patchelf修改二进制文件的解释器路径。比如遇到题目给的libc版本不一致时patchelf --set-interpreter /path/to/ld.so --set-rpath /path/to/libc ./challenge2.2 增强型GDB配置在~/.gdbinit中添加这些实用命令define hook-stop x/10gx $rebase(0x202060) heap chunks end这个配置会在每次断点时自动显示堆关键区域状态对于分析堆题特别有用。3. 堆利用实战House of Husk解法3.1 题目逆向分析用IDA打开题目文件发现是个典型的菜单堆题有malloc/free/edit/show功能。关键漏洞点在于edit时存在off-by-oneint edit() { unsigned int idx; printf(index: ); idx read_int(); if ( idx 0xF ) return puts(invalid); printf(content: ); return read_until(bss_chunks[idx], sizes[idx] 1, \n); // 多读1字节 }3.2 利用链构建通过以下步骤完成利用先申请0x18和0x28两个chunk实际得到0x20和0x30用off-by-one修改0x30chunk的size为0x61释放这个伪造的0x60chunk进入unsorted bin申请0x58大小触发切割残留main_arena指针在堆上修改指针低字节指向__printf_arginfo_table关键技巧在glibc-2.31下需要先泄露heap地址才能正确伪造fake table3.3 完整exp代码from pwn import * context.archamd64 def add(size,cont): p.sendlineafter( ,1) p.sendlineafter(: ,str(size)) p.sendafter(: ,cont) def edit(idx,cont): p.sendlineafter( ,3) p.sendlineafter(: ,str(idx)) p.sendafter(: ,cont) # 省略部分交互代码... # 触发FSOP payload p64(0)*3 p64(win_addr) edit(2, payload) p.sendlineafter( ,4) # 触发printf4. 栈溢出经典题ROPchain构造艺术4.1 漏洞定位checksec检查发现Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE经典的栈溢出可执行栈场景通过逆向找到gets函数调用点。4.2 利用思路用ROP泄露libc地址二次溢出调用system(/bin/sh)需要处理栈对齐问题movaps指令4.3 动态调试技巧在gdb中这样定位返回地址偏移pattern create 200 r $(cat pattern) x/gx $rsp pattern offset $rsp_value5. 高级堆利用Tcache Poisoning5.1 题目特点分析这次题目增加了沙箱保护禁用了execve。需要结合ORWopen/read/write来读flag。关键漏洞是UAFfree(chunk); // 没有清空指针 edit(chunk); // 仍可写入5.2 利用步骤填满tcache bin释放chunk进入unsorted bin泄露libc用UAF修改tcache的next指针指向_IO_2_1_stdout_修改_IO_write_ptr实现任意地址读最后劫持free_hook为setcontext61实现栈迁移踩坑记录在glibc-2.32及以上版本需要处理指针异或加密6. 常见问题排查指南6.1 堆布局失败现象明明计算好的偏移实际运行时却崩溃 解决方法在gdb中heap bins查看各bin状态vmmap确认内存映射是否预期检查是否遗漏了某些malloc/free调用6.2 ROP链执行异常典型报错movaps XMMWORD PTR [rsp0x40], xmm0 解决方法在system调用前加ret指令调整栈对齐或改用其他gadget如__libc_csu_init中的片段6.3 本地通远程挂可能原因网络延迟导致交互超时添加timeout参数环境变量差异用env -i运行本地程序libc版本偏移不同用DynELF或多次泄露7. 提升pwn能力的训练建议每日一练从pwnable.tw的简单题开始源码分析精读glibc的malloc.c源码武器开发封装自己的pwntools常用函数赛后复盘参加完比赛必须写完整WP我个人的训练方法是建立漏洞模式库把每次遇到的利用技术分类记录。比如堆利用就细分为UAFdouble freeoff-by-oneheap overflow 每种类型保存3-5个典型exp模板实战时快速适配