20242422 2026-2027-1 《网络与系统攻防技术》实验一实验报告
20242422 2026-2027-1 《网络与系统攻防技术》实验一实验报告
1. 基础知识
本次实验为缓冲区溢出基础实验,主要涉及 Linux 下 32 位 ELF 可执行文件、栈结构、函数调用栈帧原理。
- 缓冲区溢出原理:程序使用不安全函数
gets()读取输入,未对输入长度做校验,超出缓冲区的数据会覆盖栈上的 ebp 以及函数返回地址 ret。当函数执行 ret 指令时,CPU 会跳转到被覆盖的地址执行代码。 - objdump 工具:二进制反汇编工具,查看程序汇编指令,获取函数入口地址。
- xxd:十六进制查看与转换工具,可以将二进制文件转为十六进制文本进行修改,再还原回二进制程序。
- GDB:程序调试器,用于断点调试、查看寄存器、内存地址,获取栈地址、偏移量。
- ASLR:地址空间布局随机化,系统安全保护机制,开启时栈地址每次运行都会变化,实验需要临时关闭。
- 小端序:x86 架构存储多字节数据时,低位字节放在低地址,构造 payload 地址时需要按小端序排列。
2. 实验内容
任务一:直接修改机器指令,改变执行流程
任务二:BOF 攻击,覆盖返回地址
任务三:注入 Shellcode,运行任意代码
实验环境:VMware 虚拟机,Kali Linux 系统,32 位 ELF 程序。
3. 实验过程
任务一:静态修改二进制文件
- 使用
objdump -d pwn1_20242422 | grep -A20 -B10 getShell命令反汇编,获取 getShell 函数入口地址0804847d,截图保存。
![alt text]()
- 查看 main 函数汇编代码,main 函数会调用 foo 函数,foo 函数执行完成后 ret 返回 main。目标是修改 foo 函数的返回地址,替换为 getShell 入口地址。
![alt text]()
- 使用 xxd 将 pwn1 二进制转为十六进制文本
pwn1.hex,使用 nano 编辑器打开十六进制文件,找到 foo 函数 ret 对应的返回地址位置,将原有返回地址修改为 getShell 的地址(小端序)。
![alt text]()
![alt text]()
- 执行
xxd -r pwn1.hex > pwn1_mod,将十六进制文件还原为新二进制文件;chmod +x pwn1_mod赋予执行权限,运行./pwn1_mod,成功弹出 shell。
![alt text]()
任务二:栈溢出跳转 getShell
- 分析 foo 函数汇编,foo 函数内部调用危险函数 gets,存在缓冲区溢出漏洞。计算缓冲区到返回地址的偏移长度。
- 构造 payload:填充字符(A)填满缓冲区 + ebp,后面拼接 getShell 函数地址(小端序)。
- 将 payload 输入给 pwn1 程序,覆盖栈上返回地址。当 foo 函数执行 ret 时,CPU 读取被篡改的返回地址,跳转到 getShell 函数,成功获取 shell。
任务三:Shellcode 注入执行
- 执行
sudo sysctl -w kernel.randomize_va_space=0关闭系统 ASLR 地址随机化保护,保证栈地址固定。 - 使用 GDB 调试
gdb ./pwn1_20242422,在 foo 函数断点,运行程序,获取栈上 esp 地址。
![alt text]()
- 编写 Python exp 脚本,构造 payload:填充 A 字符至返回地址偏移,将返回地址改为栈上 shellcode 起始地址,后面拼接 32 位 Linux 系统调用 shellcode。
![alt text]()
- 运行 exp 脚本,将 payload 输入程序,触发栈溢出,程序跳转到栈中 shellcode,执行 shellcode,获取 shell。
![alt text]()
4. 问题及解决方案
- 问题 1:VMware 虚拟机,宿主机和 Kali 之间无法直接拖拽文件,无法把 pwn1 二进制传入虚拟机。
- 解决方案:改用 Python 简易 HTTP 服务传输文件。在宿主机开启 http 服务,Kali 虚拟机使用 wget 命令下载 pwn1 文件。
- 问题 2:虚拟机鼠标卡顿,鼠标指针几乎看不清。
- 解决方案:安装 VMware Tools,虚拟机设置调整鼠标缩放;临时切换虚拟机独占模式。
- 问题 3:修改完十六进制文件,xxd 还原二进制后程序无法运行。
- 解决方案:修改十六进制时,严格核对地址位置,不要改动其他无关字节;还原二进制后,必须执行 chmod +x 添加可执行权限。
- 问题 4:GDB 调试获取地址,直接在 gdb 内执行 shell 命令,命令报错。
- 解决方案:区分 GDB 内命令和系统 bash 命令,shell 命令需要在 GDB 外部终端执行;gdb 内部使用 run、break、x 等调试指令。
- 问题 5:payload 发送后程序没有反应,无法触发溢出,或者报段错误。
- 解决方案:缓冲区偏移量计算错误;重新用 pattern_create、pattern_offset 精确计算溢出偏移;检查地址是否写成大端序,x86 需要小端序。
- 问题 6:ASLR 开启,每次调试栈地址都变化,shellcode 无法稳定执行。
- 解决方案:使用 sysctl 命令临时关闭内核 ASLR 随机化。
5. 学习感悟、思考等
本次缓冲区溢出实验,直观理解了程序栈帧、函数调用和返回地址的底层原理。gets()这类不安全函数不限制输入长度,是栈溢出漏洞的根源。
实验一共三个任务,从静态修改程序,到利用溢出跳转已有函数,最后注入 shellcode 执行自定义代码,层层递进。实验过程中遇到虚拟机文件传输、地址大小端、ASLR 保护、偏移量计算等问题,在排查问题时加深了对漏洞原理、操作系统内存保护机制的理解。
同时也认识到缓冲区溢出漏洞危害巨大,现代操作系统通过 ASLR、栈保护等机制缓解溢出攻击。开发程序时禁止使用 gets、strcpy 等危险函数,做好输入长度校验,从源码层面防止缓冲区溢出。








浙公网安备 33010602011771号