二进制漏洞利用与挖掘_二进制各种漏洞原理实战分析总结

本部分将对常见的二进制漏洞做系统分析,方便在漏洞挖掘过程中定位识别是什么类型漏洞,工欲善其事,必先利其器。

0x01栈溢出漏洞原理

栈溢出漏洞属于缓冲区漏洞的一种,实例如下:

编译后使用windbg运行

直接运行到了地址0x41414141,这个就是字符串AAAA,就是变量str里面的字符串通过strcpy拷贝到栈空间时,没有对字符串长度做限制,导致了栈溢出,最后覆盖到了返回地址,造成程序崩溃。

溢出后的栈空间布局如下:

栈溢出原理图

0x02 堆溢出漏洞原理

使用以下代码演示堆溢出漏洞

由于调试堆和常态堆的结构不同,在演示代码中加入getchar函数,用于暂停进程,方便运行heapoverflowexe后用调试器附加进程。debug版本和Release版本实际运行的进程中各个内存结构和分配过程也不同,因此测试的时候应该编译成release版本。

运行程序,使用windbg附加调试(一定要附加调试),g运行后程序崩溃

上面的ecx已经被AAAA字符串覆盖掉了,最后在引用该地址的时候导致崩溃,通过前面的栈回溯定位到了main函数入口,找到复制字符串的函数下断点

此时堆块已经分配完毕,对应的分配地址位于0x007104a0,0x007104a0是堆块数据的起始地址,并非堆头信息的起始地址,对于已经分配的堆块,开头有8字节的HEAP_ENTRY结构,因此heap的HEAP_ENTRY结构位于0x007104a0-8=0x710498。

在windbg上查看两个堆块的信息,这两个堆块目前处于占用状态,共有0x10大小空间

在windbg中,使用!heap查看HeapCreate创建的整个堆块信息,可以发现堆块heap后面还有一个空闲堆块0x007104c0:

在复制字符串的时候,原本只有0x10大小的堆块,填充过多的字符串的时候就会覆盖到下方的空闲堆块007104c0,在复制前007104c0空闲堆块的HEAP_FREE_ENTRY结构数据如下:

覆盖后0x007104c0空闲块的HEAP_FREE_ENTRY结构数据如下:

整个空闲堆头信息都被覆盖了,包括最后的空闲链表中的前后向指针都被成了0x41414141,后面调用HeapFree释放堆块的时候,就会将buf2和后面的空闲堆块0x007104c0合并,修改两个空闲堆块的前后向指针就会引用0x41414141,最后造成崩溃。

如果把上面释放堆块的操作换成分配堆块HeapAlloc(),也会导致崩溃,因为在分配堆块的时候会去遍历空闲链表指针,会造成地址引用异常,当内存中已经分配多个堆块的时候,可能覆盖到的就是已经分配到的堆块,此时可能就是覆盖HEAP_ENTRY结构,而不是HEAP_FREE_ENTRY结构。

堆溢出原理图

0x03 堆调试技巧

微软提供了一些调试选项用于辅助堆调试,可以通过windbg提供的gflag.exe或者!gflag命令来设置:

对heapoverflow.exe添加堆尾检查和页堆,去掉堆标志:

堆尾检查

主要是在每个堆块的尾部,用户数据之后添加8字节,通常是连续的2个0xabababab,该数据段被破坏就可能发生了溢出。

对heapoverflow.exe开启hpc和htc,用windbg加载对heapoverflow程序,附加进程无法在堆尾添加额外标志,使用以下命令开启堆尾检查和堆参数检查:

执行命令g后,按下回车键程序会断下来

上面一句调试输出信息的意思是,在大小为0x10的堆块0x001E0498的0x001E04B0覆盖破坏了,0x10大小的空间加上堆头的8字节一共0x18字节,0x001E04B0-0x001E0498=0x18,也就是说0x001E04B0位于堆块数据的最后一个字节上,基于上面的信息,可以分析出程序主要是因为向0x10的堆块中复制过多数据导致的堆溢出。

