从汇编代码理解数组越界访问漏洞

news2024/10/7 4:24:05

数组越界访问漏洞是 C/C++ 语言中常见的缺陷,它发生在程序尝试访问数组元素时未正确验证索引是否在有效范围内。通常情况下,数组的索引从0开始,到数组长度减1结束。如果程序尝试访问小于0或大于等于数组长度的索引位置,就会导致数组越界访问。由于 C/C++ 没有对数组做边界检查,不检查下标是否越界可以提升程序运行的效率,导致在程序编译过程中它并不定会造成编译错误。攻击者可以利用数组越界访问漏洞来读取或修改程序内存中的数据,甚至执行恶意代码。这种漏洞可能会导致程序崩溃、拒绝服务,或者泄露敏感信息。因此,在开发软件时,应该确保对数组访问进行边界检查,以防止发生这种类型的漏洞。

一、漏洞代码示例

首先展示一个包含数组越界访问漏洞的代码:

#include<stdio.h>
int main(){
    int a[7]={0,1,2,3,4,5,6};
    for(int i=0;i<=7;i++)
    {
        a[i]=0;
        printf("This is a test!\n");
    }
    return 0;
}

可以很容易看出,数组的长度为7,下标只能取到6,而在代码的第4行for循环的终止条件却为 i<=7,导致在第6行会执行一个"a[7]=0"的赋值操作,出现数组越界问题。

我们编译并执行上述代码,发现居然成功通过编译,没有任何报错!但是陷入了死循环,并输出了满屏的"This is a test!"。

上述代码中的数组越界访问导致程序陷入死循环,那么为什么会出现这种现象呢?

二、汇编代码分析

我们通过 Compiler Explorer 将上述程序处理为 intel 风格的x86_64汇编代码看看:

下面我们来分析上述汇编代码。

  • 4-6行:常规的栈帧初始化,这里不做赘述。
  • 7-14行:栈顶指针(rsp)减32字节,为数组及变量开辟空间,接着分别赋入 a[0] - a[6] 以及变量 i 的值。
  • 15行:跳转至L2段。
  • 24-25行:比较(cmp)指针[rbp-4]处存放的值(变量i的值)与7的大小,如果小于或等于则跳转到L3段(jle,jump when less or equal)。
  • 17行:取出指针指向[rbp-4]位置的值,存入寄存器eax中。
  • 18行:执行cdqe指令,将32位寄存器eax扩展为64位寄存器rax。
  • 19行:到了导致数组越界的关键地方,在这里将0赋值给了[rbp-32+rax*4],我们假设某个时刻rax(存放变量i的寄存器)为7(即下标已经越界),此时,[rbp-32+rax*4] = [rbp-4] = i = 0(如14行)。也就是说,每当i=7时,在源代码第6行a[i]=0处会再次将0赋值给i,就导致for循环中 i=7 -> i=0,最终产生死循环。

小结一下,导致死循环的根本原因是数组赋值语句a[i]=0非法篡改了i的值。假设这里我们将a[i]=0更改为a[i]=7,此时[rbp-32+rax*4]= [rbp-4] = i = 7,程序依然可以正常执行。

三、进一步分析

这里我们更改一下示例代码为:

#include<stdio.h>
void func1()
{
    long a[2]={0,1};
    a[3] = 0;
    a[4] = 0;
}

void func2()
{
    printf("func2 excuted!");
}

int main(){
    func1();
    printf("No error!");
    return 0;
}

执行上述代码,会出现异常:

因为在函数func1栈的高地址位存放了其返回地址,当该函数执行完后,cpu依据这个地址信息回到main函数中继续执行后续代码,而第5行a[3]=0处,将数值0覆盖了该返回地址,因此导致程序异常。根据上述逻辑,如果我们将a[3]指向函数func1的返回地址,理论上程序应该也可以正常执行。

同样地,通过Compiler Explorer得到该程序的汇编代码:

将a[3]指向函数func1的返回地址,即修改 a[3]=0 为 a[3]=0x401171,再次执行程序,可以正常得到输出结果:

另外,我们还可以做如下修改:

  • a[3]=0x401151;
  • a[4]=0x401171;

