Uninitialized Variables

HackTricksをサポートする

基本情報

ここでの核心的なアイデアは、未初期化変数がどのように機能するかを理解することです。これらは、割り当てられたメモリに既にあった値を持つことになります。 例:

  • 関数1: initializeVariable: 変数 x を宣言し、値を割り当てます。例えば 0x1234 とします。このアクションは、メモリ内にスポットを予約し、特定の値をそこに置くことに似ています。

  • 関数2: useUninitializedVariable: ここでは、別の変数 y を宣言しますが、値は割り当てません。C言語では、未初期化変数は自動的にゼロに設定されることはありません。代わりに、最後にそのメモリ位置に保存されていた値を保持します。

これらの2つの関数を順次実行すると:

  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 関数は、上記の2つの関数を順番に呼び出し、初期化された変数と初期化されていない変数の対比を示します。

ARM64の例

ARM64では、ローカル変数もスタックで管理されるため、全く変わりません。これが示されているこの例を確認できます。

HackTricksをサポートする

Last updated