PWN 的一次学习笔记
一、静态逆向分析(IDA):定位漏洞点
将目标文件拖入 IDA Pro,重点分析vulnerable函数,发现核心漏洞:
危险函数:使用gets()函数读取输入,gets()无输入长度限制,可导致栈溢出(超过变量缓冲区 8 字节的部分会覆盖栈上的其他数据,包括返回地址)。
漏洞函数截图:
1. 启动调试与设置断点
将文件放入 GDB(推荐使用 Pwndbg 插件增强调试体验),执行以下命令:
调试启动截图:
断点设置与运行截图:
2. 单步执行到漏洞函数
用n(next)命令单步执行 main 函数,直至调用vulnerable函数;
用s(step)命令进入vulnerable函数内部(跟进函数调用)。
单步执行截图:
3. 测试溢出与查看栈结构
步骤 1:输入测试数据(8 个 A)
在gets()函数等待输入时,输入AAAAAAAA(8 个 A,刚好填满变量缓冲区),然后继续执行:
# 输入8个A
AAAAAAAA
# 单步执行完gets()
n
输入测试数据截图:
步骤 2:查看栈布局
使用stack N命令查看栈的前 N 项(本题查看 24 项,足够覆盖缓冲区、EBP 和返回地址):
stack 24
栈结构截图:
步骤 3:分析栈关键区域
EBP(栈基指针):指向前一个函数的 EBP 值(栈中保存的 EBP),是栈溢出的 “分界点”;
返回地址:EBP 下方(内存地址更高)的 4 字节数据,即函数执行完后要跳转的地址(本题中vulnerable函数默认返回main+93地址);
可控区域:EBP 上方(内存地址更低)的缓冲区,输入数据可覆盖此区域,超过缓冲区的部分会覆盖 EBP 和返回地址。
栈区域分析截图:
默认返回地址(main+93)截图:
4. 确定溢出偏移量
通过调试发现:
缓冲区大小:8 字节(变量占用);
EBP 占用:4 字节;
总偏移量:8(缓冲区) + 4(EBP) = 12字节?不,后续通过 IDA 进一步确认:实际缓冲区到返回地址的偏移为16 字节(缓冲区) + 4 字节(EBP) = 20 字节(以最终 Payload 构造为准)。
三、Payload 构造(Python + Pwntools):实现栈溢出攻击
1. 工具准备与环境连接
使用pwntools库编写攻击脚本,首先导入模块并建立与目标程序的连接(本地调试时用process,远程攻击时用remote):
脚本初始化截图:
2. 接收程序输出(可选)
若程序启动时有提示信息,用recvline()接收,避免干扰后续输入:
3. 确定 Payload 结构
通过 IDA 和 GDB 调试确认:
偏移量:16 字节(缓冲区) + 4 字节(EBP) = 20 字节(需用垃圾数据填充);
目标地址:getshell()函数的起始地址(从 IDA 中获取,本题为0x8048522);
打包地址:用p32()将 32 位地址打包为字节型数据(适配小端序)。
Payload 结构:
Payload 构造分析截图:
getshell()函数地址截图(IDA 中查看):
4. 发送 Payload 并获取 shell
5. 本地测试结果
发送 Payload 后,成功获取本地 shell,执行ls、pwd等命令验证权限:
四、远程攻击:实战利用
将本地调试通过的脚本修改为远程连接模式,替换process为remote:
远程攻击脚本截图:
执行脚本后,即可获取远程服务器的 shell 权限,实现远程控制。
核心总结
漏洞定位:静态逆向(IDA)找危险函数(gets)和后门函数(getshell);
偏移计算:动态调试(GDB)确定缓冲区到返回地址的偏移量;
Payload 构造:垃圾数据填充偏移 + 目标函数地址(打包为字节型);
权限获取