Uninitialized Variables

从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS红队专家)

支持HackTricks的其他方式:

基本信息

这里的核心思想是理解未初始化变量的情况,因为它们将具有已分配给它们的内存中的值。 例如:

  • 函数1:initializeVariable:我们声明一个变量x并为其赋值,比如0x1234。这个操作类似于在内存中保留一个位置并放入一个特定的值。

  • 函数2:useUninitializedVariable:在这里,我们声明另一个变量y,但不为其赋值。在C语言中,未初始化变量不会自动设置为零。相反,它们保留其内存位置上最后存储的任何值。

当我们按顺序运行这两个函数时:

  1. initializeVariable中,x被赋予一个值(0x1234),它占据了一个特定的内存地址。

  2. useUninitializedVariable中,y被声明但没有被赋值,因此它占据了紧随x后面的内存位置。由于未初始化y,它最终“继承”了与x使用的相同内存位置中的值,因为那是那里的最后一个值。

这种行为说明了低级编程中的一个关键概念:内存管理至关重要,未初始化变量可能导致不可预测的行为或安全漏洞,因为它们可能无意中保留在内存中的敏感数据。

未初始化的堆栈变量可能会带来几个安全风险,例如:

  • 数据泄露:如果存储在未初始化变量中,诸如密码、加密密钥或个人详细信息等敏感信息可能会被暴露,使攻击者有可能读取这些数据。

  • 信息泄露:未初始化变量的内容可能会透露有关程序内存布局或内部操作的详细信息,帮助攻击者开发有针对性的利用。

  • 崩溃和不稳定性:涉及未初始化变量的操作可能导致未定义的行为,导致程序崩溃或结果不可预测。

  • 任意代码执行:在某些情况下,攻击者可以利用这些漏洞来更改程序的执行流程,使其能够执行任意代码,其中可能包括远程代码执行威胁。

示例

#include <stdio.h>

// Function to initialize and print a variable
void initializeAndPrint() {
int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
}

// Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() {
int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
}

int main() {
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");

// First, call the function that initializes its variable
initializeAndPrint();

// Then, call the function that has an uninitialized variable
demonstrateUninitializedVar();

return 0;
}

工作原理:

  • initializeAndPrint 函数:此函数声明一个整数变量 initializedVar,将其赋值为 100,然后打印变量的内存地址和值。这一步很简单,展示了一个初始化变量的行为。

  • demonstrateUninitializedVar 函数:在此函数中,我们声明一个整数变量 uninitializedVar,但没有对其进行初始化。当我们尝试打印其值时,输出可能显示一个随机数。这个数字代表先前在该内存位置的任何数据。根据环境和编译器的不同,实际输出可能会有所不同,有时为了安全起见,一些编译器可能会自动将变量初始化为零,但不应依赖于此。

  • main 函数main 函数按顺序调用上述两个函数,展示了初始化变量和未初始化变量之间的对比。

ARM64 示例

在 ARM64 中,本地变量也是在堆栈中管理的,因此这一点在 ARM64 中并没有改变,您可以检查此示例

最后更新于