页堆

在调试漏洞的时候,经常需要定位导致漏洞的代码和函数,比如导致堆溢出的字节复制指令rep movsz等,前面的堆尾检查方式主要是堆被破坏的场景,不利于定位导致漏洞的代码。为此。引入了页堆的概念,开启后,会在堆块中增加不可访问的栅栏页,溢出覆盖到栅栏页就会触发异常。

开启页堆:

用windbg加载heapoverflow,运行!gflag命令开启了页堆,然后g运行后在cmd按下回车键断下

可以发现程序在复制A字符串的时候触发了异常,程序复制到0x11字节的时候被断下,此时异常还未破坏到堆块,直接定位导致溢出的复制指令rep movs

根据栈回溯,调用rep movs的上一层函数位于image00400000+0x1084的上一条指令,也就是00401322,此处调用了00401000函数,很容易发现这是主入口函数:

0x04整数溢出漏洞原理

整数分为有符号和无符号两类,有符号数以最高位作为符号位,正整数最高位为1,负整数最高位为0,不同类型的整数在内存中有不同的取值范围,unsigned int = 4字节,int = 4字节,当存储的数值超过该类型整数的最大值就会发生溢出。

在一些有符号和无符号转换的过程中最有可能发生整数溢出漏洞。

基于栈的整数溢出

基于栈的整数溢出的例子:

代码中size变量是无符号短整型,取值范围是0~65535,输入的值大于65535就会发生溢出,最后得到size为4,这样会通过边界检查,但是用memcpy复制数据的时候,使用的是int类型的参数i,这个值是输入的65540,就会发生栈溢出:

基于堆的整数溢出

基于堆的整数溢出的例子:

代码中的size是unsigned short int类型,当输入小于5,size减去5会得到负数,但由于unsigned short int取值范围的限制无法识别负数,得到正数65533,最后分配得到过大的堆块,溢出覆盖了后面的堆管理结构:

0x05 格式化字符串漏洞原理

格式化漏洞产生的原因主要是对用户输入的内容没有做过滤,有些输入数据都是作为参数传递给某些执行格式化操作的函数的,比如:printf,fprintf,vprintf,sprintf。

恶意用户可以使用%s和%x等格式符,从堆栈和其他内存位置输出数据,也可以使用格式符%n向任意地址写入数据,配合printf()函数就可以向任意地址写入被格式化的字节数,可能导致任意代码执行,或者读取敏感数据。

以下面的代码为例讲解格式化字符串漏洞原理:

可以发现当输入数据包含%s和%x格式符的时候,会意外输出其他数据:

用ollydbg附加调试程序,执行前需要先设置命令行参数,调试-参数-命令行:test-%x

在运行程序后,传递给printf的参数只有test-%x,但是他把输入参数test-%x之后的另一个栈上数据当做参数传给了printf函数,因为printf基本类型是:

传递给printf的参数只有一个,但是程序默认将栈上的下一个数据作为参数传递给了printf函数,刚好下一个数据是strcpy()函数的目标地址,就是buff变量,buff刚好指向test-%x的地址0x0019fec4,所以程序会输出0x0019fec4,如果后面再加一个%x就会将src参数的值也输出了,这样就可以遍历整个栈上数据了。

除了利用%x读取栈上数据,还可以用%n写入数据修改返回地址来实现漏洞利用。

0x06 双重释放漏洞原理

Double Free漏洞是由于对同一块内存进行二次释放导致的,利用漏洞可以执行任意代码,编译成release示例代码如下:

在二次释放p2的时候就会发生程序崩溃,但是并不是每次出现Double Free都会发生崩溃,要有堆块合并的动作发生才会发生崩溃

双重释放原理图

在释放过程中,邻近的已经释放的堆块存在合并操作,这会改变原有堆头信息,之后再对其地址引用释放就会发生访问异常。

0x07释放后重引用漏洞原理

通过以下代码理解UAF漏洞原理:

buf2 “占坑”了buf1 的内存位置,经过UAF后,buf2被成功篡改了