将数组a指向函数func2的初始化地址,让func1调用并执行func2函数。执行程序,得到如下输出结果:(成功调用了函数func2)。

四、总结

根据上述示例可以发现,通过数组越界来覆盖函数的返回地址可以更改程序的执行流程。同样地,攻击者可以填写存放恶意代码的地址,从而引导函数func1去执行该恶意代码。因此,在编写代码中对数组做边界检查尤为重要。

参考

[1] [汇编杂项]关于_高级语言中 数组越界与汇编中 栈溢出的_联系的思考 - SachieW - 博客园 (cnblogs.com)

[2] 通过查看汇编理解数组越界 - 知乎 (zhihu.com)

[3] CPU眼里的:数组越界 | 堆栈溢出_哔哩哔哩_bilibili

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

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

相关文章

Python 物联网入门指南(八)

原文&#xff1a;zh.annas-archive.org/md5/4fe4273add75ed738e70f3d05e428b06 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第三十章&#xff1a;制作机械臂 最后&#xff0c;我们终于到达了大多数人自本书开始以来就想要到达的地方。制作一个机械臂&#xff01;在…

pip如何查看Python某个包已发行所有版本号?

以matplotlib包为例子&#xff0c; pip install matplotlib6666 6666只是胡乱输入的一个数&#xff0c;反正输入任意一个不像版本号的数字都可以&#xff5e; matplotlib所有版本号如下&#xff0c; 0.86, 0.86.1, 0.86.2, 0.91.0, 0.91.1, 1.0.1, 1.1.0, 1.1.1, 1.2.0, 1.2.1…

【问题处理】银河麒麟操作系统实例分享,oom分析

1.问题现象描述 服务器数据库被oomkill掉&#xff0c;但是mem查看只占用了不到60%。 2.问题分析 2.1.oom现象分析 从下面的日志信息&#xff0c;可以看到chmod进程是在内核采用GFP_KERNEL|__GFP_COMP分配order3也就是2的3次方&#xff0c;8个连续页的时候&#xff0c;因进入…

如何使用Git-Secrets防止将敏感信息意外上传至Git库

关于Git-Secrets Git-secrets是一款功能强大的开发安全工具&#xff0c;该工具可以防止开发人员意外将密码和其他敏感信息上传到Git库中。 Git-secrets首先会扫描提交的代码和说明&#xff0c;当与用户预先配置的正则表达式模式匹配时&#xff0c;便会阻止此次提交。该工具的优…

字体反爬积累知识

目录 一、什么是字体反扒 二、Unicode编码 三、利用font包获取映射关系 一、什么是字体反扒 字体反爬是一种常见的反爬虫技术&#xff0c;它通过将网页中的文本内容转换为特殊的字体格式来防止爬虫程序直接获取和解析文本信息。字体反爬的原理是将常规的字符映射到特殊的字…

Linux 磁盘管理和文件系统

硬盘的物理结构&#xff1a; 盘片硬盘有多个盘片&#xff0c;每盘片2面磁头每面一个磁头 硬盘的数据结构&#xff1a; 扇区盘片被分为多个扇形区域&#xff0c;扇区:每个扇区存放512字节的数据&#xff0c;硬盘的最小存储单位磁道同一盘片不同半径的同心圆&#xff0c;是由磁…

C++笔记:类和对象

类和对象 认识类和对象 先来回忆一下C语言中的类型和变量&#xff0c;类型就像是定义了数据的规则&#xff0c;而变量则是根据这些规则来实际存储数据的容器。类是我们自己定义的一种数据类型&#xff0c;而对象则是这种数据类型的一个具体实例。类就可以理解为类型&#xff0c…

「翻版周慧敏」海底骚逆天长腿贺30岁生日

有「翻版周慧敏」之称的苏皓儿&#xff08;Chloe&#xff09;&#xff0c;日前原来已是她迎来30岁生日&#xff0c;她也在IG分享潜水靓相。火红色比坚尼尽骚她的苗条身材和长腿&#xff0c;就连网民也十分佩服&#xff0c;说&#xff1a;「三字头都咁靓好屈机&#xff01;」 Ch…

MySQL 核心模块揭秘 | 14 期 | 回滚整个事务

