基本概念

缓冲区是在数据从一个位置传输到另一个位置时临时保存数据的内存存储区域。当数据量超过内存缓冲区的存储容量时,就会发生缓冲区溢出(或缓冲区溢出)。结果,试图将数据写入缓冲区的程序会覆盖相邻的内存位置。

缓冲区溢出原指当某个数据超过了处理程序回传堆栈地址限制的范围时,程序出现的异常操作。造成此现象的原因有:

  • 存在缺陷的程序设计
  • 尤其是C语言,不像其他一些高级语言会自动进行数组或者指针的堆栈区块边界检查,增加溢出风险。
  • C语言中的C标准库还具有一些非常危险的操作函数,使用不当也为溢出创造条件。

什么是缓冲区溢出攻击

攻击者通过覆盖应用程序的内存来利用缓冲区溢出问题。这会改变程序的执行路径,触发损坏文件或暴露私人信息的响应。例如,攻击者可能会引入额外的代码,向应用程序发送新指令以访问
IT 系统。

如果攻击者知道程序的内存布局,他们可以故意提供缓冲区无法存储的输入,并覆盖保存可执行代码的区域,用他们自己的代码替换它。例如,攻击者可以覆盖指针(指向内存中另一个区域的对象)并将其指向漏洞利用负载,从而获得对程序的控制权。

缓冲区溢出攻击的类型

基于堆栈的缓冲区溢出 更为常见,并利用仅在函数执行期间存在的堆栈内存。

基于堆的攻击 更难执行,并且涉及将分配给程序的内存空间泛滥到超出用于当前运行时操作的内存。

哪些编程语言更容易受到攻击?

C 和 C++ 是两种极易受到缓冲区溢出攻击的语言,因为它们没有内置的保护措施来防止覆盖或访问内存中的数据。Mac OSX、Windows 和 Linux
都使用用 C 和 C++ 编写的代码。

PERL、Java、JavaScript 和 C# 等语言使用内置的安全机制来最大限度地减少缓冲区溢出的可能性。

如何防止缓冲区溢出

开发人员可以通过代码中的安全措施或使用提供内置保护的语言来防止缓冲区溢出漏洞。

此外,现代操作系统具有运行时保护。三种常见的保护措施是:

  • 地址空间随机化 (ASLR) — 随机移动数据区域的地址空间位置。通常,缓冲区溢出攻击需要知道可执行代码的位置,而随机化地址空间使得这几乎不可能。
  • 数据执行预防 ——将某些内存区域标记为不可执行或可执行,从而阻止攻击在不可执行区域中运行代码。
  • 结构化异常处理程序覆盖保护 (SEHOP) — 帮助阻止恶意代码攻击结构化异常处理 (SEH),这是一种用于管理硬件和软件异常的内置系统。因此,它可以防止攻击者利用 SEH 覆盖利用技术。在功能级别上,使用基于堆栈的缓冲区溢出来覆盖存储在线程堆栈中的异常注册记录来实现 SEH 覆盖。

代码和操作系统保护中的安全措施是不够的。当组织发现缓冲区溢出漏洞时,它必须迅速做出反应以修补受影响的软件,并确保软件用户可以访问补丁。

示例代码展示

根据STACK1_VS_2017.cpp代码进行修改

#include <stdlib.h>
#include  <stdio.h>
#include "Windows.h"int main(int argc, char **argv) {MessageBoxA((HWND)-0, (LPCSTR) "缓冲区溢出测试\n", (LPCSTR)"功能", (UINT)0);int cookie;
char buf[2];int *a = &cookie;char * b = buf;
printf("buf: %08x cookie: %08x\n", b, a);u_int64 p =(u_int64)a-(u_int64)b;printf("两变量内存地址之差=%d\n",p);
gets(buf);
if (cookie == 0x41424344)
printf("缓冲区溢出成功!\n");}

运行效果展示

使用MessageBoxA函数检测程序是否正常运行,点击确定开始测试

使用printf()函数输出提示信息,使用gets()函数获取用户输入信息

任意输入两个数值,不满足条件,程序运行完毕

代码分析漏洞成因

诱因:char buf[2]; 代码部分解析—使用char 将变量buf声明成了一个拥有2个元素数组其中元素类型为字符.buf有了两个自己长度,

提示:u_int64 p =(u_int64)a-(u_int64)b; 代码部分对程序涉及变量了内存地址进行了一个减分计算并对赋值给变量
p,(为使其运算成立还对其进行了类型转义),结果可告知两个变量内存地址距离,方便溢出利用

隐患:使用gets()函数获取输入数据,因gets()函数无限读取数据并不检查缓冲区的大小限制,会将超出缓冲区的数据继续写入堆栈,导致存在溢出隐患。

为方便理解此处代码演示下:

#include <stdlib.h>
#include  <stdio.h>
#include "Windows.h"int main() {char test[] = "test1";printf("test1初始值为%s\n清输入st值:",test);char st[2];gets(st);printf("输出test:%s\n",test);printf("输出st:%s\n",st);
}