程序通过分配和buf1大小相同的堆块buf2实现占坑,似的buf2分配到已经释放的buf1内存位置,但由于buf1指针依然有效,并且指向的内存数据是不可预测的,可能被堆管理器回收,也可能被其他数据占用填充,buf1指针称为悬挂指针,借助悬挂指针buf1将内存赋值为hack,导致buf2也被篡改为hack。

如果原有的漏洞程序引用到悬挂指针指向的数据用于执行指令,就会导致任意代码执行。

在通常的浏览器UAF漏洞中,都是某个C++对象被释放后重引用,假设程序存在UAF的漏洞,有个悬挂指针指向test对象,要实现漏洞利用,通过占坑方式覆盖test对象的虚表指针,虚表指针指向虚函数存放地址,现在让其指向恶意构造的shellcode,当程序再次引用到test对象就会导致任意代码执行。

UAF漏洞利用原理图

0x08 数组越界访问漏洞

先区分一下数组越界漏洞和溢出漏洞:数组越界访问包含读写类型,溢出属于数据写入;部分溢出漏洞本质确实就是数组越界漏洞。

数组越界就像是倒水的时候倒错了杯子,溢出就像是水从杯子里溢出来。

下面代码为例分析数组越界访问漏洞:

执行生成的程序,然后分别输入12345,输出结果如上,当输入的数组下标分别是12的时候,会得到正常数值,但是从索引3开始就超出了原来的数组array的范围,比如输入5,就会数组越界访问array数组,导致读取不在程序控制范围内的数值。

使用ollydbg调试发现array[5]就是从array开始的第六个数据0x4012A9,已经读取到了array之外的数据,如果越界访问距离过大,就会访问到不可访问的内存空间,导致程序崩溃。

0x09类型混淆漏洞原理

类型混淆漏洞(Type Confusion)一般是将数据类型A当做数据类型B来解析引用,这就可能导致非法访问数据从而执行任意代码,比如将Unit转成了String,将类对象转成数据结构。

类型混淆漏洞是现在浏览器漏洞挖掘的主流漏洞,这类漏洞在java,js等弱类型语言中非常常见。

下面的代码,A类被混淆成B类,就可能导致私有域被外部访问到:

class A {

private int value;

};

class B {

public int value;

};

B attack = AcastB(var); //将A类型混淆转成B类型

attack.value = 1; //导致可以访问私有域

以IE/Edge类型混淆漏洞(CVE-2017-0037)为例讲解,漏洞原因是函数处理时,没有对对象类型进行严格检查,导致类型混淆。

PoC如下:在PoC中定义了一个table,标签中定义了表id为th1,在boom()中引用,然后是setInterval设定事件。

运行PoC,用Windbg附加并加载运行出现崩溃

从崩溃点可以看到eax作为指针,引用了一个无效地址,导致崩溃,而上一条指令是一个call,这个无效的返回值来自这个call,在这个call处下断点,ecx作为参数,存放的对象是一个Layout::FlowItem::`vftable虚表

这里读取虚表中+4的值,为0时this指针赋值v1,随后v1+16后返回,因此,Layout::FlowItem::`vftable所属指针的这个情况是正常的,函数会正常返回进入后续处理逻辑

