20192425 2021-2022-2 《网络与系统攻防技术》实验一实验报告
1.实验内容
对一个名为pwn1的Linux可执行文件进行一些操作,实现如下:
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode。
本实验要求掌握基础汇编指令的机器码,学习运用反汇编技术与十六进制编程器,掌握如何修改机器指令从而改变程序执行流程,正确构造playload进行BOF攻击。
2.实验过程
1.直接修改程序机器指令,改变程序执行流程
call指令是计算机转移到调用的子程序。
main函数调用foo,对应机器指令为“ e8 d7ffffff”,
那我们想让它调用getShell,只要修改“d7ffffff”为
"getShell-80484ba"对应的补码就行。
用Windows计算器,直接 47d-4ba就能得到补码,是c3ffffff。
下面我们就修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff。
root@KaliYL:~# cp pwn1 pwn2
root@KaliYL:~# vi pwn2
以下操作是在vi内
1.按ESC键
2.输入如下,将显示模式切换为16进制模式
:%!xxd
3.查找要修改的内容
/e8d7
4.找到后前后的内容和反汇编的对比下,确认是地方是正确的
5.修改d7为c3
6.转换16进制为原格式
:%!xxd -r
7.存盘退出vi
:wq
常用的三种保存方式:
退出编辑: :q
强制退出: :q!
保存并退出: :wq
以上编辑操作也可以在图形化的16进制编程器中完成。在图形化界面可以更容易找到并修改。
2.通过构造输入参数,造成BOF攻击,改变程序执行流
知识要求:堆栈结构,返回地址 学习目标:理解攻击缓冲区的结果,掌握返回地址的获取 进阶:掌握ELF文件格式,掌握动态技术
-
通过反汇编,了解程序的基本功能
objdump -d pwn20192425 | more
-
确认输入字符串哪几个字符会覆盖到返回地址
如果输入字符串1111111122222222333333334444444412345678,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。
-
确认用什么值来覆盖返回地址
通过反汇编时可以看到getShell的内存地址。
确认字节序。
-
构造输入字符串
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
原理分析
通过在foo函数中,利用堆栈的相关知识,构造注入攻击。所构造的字符串前28个字符会放在给他预留的空间中,然后4个字符会放在EBP中,核心在于将放在返回地址修改为getshell的地址,即可完成攻击。
Perl语言
Perl一种功能丰富的计算机程序语言,运行在超过100种计算机平台上,适用广泛,从最初是为文本处理而开发的,现在用于各种任务,包括系统管理,Web开发,网络编程,GUI开发等。
Perl易于使用、高效、完整,而不是美观(小巧,优雅,简约)。同时支持过程和面向对象编程,对文本处理具有强大的内置支持,并且拥有第三方模块集合之一。 Perl借取了C、sed、awk、shell脚本语言以及很多其他程序语言的特性,其中最重要的特性是它内部集成了正则表达式的功能,以及巨大的第三方代码库CPAN。
在本次实验中由于我们无法通过键盘直接输入16进制,所以我们使用输出重定向">"将Perl生成的字符串存储到文件input中。
3.注入Shellcode并执行
shellcode是一段用于利用软件漏洞而执行的代码,shellcode为16进制的机器码,因为经常让攻击者获得shell而得名。shellcode常常使用机器语言编写。 可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。
关闭地址随机化
echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
也可以采用可视化图形界面的方式关闭地址随机化。关闭地址随机化 (/proc/sys/kernel/randomize_va_space=0)。
构造要注入的payload
Linux下有两种基本构造攻击buf的方法:
- retaddr+nop+shellcode
- nop+shellcode+retaddr。
nop一为是了填充,二是作为“着陆区/滑行区”。
我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。
打开一个终端注入这段攻击buf,再开另外一个终端,找到pwn20192425的进程号。用gdb来调试pwn20192425这个进程。
由于shellcode里有push操作,会覆盖我们本身的指令,导致我们实验失败,所以我们采用anything + retaddr + nop +shellcode,保证nop在shellcode之前,保证“滑行区”在shellcode前面。
通过观察构造anything+retaddr+nops+shellcode进行注入。
call指令
当执行LCALL时,把该语句的IP(或者说PC)压入堆栈,开始进入子程序DELAY,当执行到RET时,堆栈中的IP出栈,LCALL的继续执行下一条语句。一般来说,执行一条CALL指令相当于执行一条PUSH指令加一条JMP指令。call指令是调用子程序,后面紧跟的应该是子程序名或者过程名。
leave指令
leave是汇编语言中用来关闭栈帧的指令名,通常用于函数末尾。
在16位汇编下相当于:
mov sp,bp
pop bp
在32位汇编下相当于:
mov esp,ebp;//将ebp指向(ebp内部应当保存一个地址,所谓指向即这个地址对应的空间)的值赋给esp
pop ebp
/* leave指令将EBP寄存器的内容复制到ESP寄存器中,以释放分配给该过程的所有堆栈空间。然后,它从堆栈恢复EBP寄存器的旧值。*/
输入/输出重定向
- command > file 将输出重定向到 file。
- command < file 将输入重定向到 file。
- command >> file 将输出以追加的方式重定向到 file。
- n > file 将文件描述符为 n 的文件重定向到 file。
- n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
- n >& m 将输出文件 m 和 n 合并。
- n <& m 将输入文件 m 和 n 合并。
- << tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
Linux管道符|命令
“|”是Linux管道命令操作符,简称管道符。使用此管道符“|”可以将两个命令分隔开,“|”左边命令的输出就会作为“|”右边命令的输入,此命令可连续使用,第一个命令的输出会作为第二个命令的输入,第二个命令的输出又会作为第三个命令的输入,依此类推。
cat命令
cat(英文全拼:concatenate)命令用于连接文件并打印到标准输出设备上。
3.问题及解决方案
- 问题1:虚拟机中没有安装gdb
-
问题1解决方案:通过上网查询后进行安装,在过程中遇到遇到包依赖关系等问题,通过提示相关命令顺利安装。
apt-get update apt-get install gdb Do you want to continue? [Y/n] y
-
问题2:没有关闭地址随机化
-
问题2解决方案:如果不关闭地址随机化,会使得加载程序的时候不再使用固定的基址,从而干扰Shellcode定位
ASLR(Address Space Layout Randomization,地址空间布局随机化)是一种针对缓冲区溢出的安全保护技术。借助ASLR,PE文件每次加载到内存的起始地址都会随机变化。
ASLR虽然增加了编写恶意代码的难度,但是仍存在很多绕过方式,如攻击未启用ASLR的模块、堆喷射(HeapSpray)、覆盖部分返回地址、Java applet heap spray等。因此,想要真正防御缓冲区溢出,还需要综合使用多种安全保护技术。
4.学习感悟、思考等
本次实践内容,代表了现实情况中的可能会遇到的攻击情况,包括
1.运行原本不可访问的代码片段
2.强行修改程序执行流
3.以及注入运行任意代码。
通过本次实验我们可以发现,本次实验是在很多预设条件下进行的,比如需要我们手动关闭地址随机化,而现在大部分主流操作系统都已经实现了地址空间布局随机化,如Windows Vista、Linux 2.6.12、Mac OS X 10.7、iOS 4.3以及Android 4.0均从此版本开始支持ASLR。由此可见,在现实情况要比我们实验的环境要更加复杂,我们需要学好理论知识基础,才能应对更加复杂的实际情况。
本次实验中很多东西都是老师直接提供给我们的,比如Shellcode,实现的是获得Shell这个功能,如果需要通过自己编写shellcode实现其他的功能,还需要我们对Shellcode的相关知识进行更加深入的学习。