通过在未初始化数据段 (bss) 中打印 "garbage values" 我们可以映射出先前程序中的所有值
By printing "garbage values" in uninitialized data segment (bss) can we map out all values from previous program
我有一个奇怪的问题,我不确定我是否能够解释它,但我们开始吧。在学习和使用 C 时,您通常会遇到术语“垃圾”或“垃圾”值,我的第一个问题是,数据是来自某个不同程序或任何东西的内存地址中的数据遗留下来的,还是实际上是一些 'random' value ,如果我认为那个内存地址中的剩余值是真的,为什么我们仍然能够从这样的内存地址读取,我的意思是让我们假设我们只是声明 int x;它现在存储在 bss 中的某个内存地址 # 上,我们要输出它的值,我们将获得驻留在该地址上的值,所以如果我说的所有事情都是真的,那我们就不能声明很多许多变量但只声明而不初始化也许我们可以映射以前存储在 bss 中的所有值从之前的某个程序等。
我很可能确定这将是一个很大的安全威胁,因此我知道可能有一些措施可以防止这种情况发生,但我想知道是什么阻止了这种情况?
不,.bss
部分的内容在您的程序开始之前已清零。这是为了满足 C 对全局和 static
变量的保证,如果未明确初始化,将被初始化为零。
事实上,在一个典型的多任务系统上,所有 由您的进程分配的内存将在您被授予访问权限之前被操作系统清零。这正是为了避免您提到的安全漏洞。
堆栈上的局部 (auto
) 变量的值如果未初始化,通常会包含“垃圾”,但它会是您自己的程序执行到此时遗留下来的垃圾.如果您的程序碰巧没有向堆栈上的特定位置写入任何内容,那么它仍将包含零(同样是典型的 OS);它永远不会包含来自其他程序的内存内容。
malloc
分配的内存也是如此。如果它直接来自 OS,它包含零。如果它恰好是之前分配和释放的块,它可能包含您之前使用该内存或 malloc 的内部数据产生的垃圾,但同样它永远不会包含另一个程序的数据。
C 语言本身没有什么能阻止你几乎完全按照你说的去做。仅考虑 C 标准的要求,您所说的唯一错误是在谈论“bss”中的变量。具有静态存储持续时间且没有初始化程序(这是 bss 中变量的标准等价物)的对象保证在程序启动时被初始化为零,因此您不能以这种方式访问 no-longer-运行 程序的数据。但是,在像老式的 MS-DOS 或 CP/M 这样的环境中,没有任何东西可以阻止您设置指向物理 RAM 基址的指针,扫描到末尾,并从以前的程序中查找数据。
但是,所有用于全功能计算机的现代操作系统都提供内存保护,这意味着,除其他外,它们保证没有进程可以读取另一个进程的内存,无论另一个进程是否仍然 运行,除非通过明确定义的 API 执行安全策略。 “Spectre”系列硬件错误是一个大问题 只是因为 它们破坏了这一保证。
关于内存保护如何工作的细节过于复杂,无法放入此答案框,但几乎总是要做的一件事是,每当您从操作系统分配更多内存时,该内存就会被初始化,或者全零位或磁盘上文件的内容。无论哪种方式,您都无法获得“垃圾”。
我有一个奇怪的问题,我不确定我是否能够解释它,但我们开始吧。在学习和使用 C 时,您通常会遇到术语“垃圾”或“垃圾”值,我的第一个问题是,数据是来自某个不同程序或任何东西的内存地址中的数据遗留下来的,还是实际上是一些 'random' value ,如果我认为那个内存地址中的剩余值是真的,为什么我们仍然能够从这样的内存地址读取,我的意思是让我们假设我们只是声明 int x;它现在存储在 bss 中的某个内存地址 # 上,我们要输出它的值,我们将获得驻留在该地址上的值,所以如果我说的所有事情都是真的,那我们就不能声明很多许多变量但只声明而不初始化也许我们可以映射以前存储在 bss 中的所有值从之前的某个程序等。 我很可能确定这将是一个很大的安全威胁,因此我知道可能有一些措施可以防止这种情况发生,但我想知道是什么阻止了这种情况?
不,.bss
部分的内容在您的程序开始之前已清零。这是为了满足 C 对全局和 static
变量的保证,如果未明确初始化,将被初始化为零。
事实上,在一个典型的多任务系统上,所有 由您的进程分配的内存将在您被授予访问权限之前被操作系统清零。这正是为了避免您提到的安全漏洞。
堆栈上的局部 (auto
) 变量的值如果未初始化,通常会包含“垃圾”,但它会是您自己的程序执行到此时遗留下来的垃圾.如果您的程序碰巧没有向堆栈上的特定位置写入任何内容,那么它仍将包含零(同样是典型的 OS);它永远不会包含来自其他程序的内存内容。
malloc
分配的内存也是如此。如果它直接来自 OS,它包含零。如果它恰好是之前分配和释放的块,它可能包含您之前使用该内存或 malloc 的内部数据产生的垃圾,但同样它永远不会包含另一个程序的数据。
C 语言本身没有什么能阻止你几乎完全按照你说的去做。仅考虑 C 标准的要求,您所说的唯一错误是在谈论“bss”中的变量。具有静态存储持续时间且没有初始化程序(这是 bss 中变量的标准等价物)的对象保证在程序启动时被初始化为零,因此您不能以这种方式访问 no-longer-运行 程序的数据。但是,在像老式的 MS-DOS 或 CP/M 这样的环境中,没有任何东西可以阻止您设置指向物理 RAM 基址的指针,扫描到末尾,并从以前的程序中查找数据。
但是,所有用于全功能计算机的现代操作系统都提供内存保护,这意味着,除其他外,它们保证没有进程可以读取另一个进程的内存,无论另一个进程是否仍然 运行,除非通过明确定义的 API 执行安全策略。 “Spectre”系列硬件错误是一个大问题 只是因为 它们破坏了这一保证。
关于内存保护如何工作的细节过于复杂,无法放入此答案框,但几乎总是要做的一件事是,每当您从操作系统分配更多内存时,该内存就会被初始化,或者全零位或磁盘上文件的内容。无论哪种方式,您都无法获得“垃圾”。