20222318 2024-2025-1 《网络与系统攻防技术》实验一实验报告
一.实验内容
(一)本周学习内容
本周学习了缓冲区溢出的相关原理,包括简单的汇编代码、缓冲区溢出本质、堆栈的工作原理、Shellcode的编写等等。
(二)实验涉及知识点
(1)Linux基本操作:
①熟悉Linux环境:能够在Linux系统中进行基本的文件操作、目录导航,如cd等。
②常用指令理解:如管道(|)、输入、输出重定向(>)、提升命令权限(sudo)等。
(2)缓冲区溢出原理:
①缓冲区溢出原理:本质是数组的生长方向与栈的生长方向相反,且数组调用没有进行越界检查。
②返回地址覆盖:掌握如何通过缓冲区溢出覆盖栈上的返回地址,以控制程序的执行路径。
③堆栈原理:理解堆栈的工作原理,包括数据的压栈和出栈过程。
④返回地址位置:明确在函数调用过程中,返回地址是如何被存储在堆栈上的。
(3)程序汇编与反汇编:
①汇编语言基础:能看懂简单的汇编代码,如指令调用call、数据移动mov等。
②EIP与指令地址:理解EIP(指令指针寄存器)的作用,以及EIP如何操作才能变成call需要的地址。
③objdump工具:会使用objdump工具对程序进行反汇编,以查看其汇编代码。
(4)程序编辑与调试:
①gdb调试器:会使用gdb进行程序的调试,如设置断点、查看寄存器值、内存地址等。
②vi编辑器:掌握vi文本编辑器的使用方法,用于修改代码或编写脚本。
(5)Shellcode相关知识:
①Shellcode编写:了解如何编写或获取一段用于执行特定操作的机器码Shellcode。
②Shellcode注入:掌握将Shellcode注入到目标程序中的方法,以实现特定的攻击效果。
③堆栈可执行设置:了解如何设置堆栈为可执行状态,以便注入的Shellcode能够执行。
④地址随机化关闭:掌握如何关闭地址随机化技术,以稳定地找到目标程序的地址空间。
二.实验过程
(一)任务一:手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
(1)下载并解压缩pwn1文件,通过Xftp传输到Kali虚拟机上
(2)修改主机名(文件名也全程要注意有学号痕迹!)
在命令行页面使用sudo hostnamectl set-hostname 新的主机名
命令将主机名修改为自己的姓名拼音
再重启即可(可手动可用命令sudo reboot
)
(3)反汇编查看pwn1文件的汇编代码,了解这一部分汇编代码的意义以及做的事情(非必须)
反汇编需要进入文件所在文件夹,在该文件夹下进入命令行终端,命令为objdump -d 可执行文件 | more
·~往下查找目标函数,看到main函数第四行“e8 d7ffffff call 804891
·~具体原理:当main函数执行到call
·~所以此处若需直接改动跳转地址,需计算EIP相对于
(4)备份pwn文件并修改备份文件
所需命令如下:
cp pwn1 复制后的文件名
//cp是复制文件命令
vi pwn20222318
//vi+文件名进行修改
//打开文件后显示乱码
:%!xxd
//将文件显示模式切换为16进制模式
/e8 d7
//‘/’为检索命令。此处可换成/d7ff
按i
进入插入模式,修改“d7”为“c3”,按Esc
退出插入模式
再用:%!xxd -r
命令转换回原格式,最后:wq
保存并退出(如果没用root账号登录需要在后面加一个!,如:wq!表示强制执行)
再用反汇编命令objdump -d pwn20222318 | more
查看,修改成功
(5)执行pwn文件,检验是否成功
此时直接执行文件可以直接跳转ShellCode.
其中chmod +x ./可执行文件
是提升文件权限的指令,因为我注册的是普通用户,做什么操作都要提升权限(比如还要用sudo命令)
./pwn
就能执行pwn了
可以看到出现Shell提示符$,任务一完成。
(二)任务二:利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
(1)反汇编了解程序结构
由上图可见foo函数只预留了56字节的缓冲区(0x38=3*16+8=56)【自己的理解:其中sub
是不借位减法指令,在上一行将栈底指针的值赋给栈顶指针,进行整个栈帧的清空、初始化,下一行就对栈顶指针进行操作,为栈中的局部变量预留空间。】,而只要我们输入足够长的字符串,超出部分就会溢出,从而覆盖到返回地址。栈的结构参考如下:
故接下来我们需要看输入字符才能覆盖到返回地址RET(在调试过程中体现为EIP的值),以及具体是哪几个字符的位置可以覆盖到RET
(2)确认输入字符串哪几个字符会覆盖到返回地址
此处需要用到编译、断点功能,顾需要下载编译器gdb。使用sudo apt-get update && sudo apt-get upgrade
升级下载服务包,再用sudo apt-get install gdb
下载gdb。
下载完之后用gdb --version
查看是否下载完成,如上图。
复制一份pwn文件,之后进行编译。使用字符串“8个1,8个2,8个3,8个4,8个5”作为输入,使用如图命令查看各寄存器的值。
可以看到EBP=0x34343434,0x34是ASCII码中的4,又EIP=0x35353535,是ASCII码中的5,可以确定最终覆盖在RET上的数字为5555(前四个)
(3)确认存放顺序是小端还是大端,从而确认如何输入才能将Shell的地址正确覆盖在返回地址上
这次使用字符串“8个1,8个2,8个3,8个4,12345678”作为输入。
可以看到,EIP=0x34333231,即4321,确认为倒序。故等下输入返回地址的时候也需要是倒序。
再用断点验证一下猜想(指导里这么写的,但是我没太看懂这一步有什么用?)
结合反汇编文件中的getshell地址0804847d,故最终应输入“8个1,8个2,8个3,8个4,\x7d\x84\x04\x08......”
(4)构造输入字符串
因为我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先生成包括这样字符串的一个文件。\x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。
xxd是使用十六进制查看input文件的命令,验证输入无误之后可将input文件作为pwn的输入。
可以看见执行pwn文件后出现了命令行,输入指令,可以正常运行,任务二完成。
(三)任务三:注入一个自己制作的shellcode并运行这段shellcode。
(1)做准备工作,为pwn文件放行
下载execstack:在自己的物理机上下载。网址:
下载完之后用Xftp传到虚拟机上,用sudo dpkg -i execstack_0.0.20131005-1+b10_amd64.deb
命令解压缩即可
接着就是输入下图指令(-s设置堆栈可执行,-q查询文件的堆栈是否可执行,echo “0” 关闭地址随机化)
(2)构造要注入的Payload
注:本环节需要开启两个终端,一个用于监听进程运行,一个用于运行进程
打开终端后点击文件一栏内的“新建标签页”即可
在参考资料内找到一段用于攻击的Shellcode:\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\x4\x3\x2\x1\x00
打开一个终端注入这个攻击buf
再打开另一个终端,先用ps -ef | grep pwn20222318-3
查看进程号
可以看见./pwn20222318-3的进程号为47056(因人而异)
再使用gdb调试该进程
通过设置断点,来查看注入buf的内存地址
ret完,就跳到我们覆盖的retaddr那个地方了,在另外一个终端中按下回车,继续执行。
然后完善Shellcode,将分析所得结果填入,以input_shellcode文件作为输出运行。
Shellcode成功运行了,任务三结束。
另:有一个有趣的现象,此时另一个终端也出现了Shellcode的神秘命令行。
三.问题及解决方案
-
问题1:Xftp无法连接上Kali虚拟机,无法传输pwn文件
-
问题1解决方案:使用
sudo vi /etc/ssh/sshd_config
命令修改ssh配置文件,将#TcpForwarding yes这一行以及以下四行的“#”都删去,然后将Gateway改成yes,再用sudo systemctl restart sshd
重启ssh服务,再与Xftp建立连接即可。 -
问题2:用/e8d7命令找对应机器码的时候没找到
-
问题2解决方案:在文件内e8 d7不是连着的,中间有空格,故检索命令中间加个空格就行了。
-
问题3:执行./pwn文件时权限不够
-
问题3解决方案:使用
chmod +x ./pwn
提升权限 -
问题4:关闭地址随机化的时候权限不够,sudo语句不能解决问题
-
问题4解决方案:使用
sudo echo "0" > /proc/sys/kernel/randomize_va_space
命令时,实际上sudo
只提升了echo
命令的权限,而没有提升重定向操作符 > 的权限。因此,这个命令会因为权限不足而失败,故使用sudo sh -c '需要提升权限的命令'
命令进行操作 -
问题5:任务三不知道怎么分析出的堆栈地址
-
问题5解决方案:待解决
四.学习感悟、思考等
这次实验真的很考验实践能力了,很多知识都不仅仅是从课堂上学的,要自己去查每一行代码什么意思,从而去从底层理解缓冲区溢出的原理。这是以前从来没有过的视角,理解起来确实有一点挑战。计算机底层的世界有些晦涩,但也欢迎求知者去探索。我从这次实验学到了很多,也改进了我的学习方法。从以前的只会运用课堂知识去做实验,到现在的主动去网上找大量资料去补全自己的知识网络,我在慢慢习惯大三的学习节奏。希望我能继续克服万难,学好网络攻防!