1.实验内容
-
本次实践的对象是一个名为20145329的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。
-
我们将学习三种方法
1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
3.注入一个自己制作的shellcode并运行这段shellcode。
这几种思路,基本代表现实情况中的攻击目标(1)运行原本不可访问的代码片段(2)强行修改程序执行流(3)以及注入运行任意代码。
2.基础知识
-
管道(|):进程用来通讯的共享内存区域。一个进程往管道中写入信息,而其它的进程可以从管道中读出信息。通常涉及到两个进程:客户进程和服务进程。服务进程负责创建管道。客户进程连接到管道。服务进程可以创建一个管道的多个实例,以此支持多个客户进程。
-
输入重定向(<):输入重定向:是指不使用系统提供的标准输入端口,而进行重新的指定。输入重定向运算符“(<)”可以处理从除键盘外的设备到Windows Vista命令的输入。输入重定向总是用于发送文本文件内容到Windows Vista命令。最常用的示例是MORE命令,其用于每次在屏幕上显示信息。
-
输出重定向:将与标准输出相联系的默认设备改变为另一文件。这就允许命令将结果输出到新关联的文件,而不是输出到显示屏中。
-
Bof的原理:缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量溢出的数据覆盖在合法数据上,理想的情况是 程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间想匹配,这就为缓冲区溢出埋下隐患.操作系统所使用的缓冲区 又被称为"堆栈". 在各个操作进程之间,指令会被临时储存在"堆栈"当中,"堆栈"也会出现缓冲区溢出 。通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其它指令,以达到攻击的目的。造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。
3.实验过程
3.1直接手工修改可执行文件
- 原文件执行结果:输入字符串返回相同内容
- 查看目标文件反汇编代码:
main函数调用foo,对应机器指令为“ e8 d7ffffff”,那我们想让它调用getShell,只要修改“d7ffffff”为,"getShell-80484ba"对应的补码就行。用Windows计算器,直接 47d-4ba就能得到补码,是c3ffffff
- 使用vi修改汇编指令,切换至十六进制显示:
- 修改机器指令call后面的地址为getshell的地址,找到e8 d7修改为e8 c3:
- 退出十六进制显示并保存退出:
- 反汇编查看call指令调用getshell:
- 测试执行代码能够运行getshell:
3.2通过构造输入参数,造成BOF攻击,改变程序执行流
-
缓冲区溢出:可执行文件正常运行是调用如下函数foo,这个函数有Buffer overflow漏洞,利用此漏洞溢出跳转地址,触发getShell函数
-
使用gdb测试溢出出现在字符串中第几位以后:
- 得知溢出出现在字符串中5的位置,进一步测试是其中的哪几位覆盖到返回地址:
- 从上图可知第1到4个字符覆盖到返回地址,并且可以从上图中看出字符在堆栈中是使用大端法存储,使用perl语言将getshell的地址存储到input文件中:
- ,然后将input的输入,通过管道符“|”,作为20145329pwn1的输入运行main函数,正确跳转到getshell得到shell提示符: