第3章“程序的机器级表示”:存储器的越界引用和缓冲区溢出

news2025/2/12 21:53:06

已经看到,C 对于数组引用不进行任何边界检查,而且局部变量和状态信息(如寄存器值和返回指针)都存放在栈中。这两种情况结合到一起就能导致严重的程序错误,一个对越界的数组元素的写操作破坏了存储在栈中的状态信息。然后,当程序使用这个被破坏的状态,试图重新加载寄存器或执行 ret 指令时,就会出现很严重的错误。

一种特别常见的状态破坏称为缓冲区溢出(buffer overflow)。通常,在栈中分配某个字节数组来保存一个字符串,但是字符串的长度超出了为数组分配的空间。下面这个程序示例就说明了这个问题:

/* Implementation of library function gets() */
char *gets(char *s)
{
	int c;
	char *dest = s;
	while ((c = getchar()) != '\n' && c != EOF)
		*dest++ = c;
	*dest++ = '\0'; /* Ternimate String */
	if (c == EOF) 
		return NULL;
	return s;
}

/* Read input line and write it back */
void echo()
{
	char buf[4]; /* Way to small! */
	gets(buf);
	puts(buf);
}

该代码是库函数 gets 的实现,用来说明这个函数的严重问题。它从标准输入读入一行,在遇到一个 “\n” 字符或某个错误情况时停止。它将这个字符串拷贝到参数 s 指明的位置,并在字符串结尾加上 null 字符。在函数 echo 中,使用了 gets,这个函数只是简单地从标准输入中读入,再回送到标准输出。

gets 的问题是它没有办法确定是否为保存整个字符串分配了足够的空间。在 echo 示例中,故意将缓冲区设得非常小——只有4字节长。任何长度超过 3 个字符的字符串都会导致写越界。

研究 echo 汇编代码的这一部分,看看栈是如何组织的:

在这里插入图片描述
该例子中,可以看到,程序总共为局部存储(storage)分配了 32 个字节(第4行和第6行)。不过,字符数组 buf 的位置在 %ebp 下方四个字节处(第7行)。

下图给出了得到的栈结构:
在这里插入图片描述
正如看到的那样,所有对 buf[4] ~ buf[7] 的写都是会导致 %ebp 的保存值被破坏。当程序随后试图以它为栈指针进行恢复时,所有后来的栈引用都会是非法的。所有对 buf[8] ~ buf[11] 的写都会导致返回地址被破坏。当在函数结尾执行 ret 指令时,程序会 “返回” 到错误的地址。像这个示例说明的那样,缓冲区溢出可能导致程序出现严重的错误。

echo 代码很简单,但是有点太随意了。更好一点的版本是使用 fgets 函数,它包括一个参数,限制待读入的最大字节数。通常,使用 gets 或其他能导致存储溢出的函数,都是不好的编程习惯。当编译一个含有调用 gets 的文件时,C 编译器甚至会产生这样的出错信息:“the gets function is dangerous and should not be used(gets 函数很危险,不应使用)。”

缓冲区溢出的一个更加致命的使用就是让程序执行它本来不愿意执行的函数。这是一种最常见的通过计算机网络攻击系统安全的方法。通常,输入给程序一个字符串,这个字符串包含一些可执行代码的字节编码,称为 exploit code,另外,还有一些字节会用一个指向缓冲区中那些可执行代码的指针覆盖掉返回指针。所以,执行 ret 指令的效果就是跳转到 exploit code。

在一种攻击形式中,exploit code 会使用系统调用启动一个 shell 程序,提供给攻击者一组操作系统的函数。在另一种攻击形式中,exploit code 执行一些未授权的任务,修复对栈的破坏,然后第二次执行 ret 指令,(看上去好像)正常返回给调用者。

来看个例子,著名的 Internet 蠕虫病毒在 1988 年 11 月通过 Internet 以四种不同的方法获取对许多计算的访问。一种是对 finger 守护进程 fingerd 的缓冲区溢出攻击,fingerd 是通过 FINGER 命令来服务请求的。通过以一个适当的字符串调用 FINGER,蠕虫可以使远程的守护进程缓冲区溢出并只执行一段代码,该代码能让蠕虫访问远程系统。一旦蠕虫获得了对系统的访问,它就能自我复制,几乎完全地消耗掉机器上所有的计算资源。因此,在安全专家抓住如何消除这种蠕虫的方法之前,成百上千的机器实际上都瘫痪了。这种蠕虫的始作俑者最后被抓住并被起诉。他被判处三年徒刑(缓期执行)、400个小时的社区服务以及 10500 美元的罚款。不过,即使到今天,人们还是在不断地发现使他们容易遭受缓冲区溢出攻击的系统安全漏洞,这更加突显了小心仔细编写程序的必要性。任何到外部环境的接口都应该是“防弹的”,这样,外部 agent 的行为才不会导致系统出现错误。

蠕虫和病毒

蠕虫和病毒都是试图在计算机从中传播它们自己的代码。正如 Spafford[73] 讲述的那样,蠕虫(worm)是这样一种程序,它可以自己运行,并且能够将一个完全有效的自己传播到其他机器。与此相应地,病毒(virus)是这样一段代码,它能将自己添加到包括操作系统在内的其他程序中,但它不能独立运行。在一些大众媒体中,术语 “病毒” 用来指各种不同的在系统间传播攻击代码的策略,所以你可能会听到人们把本来应该叫做“蠕虫”的东西称为了“病毒”。

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

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

相关文章

60题学会动态规划系列:动态规划算法第三讲

简单多状态问题 文章目录 一.按摩师二.打家劫舍系列三.删除并获得点数四.粉刷房子 1.按摩师 力扣链接:力扣 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预…

java泛型学习

前言 没有泛型的时候,我们声明的 List 集合默认是可以存储任意类型元素的,乍一看你可能还会觉得挺好,这样功能强大,啥类型都可以存储......但是开发的时候由于不知道集合中元素的确切类型,遍历的时候我们拿到的 item …

路径规划算法:基于供需优化的路径规划算法- 附代码

路径规划算法:基于供需优化的路径规划算法- 附代码 文章目录 路径规划算法:基于供需优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要:本文主要介绍利用智能优化算法供需…

图形编辑器开发:最基础但却复杂的选择工具

大家好,我是前端西瓜哥。 对于一个图形设计软件,它最基础的工具是什么?选择工具。 但这个选择工具,却是相当的复杂。这次我来和各位,细说细说选择工具的一些弯弯道道。 我正在开发的图形设计工具的: http…

复习并发编程的基础知识(二)

线程的状态6种状态及生命周期 1.new 2.Runnable(Ready和Running) 3.Blocked 4.Waiting 5.Timed_Waiting 6.Terminated 线程同步 同步:一些敏感的数据(比如共享的需要修改的资源)不允许被多个线程同时访问&#…

centos7 gitlab安装配置

gitlab概述 GitLab是一个基于Web的Git存储库管理和代码协作平台。它提供了一套完整的工具和功能,使团队能够更高效地进行代码版本控制、协作开发和持续集成/持续部署(CI/CD)。 以下是GitLab的主要功能和概述: 版本控制系统&…

使用布隆过滤器的flink十亿级数据实时过滤实践一

1项目背景 1.1 需求 实时推荐项目需求如下:根据用户实时行为(如关注,播放,收藏)推荐该UP主(关注的up主,播放视频发布up主,收藏up主)或其相似UP主的作品,UP主及相似UP主下的作品是提前离线召回…

react---生命周期

目录 1.新旧生命周期对比 2.常用的3个钩子函数 3.生命周期(旧) 4.生命周期(新) React 中为我们提供了一些生命周期钩子函数,让我们能在 React 执行的重要阶段,在钩子函数中做一些事情。 1.新旧生命周期…

数据安全--17--数据安全管理之数据传输

本博客地址:https://security.blog.csdn.net/article/details/131061729 一、数据传输概述 数据传输有两个主体,一个是数据发送方,另一个是数据接收方。数据在通过不可信或者较低安全性的网络进行传输时,容易发生数据被窃取、伪…