让程序继续运行,会再次调用该函数,此时ecx并不是一个虚表对象,而是一个int Array对象,这里我们可以通过条件断点来跟踪两个对象的创建过程,重点关注两个对象创建的函数,一个是FlowItem::`vftable对应的虚表对象,另一个是引发崩溃的int Array对象。这两个函数的返回值,也就是eax寄存器中存放的指向这两个创建对象的指针。

通过跟踪可以看到第一次调用Readable函数时ecx是一个正常的FlowItem对象,而第二次调用的时候ecx是一个int Array Object。Layout::Patchable >::Readable函数是处理虚表对象的函数,由于boom()函数中引用th1.align导致Readable函数得到第二次引用,由于没有进行对象属性检查,导致第二次调用时将table对象传入,最终发生类型混淆崩溃。

0x10竞争条件漏洞原理

竞争条件(Race Condition)是由于多个线程/对象/进程同时操作同一资源,导致系统执行违背原有逻辑设定的行为,这类漏洞在linux,内核层面非常多见,在windows和web层面也存在。

互斥锁的出现就是为了解决此类漏洞问题,保证某一对象在特定资源访问时,其他对象不能操作此资源。

比如如下代码:

执行结果如下:

按照我们的预想,结果应该都是10,但是发现结果可能存在非预期解,原因就在于我们没有对变量COUNT做同步制约,导致可能Thread-7在读COUNT,还没来得及更改COUNT,Thread-8抢夺资源,也来读COUNT,并且将COUNT修改为它读的结果+1,由此出现非预期。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle入门(十四H)之良好的编程实践

一、为什么要学习它 好的编程实践是技巧,可以按照创建最好的代码可能。 编程实践涵盖了一切从代码更多可以用更快的速度创建代码性能。 软件工程团队通常会遵循风格指导让团队中的每个人使用相同的技术。 这使它更容易阅读和修改编写的代码其他。二、编程实践已经学…

微软.NET 正式劈腿成功,横跨所有平台

.NET官方博客宣布了《Announcing .NET Core RC2 and .NET Core SDK Preview 1》,正式如期发布了.NET Core RC2, 现在可以放心的基于.NET Core 构建 ASP.NET Core, console apps 和 class libraries for Windows, OS X and Linux。这里贴张图表达下他们之间的关系: …

2.BIO与NIO区别

【README】 1.本文总结自B站《netty-尚硅谷》,很不错;2.本文介绍 BIO, NIO的知识;【1】BIO(传统java IO模型) 1)BIO-Blocking IO:同步阻塞,服务器实现模式为一个连接一…

k8s往secret里导入证书_K8S之Secret

简介secret顾名思义,用于存储一些敏感的需要加密的数据。这些数据可能是要保存在pod的定义文件或者docker的镜像中。把这些数据通过加密的方式存放到secrets对象中,可以降低信息泄露的风险。在secret中存储的数据都需要通过base64进行转换加密后存放。创…

Oracle入门(十四G)之PL / SQL中检索数据

一、PL / SQL中检索数据 (1)PL / SQL中的SQL语句可以在PL / SQL中使用以下几种SQL语句:•SELECT从数据库检索数据。•DML语句,例如INSERT,UPDATE和DELETE,以更改数据库中的行。•事务控制语句,例…

.NET Core 1.0 CentOS7 尝试

昨天宣布 ASP.NET Core RC2,据说差不多稳定了,以后不会有大改了。 参考:https://blogs.msdn.microsoft.com/webdev/2016/05/16/announcing-asp-net-core-rc2/ 一、环境装备 等待很久了,高兴之余昨晚安装一个CentOS系统,版本如下&a…

6.netty线程模型-Reactor

【README】 1..本文部分内容翻译自: [Netty] Nettys thread model and simple usage 2.netty模型是以 Reactor模式为基础的,具体的,netty使用的是 主从Reactor多线程模型; 3.先介绍了 Reactor线程模型;后介绍了 Ne…

python mac读取 文件属性_从Python获取和设置mac文件和文件夹查找器标签

macfile模块是^{}模块的一部分,在"2006-11-20 0.2.0"中被重命名为mactypes使用此模块,以下两个函数可用于获取和设置appscript 1.0版的查找器标签:from appscript import appfrom mactypes import File as MacFile# Note these lab…

Oracle入门(十四.1)之PL / SQL简介

一、PL / SQL描述程序语言扩展到SQL: •允许将基本程序逻辑和控制流与SQL语句组合在一起。 •是Oracle专有编程语言。- 它只能用于Oracle数据库或工具。二、程序语言扩展到SQL•是一种程序语言。 - 当遵循一系列指令时会产生结果。 •是3GL(第三代编程语…

构建高性能.NET应用之配置高可用IIS服务器-第三篇 IIS中三个核心组件的讲解(上)

今天的文章的比较的容易,主要讲述IIS中三个比较重要的组件:协议监听者(Protocol Listeners),WWW服务(World Wide Web Publishing Service)和WAS(Windows Process Activation Service),理解这三个组件的功能,是理解IIS…

7.netty服务器中提交任务到NioEventLoop(Nio事件循环执行线程)

【README】 1.本文总结自 B站 《尚硅谷-netty》; 2.NioEventLoop实际上是一个提交到线程池的Runnable任务,在while无限循环中运行 taskQueue中的任务(串行); 【1】提交任务到NioEventLoop 1)NioEventLoop&#xff1…

Oracle入门(十四.2)之PL / SQL的好处

一、PL / SQL的好处在Oracle数据库中使用PL / SQL编程语言有很多好处。 1.将过程构造与SQL集成 2.模块化程序开发 3.改进的性能 4.与Oracle工具集成 5.便携性6.异常处理二、优点 优点1:使用SQL集成程序化结构PL / SQL的首要优势是程序结构与SQL的集成。 SQL是一种非…

炒菜机器人的弊端_机器人炒菜真不是你想的那样!

7月8日下午,爱餐全产业链模式发布会在张家口进行,会上,张家口文旅投集团与上海爱餐机器人有限公司签订了3000台智能机器人设备合作协议,这些机器人可是身手不凡,清一色的都是会厨艺的炒菜机器人,未来他们还…

构建高性能.NET应用之配置高可用IIS服务器-第四篇 IIS常见问题之:工作进程回收机制(上)

通过三篇文章的普及,相信大家对IIS应该有了一个基本的了解。那么从本篇文章开始,我们就开始进入IIS一些比较实际的话题:如何配置IIS,使得其性能尽可能的高。 我们在本篇中主要讲述的就是“工作进程回收机制”,下面我们…

8.基于netty实现群聊,心跳检测

【README】 1.本文总结自B站《netty-尚硅谷》,很不错; 2.本文po出了 Unpooled创建缓冲区的 代码示例; 3.本文示例代码基于netty实现以下功能: 群聊客户端及服务器;心跳检测;【1】Unpooled创建缓冲区 U…

Oracle入门(十四.3)之创建PL / SQL块

一、PL / SQL块结构 一个PL / SQL块由三部分组成。PL / SQL块结构部分二、PL / SQL编译器用高级编程语言(C,Java,PL / SQL等)编写的每个程序都必须经过检查并转换为二进制代码(1和0),然后才能执…

[.NET Core].NET Core R2安装及示例教程

前言 前几天.NET Core发布了.NET Core 1.0.1 R2 预览版,之前想着有时间尝试下.NET Core。由于各种原因,就没有初试。刚好,前几天看到.NET Core发布新版本了,决定要去一探究竟。于是乎,就立马去官网查找相关的信息&…

Oracle入门(十四.4)之在PL / SQL中使用变量

一、变量的使用 (1)使用变量的原因•临时存储数据 •储存值的操作 •可重用性(2)处理PL / SQL中的变量变量是: •在声明部分声明并初始化 •在可执行部分中使用并分配新值 变量可以是: •作为参数传递给PL …

dismiss的词组_法律英语常用词必记:Dismiss

Dismiss英[dɪsmɪs] 美[dɪsmɪs]【英文释义】v.to refuse to give further hearing to a case in court. If a judge dismisses a court case, they officially decide that the case should not continue【中文释义】v. (1)解雇;免职;开除(2)驳回(起诉…

构建高性能.NET应用之配高可用IIS服务器-第五篇 IIS常见问题之:工作进程回收机制(中)

我们在本篇中接着讲述“工作进程回收机制”。 本篇文章的议题如下: 工作进程回收机制讲解 基于时间的回收机制 基于请求数的回收机制 基于内存使用的回收机制 基于活动状态的回收机制 基于请求数的回收机制 这种基于请求数量回收的机制非常的好理解:当我…