回滚整个事务要怎么清除 binlog 日志&#xff0c;InnoDB 又会进行哪些操作&#xff1f; 作者&#xff1a;操盛春&#xff0c;爱可生技术专家&#xff0c;公众号『一树一溪』作者&#xff0c;专注于研究 MySQL 和 OceanBase 源码。 爱可生开源社区出品&#xff0c;原创内容未经授…

电商价格监测合规性探讨

品牌在做控价、数据分析的过程中&#xff0c;都需要先有数据作为支撑&#xff0c;也就是说要先采集数据&#xff0c;价格监测也是如此&#xff0c;监测的基础是采集&#xff0c;现在主流的采集形式是爬虫采集&#xff0c;可以理解为人工采集的升级版&#xff0c;以机器代替人工…

Python基于深度学习的车辆特征分析系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

西晋从建立到灭亡51年历史

西晋的建立&#xff0c;也标志着三国时期的结束&#xff0c;也开启了中国历史上的一个新时代。下面让我们来揭开西晋从建立到灭亡51年的历史。 1、高平陵事变 曹丕去世后&#xff0c;魏明帝曹睿继位&#xff0c;但曹睿却英年早逝&#xff0c;幼子曹芳继位。 司马懿受曹睿托孤…

微服务之网关路由

一、概述 1.1认识网关 什么是网关&#xff1f; 顾明思议&#xff0c;网关就是网络的关口。数据在网络间传输&#xff0c;从一个网络传输到另一网络时就需要经过网关来做数据的路由和转发以及数据安全的校验。 更通俗的来讲&#xff0c;网关就像是以前园区传达室的大爷。 外…

vue 常用的日历排班,带农历显示组件(2024-04-16)

显示当前月日历组件&#xff0c;里面带农历或节日显示 后面可以丰富一些国家法定节假期的业务需求 代码 js-calendar.js 文件 var lunarInfo [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-19090x04ae0, 0x0a5b6, 0…

了解 Unity AI:从初学者到高级的综合指南

游戏中的AI是什么? 游戏中的人工智能是指利用人工智能技术使视频游戏中的非玩家角色和实体智能地行动、做出决策、对游戏环境做出反应,并提供引人入胜的动态游戏体验。什么是NPC? NPC 代表“非玩家角色”。NPC 是视频游戏、角色扮演游戏中不受人类玩家控制的角色。它们是计算…

Python-VBA函数之旅-exec函数

目录 一、exec函数的常见应用场景&#xff1a; 二、exec函数安全使用注意事项&#xff1a; 三、exec函数与eval函数对比分析&#xff1a; 1、exec函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、相关文章&#xff1a; 个人主页&#xff1a;神奇夜光…

【word技巧】如何锁定word文档格式不变?

Word文档编辑完成之后不想被其他人修改格式&#xff0c;应该如何设置&#xff1f;限制编辑来搞定。 打开word文档设置限制编辑的界面&#xff0c;我们只勾选【限制对选定样式设置格式】&#xff0c;点击底下的设置&#xff0c;除了勾选第一个选项以外&#xff0c;还可以勾选上…

通过 Ollama、Langchain 实现 RAG

RAG 是什么 RAG 在 Langchain 上的定义是&#xff0c;作为大语言模型最常用的场景就是问答系统&#xff0c;可以针对特别来源数据做问题回答&#xff0c;就是私有数据&#xff0c;这就是 RAG&#xff0c;英文全称是Retrieval Augmented Generation。就是对现有模型数据的增广&…

树和二叉树(一)

一、树 非线性数据结构&#xff0c;在实际场景中&#xff0c;存在一对多&#xff0c;多对多的情况。 树( tree&#xff09;是n (n>0&#xff09;个节点的有限集。当n0时&#xff0c;称为空树。 在任意一个非空树中&#xff0c;有如下特点。 1.有且仅有一个特定的称为根的节点…

公园高速公路景区校园IP网络广播音柱SIP音柱

公园高速公路景区校园IP网络广播音柱SIP音柱 适用于学校、车站、教堂、工厂、仓库、公园停车场及露天市场高速公路等场所播放录制语音文件或背景音乐节目&#xff0c;专业一体化音箱设计&#xff0c;高强度防水设计&#xff0c;符合IP54防护等认证&#xff0c;数字化产品&…