在运行效果上可以看到超出堆栈空间的值继续写入堆栈导致覆盖了test在堆栈内对应的值,导致其数值进行了改变:test1-3456

反汇编分析其运行过程堆栈是如何变化的
有运行得知(外加源代码)程序初始关键词:test1初始值为test1

可通过此关键词,在反汇编程序快速定位到程序相关函数运行区域

在入口指令处下断点方便分析

并在实际运行发现运行到此处为显示相关特征字符信息,初步判断正确

将此区域字符串进行反编译与源码对照进一步验证

没汇编指令对照不太直观换个插件与工具,进行展示

未输入st值时test对应数据堆栈情况

000000000061FDE8 000000000061FE0A “test1”

输入后查看

000000000061FDE8 000000000061FE08 “123456”

000000000061FDF0 000000000061FE0A “3456” //之前为test1

根据此思路分析之前的示例程序

反汇编分析

根据之前的思路定位关闭区域

定位特征代码:

根据特征代码搜索

在入口指令处下断点

运行看到一个变量的对应地址

继续运行看到另一个变量的地址

因剩下的只是运行用就不展示了

输入数值后可看到由之前空白数据已被输入的数据覆盖

扩展知识:发现栈中对应的值与内存对应的值是相反的,因为堆栈中的值遵循先进后出原则故是相反的

扩展分析

看到此区域有个je跳转指令,其上方有个cmp指令(功能是用来比较),其中有一值被固定为:41424344

可以看到明显不满足跳转故跳转不会执行,不显示隐藏的信息

根据此思路:输入两值将缓冲区堆满,之后数据溢出覆盖思路,并且根据提示计算出两变量相距离为2与堆栈数据先进后出原则,故输入如下条件即可使跳转成立,进而输出隐藏信息

12DCBA

跳转成立

可以看到隐藏信息已显示

扩展知识

RSP+2C = rsp对应的地址+2c 即000000000061FDE0+2C=61FE0C

将16进制转10进制计算

IDA调试分析使其跟清晰地去查看变化

为方便分析可在关键函数处下断点单步执行看执行效果,

由之前可知MesssageBoxA后才开始正式运行,故可在此call后下断点

运行,直到到断点暂停

运行后发现rsi对应数值无变化,正常因除了初始赋值后无其它赋值给rsi的指令

gets函数执行前rsi对应数据仍未变化

gets函数执行后rsi对应数据发生改变

ush    rsi
.text:00000000004078D1 push    rbx
.text:00000000004078D2 sub     rsp, 38h
.text:00000000004078D6 call    __main
.text:00000000004078DB lea     rsi, [rsp+48h+var_1E]    初始rsi值
.text:00000000004078E0 xor     r9d, r9d        ; uType
.text:00000000004078E3 xor     ecx, ecx        ; hWnd
.text:00000000004078E5 lea     rbx, [rsp+48h+var_1C]
.text:00000000004078EA lea     r8, Caption     ; lpCaption
.text:00000000004078F1 lea     rdx, Text       ; lpText
.text:00000000004078F8 call    cs:__imp_MessageBoxA
.text:00000000004078FE mov     r8, rbx
.text:0000000000407901 mov     rdx, rsi
.text:0000000000407904 sub     rbx, rsi
.text:0000000000407907 lea     rcx, aBuf08xCookie08 ; "buf: %08x cookie: %08x\n"
.text:000000000040790E call    _Z6printfPKcz   ; printf(char const*,...)
.text:0000000000407913 lea     rcx, byte_40902D ; char *
.text:000000000040791A mov     rdx, rbx
.text:000000000040791D call    _Z6printfPKcz   ; printf(char const*,...)
.text:0000000000407922 mov     rcx, rsi
.text:0000000000407925 call    gets
.text:000000000040792A cmp     [rsp+48h+var_1C], 41424344h
.text:0000000000407932 jz      short loc_40793D

根据此区域汇编代码分析得知,除了初始运行对rsi进行赋值后均无对其赋值的指令,故可得知存在溢出漏洞,覆盖了rsi原始数据,导致其值改变,根据单步跟踪执行流程可值执行完gets函数后其值发生变化,故可判断使用gets函数获取的数据导致堆栈数据溢出。

修复

可使用fgets或gets_s函数替换gets函数。

函数解析:

fgets()函数的第2个参数指明了读入字符的最大数量。如果该参数的值是n,那么fgets()将读入n-1个字符,或者读到遇到的第一个换行符为止;
这里为3,故获取的数值为12,共输入6个数读取到第2个结束

IDA附加进程并单步执行查看执行流程

fgets执行前rsi对应数据

fgets执行后rsi对应数据

可以看到数据未溢出,分析到此告一段落

最后

网络安全工程师企业级学习路线

如图片过大被平台压缩导致看不清的话,扫码下方二维码CSDN大礼包:《黑客&网络安全入门&进阶学习资源包免费分享


视频配套资料&国内外网安书籍、文档&工具
当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

​​
一些我自己买的、其他平台白嫖不到的视频教程:

