news 2026/4/25 15:36:56

CTFshow-PWN-栈溢出(pwn40):64位传参规则与ROP链实战构建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CTFshow-PWN-栈溢出(pwn40):64位传参规则与ROP链实战构建

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链要完成两个关键操作:

  1. 将/bin/sh字符串的地址放入rdi寄存器
  2. 调用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 "ret"

3. 实战构建pwn40的exploit

现在让我们一步步构建pwn40的完整攻击流程。首先用IDA分析程序,我们得到以下关键信息:

  • 栈溢出需要的填充长度:0xA+8字节
  • /bin/sh字符串地址:0x400808
  • system函数地址:0x400520
  • pop rdi; ret gadget地址:0x4007e3
  • ret gadget地址:0x4004fe

payload的结构应该是这样的:

  1. 填充垃圾数据直到覆盖返回地址(0xA+8字节)
  2. pop rdi gadget的地址
  3. /bin/sh字符串的地址(会被pop到rdi)
  4. ret gadget的地址(用于栈对齐)
  5. system函数的地址

用pwntools实现的完整exploit代码如下:

from pwn import * context.log_level = 'debug' p = remote('pwn.challenge.ctf.show', 28286) payload = b'a'*(0xA+8) 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配合pwntools:

gdb -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这样的基础题目中,这些防护通常是被禁用的,但了解它们对实战很重要。建议从简单题目开始,逐步挑战更复杂的场景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 15:36:18

别再只看准确率了!聊聊深度学习模型预测时那个‘心里有底’的置信度

深度学习模型预测中的置信度:超越准确率的决策智慧 在图像识别系统将一只狐狸误判为狗时,模型却以98%的置信度"坚信"自己的错误判断——这种场景对算法工程师来说并不陌生。当我们将深度学习模型部署到医疗诊断、自动驾驶或金融风控等关键领域…

作者头像 李华
网站建设 2026/4/25 15:29:41

BetterNCM插件管理器终极指南:3步打造你的专属音乐播放器

BetterNCM插件管理器终极指南:3步打造你的专属音乐播放器 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 想不想让你的网易云音乐变得更好用?BetterNCM插件管理…

作者头像 李华
网站建设 2026/4/25 15:27:52

DeepSeek_TileKernels源码解析

DeepSeek TileKernels源码解析:GPU计算优化的新范式 前言 DeepSeek近期开源了TileKernels项目,这是一个用TileLang编写的内核库,专门用于GPU计算优化。该项目在GitHub上迅速获得1076+ stars,显示了社区对高性能计算的关注。本文将深入解析TileKernels的设计原理和实现细节…

作者头像 李华