[ pwn 学习 ] CTFshow-pwn24
2026-08-22 20:36:38
pwn24 NX 禁用下的 shellcode
NX 关闭意味着栈上的数据可以被 CPU 当作指令执行,攻击者只需将 Shellcode 写入栈即可获得系统控制权。
1.基础信息

- NX: NX disabled (这意味着 CPU 允许执行栈或数据段上的指令!)
相当于你可以把任何代码直接发给程序,程序都会傻傻地帮你执行(NX 就是数据区和代码区之间的墙。墙没了,你写什么数据,程序就当代码跑了)
- RWX: Has RWX segments (内存中存在既能写又能运行的区域)
2.逆向分析
反编译共 15 个函数。除main和ctfshow外全是库函数/启动代码,不用看
2.1 ctfshow — 漏洞核心
1 | int ctfshow(void) |
三个漏洞点:
| 漏洞 | 说明 |
|---|---|
| 栈溢出 | read(0, v0, 0x100) 读了 256 字节,缓冲区只有 132 字节,溢出 124 字节 (会覆盖空隙区域、旧 ebp、返回地址和部分 main 栈帧 |
| 信息泄露 | puts(v0) ** 打印缓冲区直到遇到\x00,可泄露栈上数据** (如果不填满 132 字节 就会打印出栈上残留的数据,可能泄露 libc地址或者栈地址如果填满且无 \x00,连旧 ebp 和返回地址都会一起打印出来,泄露代码段基址) |
| 代码执行 (核心漏洞) |
return (v0)() ** 直接把你的输入当代码执行** (v0)——数组退化成指针C 语言中,数组名 v0 在表达式中退化为指向首元素的指针,即 v0 的地址 = ebp - 0x8c,指向输入的第一个字节(v0)()——指针当作函数调用等价于 lea eax,[ebp -0x8c];取 v0 首地址call eax;直接跳过去执行相当于直接执行输入的第一条指令 发送 shellcode 即 getshell |
2.2 main — 环境信息
关键信息在这两行 Hint:
1 | * Hint : NX disabled & Has RWX segments |
- NX 关闭 → 栈可执行,直接跑 shellcode
- RWX 段 → 内存可读可写可执行
意味着不需要 ROP,不需要覆盖返回地址,不需要绕过 NX——程序主动跳过去执行你的输入
3.栈帧布局
1 | 格子编号 地址 内容 |
[bp-0x8c]=v0 到旧 ebp 开头的距离=0x8c=140 字节
(v0)()直接跳转到0x00执行,不需要覆盖返回地址
read(0,v0,0x100)
从 v0 标准输入读取 0x100=256字节
但是 v0 只有 132 字节
溢出量:256-132=124字节 超出了缓冲区
这 124 多余字会覆盖掉
v0[132] → 空隙区域
v0[140] ~ v0[143] → saved ebp
v0[144] ~ v0[147] → ★ 返回地址
v0[148] ~ v0[259] → main 的栈帧(继续往上写)
4.Exploit
1 | from pwn import * |
cat ctfshow_flag
1 | /* ===== ctfshow @ 0x80484f6 ===== */ |
相关笔记
栈溢出系列:
- pwn23 —
strcpy溢出 + SIGSEGV 信号劫持(无 NX 也能做) - pwn25 ret2libc 栈溢出利用 (NX 绕过) — NX 开启时无法用 shellcode,需 ret2libc
NX 保护对比:
工具:
pwntools—asm(shellcraft.sh())生成 shellcode