如图片过大被平台压缩导致看不清的话,扫码下方二维码CSDN大礼包:《黑客&网络安全入门&进阶学习资源包免费分享

缓冲区溢出漏洞那些事:C -gets函数相关推荐

  1. 缓冲区溢出漏洞利用--调用白板Messagebox函数两次

    //******有漏洞的程序************* //漏洞函数VerifyPassword 由于文件大小是可变的 但是szBuffer大小只有50 当文件大小大于50的 //时候就会产生缓冲区溢 ...

  2. php crypt函数缓冲区溢出漏洞,GIMP 堆缓冲区溢出漏洞(CVE-2017-17784)

    GIMP 堆缓冲区溢出漏洞(CVE-2017-17784) 发布日期:2018-04-20 更新日期:2018-05-03 受影响系统:GIMP GIMP 2.8.22 描述: BUGTRAQ  ID ...

  3. php crypt函数缓冲区溢出漏洞,简单缓冲区溢出漏洞攻击实验

    缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回 ...

  4. 缓冲区溢出漏洞攻击——Shellcode编写

    一.实验内容 利用一个程序漏洞,编写shellcode,达成效果:蹦出对话框,显示"You have been hacked!(by JWM)" 二.实验原理 因为输入了过长的字符 ...

  5. 缓冲区溢出漏洞攻击演示实验(CProxy 6.2缓冲区溢出漏洞)

    实验内容: 分析缓冲区溢出漏洞,利用CCProxy 6.2的这个缓冲区溢出漏洞,利用ping命令向其发送一个长的字符串,溢出局部变量,覆盖RET的位置,从而实现程序跳转到自己想要让其执行的程序上去. ...

  6. 安装squid_CVE-2019-12527:Squid缓冲区溢出漏洞利用分析

    报告编号:B6-2019-110702 报告来源:360-CERT 报告作者:360-CERT 更新日期:2019-11-07 0x00 背景描述 2019年8月22日,趋势科技研究团队发布了编号为C ...

  7. CVE-2021-2429:MySQL InnoDB Memcached 插件中的堆缓冲区溢出漏洞详解

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 2021年4月,ZDI 收到了一名匿名者提供的关于MySQL 数据库中某漏洞的报告,结果是位于 InnoDB memcached 插件中的基于堆 ...

  8. 虚拟机危险!一个存在11年的缓冲区溢出漏洞--毒液

    本文讲的是 虚拟机危险!一个存在11年的缓冲区溢出漏洞--毒液,CrowdStrike的研究人员昨日声称,他们发现当今大多数最流行的虚拟机平台软件中,都存在一个缓冲区溢出漏洞,该漏洞能够潜在的导致攻击 ...

  9. 分区起始位置参数溢出_IIS6.0缓冲区溢出漏洞深度分析(CVE-2017-7269)

    漏洞描述 开启WebDAV服务的IIS6.0存在缓冲区溢出漏洞可以任意代码执行,目前针对 Windows Server 2003 R2 可以稳定利用.在WebDAV服务的ScStoragePathFr ...

最新文章

  1. request和response一览
  2. 带评分的Jupyter资源列表:270个开源项目,总计24w星,帮你快速找代码
  3. 中值滤波_Halcon联合C#编程自学笔记三之中值滤波
  4. Chapter 1 First Sight——25
  5. 量化金融第一步获取市场数据 (Python Tushare)
  6. Flink 1.9报错:No implicits found for parameter evidence$2: TypeInformation[(String, String, String)]
  7. 用Win2003做×××借线
  8. 百度违规屏蔽词过滤查询工具
  9. 【矢量图】PyEcharts导出图片并矢量化
  10. java 法定节假日_【java】如何获得每年的法定节假日期以及全年的日历
  11. 12 道腾讯前端面试真题及答案整理
  12. 对Windows和类Unix争论的观点] 谁是谁的躯壳,谁又是谁的灵魂
  13. 小妲己智能机器人要连接wifi吗_小度智能机器人怎么连wifi
  14. 强大、优秀的文件管理软件评测:图片管理、书籍管理、文献管理
  15. centos7 NFS客户端自动挂载
  16. java解决udp可靠性,由于UDP协议提供的是不可靠的服务,因此,可以被淘汰掉。...
  17. steam教育课程是什么总结
  18. PICK菲仕乐锅具,轻松开启荤素搭配健康轻生活
  19. 批量DICOM转jpg格式
  20. 循序渐进学运维-服务篇V1版更新完毕

热门文章

  1. Unity与汇承HC-02蓝牙串口模块通讯
  2. 毕业设计 基于stm32的人体健康监护系统 - 单片机 嵌入式 物联网
  3. 宝塔安装swoole 及几十万微信模板消息异步发送
  4. web自动化之frame、文件上传、窗口切换、悬浮菜单
  5. VMware安装win10遇到的一个错误及解决方式
  6. alin的学习之路(Linux网络编程:十)(http协议,BS模型)
  7. 1279 红绿灯路口
  8. 使用winRAR的绿色版的操作
  9. 利用WinRAR打包免安装绿色C#程序
  10. STM32软件复位办法