Mybatis源码学习之全局配置文件和映射文件解析

全局配置文件和映射文件解析 全局配置文件解析 public static void main(String[] args) throws IOException {// 读取配置文件InputStream is Resources.getResourceAsStream("org/apache/ibatis/builder/MapperConfig1.xml");// 创建SqlSessionFactory工厂SqlSes…

JDK11 官网下载(提供网盘下载资源)

目录 引言一、Oracle(甲骨文)二、JDK11下载1.JDK11下载入口2.JDK版本说明3.JDK11下载前说明4.JDK11下载 三、网盘下载1.资源提供说明2.资源列表清单(持续更新中...)3.获取方式 总结 引言 我们要学习 Java 语言去开发 Java 程序&a…

k8s 基本架构

k8s 中支持的 node 数 和 pod 数 k8s 也是逐步发展过来的,来看看以前和现在支持的 node 数 和 pod 数对比 node 即 节点 , 早期的 k8s 版本能够支持 100 台节点,现在 k8s 可以支持到 2000 台了 pod 数,早期的版本可以支持 1000 …

Android 自定义View 之 Dialog弹窗

Dialog弹窗 前言正文一、弹窗视图帮助类二、弹窗控制类三、监听接口四、样式五、简易弹窗六、常规使用七、简易使用八、源码 前言 在日常开发中用到弹窗是比较多的,常用于提示作用,比如错误操作提示,余额不足提示,退出登录提示等&…

linux 内核版本和发行版本

当要明确自己的Linux系统的版本号时,大多数情况是用命令确定Linux内核版本的。不过这个还是要与CentOS的版本号(就是你使用的Linux系统的发行版本)区分开来,这两个不是一个东西。 一、发行版本号 比如当时安装CentOS时&#x…

【Python】集合 set ① ( 集合定义 | 集合特点 | 代码示例 - 集合定义 )

文章目录 一、集合特点二、集合定义三、代码示例 - 集合定义 一、集合特点 在之前 的博客中 介绍了 列表 / 元组 / 字符串 数据容器 , 列表 支持 定义后 , 增加元素 / 修改元素 / 删除元素 , 并且 列表中可以存储 重复 / 有序 的元素 ;元组 定义后 不能 进行 增加元素 / 修改元…

(转载)有导师学习神经网络的回归拟合(matlab实现)

神经网络的学习规则又称神经网络的训练算法,用来计算更新神经网络的权值和阈值。学习规则有两大类别:有导师学习和无导师学习。在有导师学习中,需要为学习规则提供一系列正确的网络输入/输出对(即训练样本),当网络输入时,将网络输…

对于Promise的理解

1.什么是回调地狱 多层异步函数的嵌套叫做回调地狱 代码1: setTimeout(() > {console.log(吃饭);setTimeout(() > {console.log(睡觉);setTimeout(() > {console.log(打豆豆);}, 1000);}, 2000);}, 3000); 代码2: 通过id获取用户名,通过用户名获取邮箱…

如何自动识别快递单号和批量查询的方法

最近有很多朋友问我,有没有办法批量查询快递单号,查询该快递单号的所有物流发货信息?今天小编就来分享一个实用的查询技巧,教大家轻松查询多个快递单号,还可以一键保存查询数据,一起来看看吧。 首先今天我们…

PoseNet深度网络进行6D位姿估计的训练,python3实现

0.相关github网址 原版github代码-caffe实现tensorflow实现,相关版本较低,python2,本文根据此代码迁移到python3上面。pytorch实现,但将骨干模型从goglenet改成了resnet,实验效果得到提升,但没公布预训练权…

快递单号一键批量查询的具体操作方法和步骤

最近做电商的朋友对一个话题很感兴趣:如何批量查询快递单号?今天,小编给你安利一款软件:固乔快递查询助手,支持大量快递单号的批量查询。下面我们来看看批量查询的具体操作方法。 小伙伴们需要先在“固乔科技”的官网上…