基本概念 缓冲区是缓冲函数在数据从一个位置传输到另一个位置时临时保存数据的内存存储区域
。当数据量超过内存缓冲区的区溢存储容量时,就会发生缓冲区溢出(或缓冲区溢出)。出漏结果 ,洞那试图将数据写入缓冲区的缓冲函数程序会覆盖相邻的内存位置 。 缓冲区溢出原指当某个数据超过了处理程序回传堆栈地址限制的区溢范围时,程序出现的出漏异常操作。造成此现象的洞那原因有
: 攻击者通过覆盖应用程序的内存来利用缓冲区溢出问题
。这会改变程序的区溢执行路径,触发损坏文件或暴露私人信息的出漏响应。例如,免费模板攻击者可能会引入额外的代码,向应用程序发送新指令以访问 IT 系统。 如果攻击者知道程序的内存布局 ,他们可以故意提供缓冲区无法存储的输入,并覆盖保存可执行代码的区域,用他们自己的代码替换它。例如,攻击者可以覆盖指针(指向内存中另一个区域的对象)并将其指向漏洞利用负载
,从而获得对程序的控制权。服务器租用 基于堆栈的缓冲区溢出更为常见
,并利用仅在函数执行期间存在的堆栈内存
。 基于堆的攻击更难执行,并且涉及将分配给程序的内存空间泛滥到超出用于当前运行时操作的内存
。 C 和 C++ 是两种极易受到缓冲区溢出攻击的语言,因为它们没有内置的保护措施来防止覆盖或访问内存中的数据。源码库Mac OSX
、Windows 和 Linux 都使用用 C 和 C++ 编写的代码 。 PERL、Java、JavaScript 和 C# 等语言使用内置的安全机制来最大限度地减少缓冲区溢出的可能性
。 开发人员可以通过代码中的安全措施或使用提供内置保护的语言来防止缓冲区溢出漏洞 。 此外
,现代操作系统具有运行时保护。三种常见的保护措施是: 代码和操作系统保护中的安全措施是不够的。当组织发现缓冲区溢出漏洞时,它必须迅速做出反应以修补受影响的软件
,并确保软件用户可以访问补丁
。 根据STACK1_VS_2017.cpp代码进行修改; 运行效果展示; 使用printf()函数输出提示信息,使用gets()函数获取用户输入信息; 任意输入两个数值,不满足条件 ,程序运行完毕; 诱因:char buf[2]; 代码部分解析---使用char 将变量buf声明成了一个拥有2个元素数组其中元素类型为字符.buf有了两个自己长度, 提示:u_int64 p =(u_int64)a-(u_int64)b; 代码部分对程序涉及变量了内存地址进行了一个减分计算并对赋值给变量 p,(为使其运算成立还对其进行了类型转义),结果可告知两个变量内存地址距离 ,方便溢出利用 隐患
:使用gets()函数获取输入数据,因gets()函数无限读取数据并不检查缓冲区的大小限制
,会将超出缓冲区的数据继续写入堆栈 ,导致存在溢出隐患。 为方便理解此处代码演示下 : 在运行效果上可以看到超出堆栈空间的值继续写入堆栈导致覆盖了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 D1 push rbx h D6 call __main 初始rsi值 uType hWnd lpCaption lpText __imp_MessageBoxA rbx rsi rsi rbx rsi call gets h 根据此区域汇编代码分析得知
,除了初始运行对rsi进行赋值后均无对其赋值的指令,故可得知存在溢出漏洞,覆盖了rsi原始数据,导致其值改变 ,根据单步跟踪执行流程可值执行完gets函数后其值发生变化,故可判断使用gets函数获取的数据导致堆栈数据溢出 。 可使用fgets或gets_s函数替换gets函数。 函数解析
: 个字符,或者读到遇到的第一个换行符为止; IDA附加进程并单步执行查看执行流程; fgets执行前rsi对应数据; fgets执行后rsi对应数据 可以看到数据未溢出,分析到此告一段落。






























修复



