动态

详情 返回 返回

逆向視角:C/C++ 變量存儲的 "秘密基地",一次看透 5 種變量的本質 - 动态 详情

作為程序員,我們幾乎每天都在和變量打交道,但你真的瞭解這些變量在內存裏的"藏身之處"嗎?今天從逆向分析的角度,帶大家扒開普通局部變量、靜態局部變量、全局變量、靜態全局變量和const全局變量的底層存儲邏輯,看完讓你對變量的理解再上一個台階。

先看一段"找茬"代碼

為了把問題説透,先上一段包含5種變量的測試代碼:

// 全局變量家族
int g_global_int = 0x01;
static int g_static_global_int = 0x02;
const int g_const_global_int = 0x03;

// 局部變量家族展示
void local_variable_demo()
{
    int local_int = 0x04;               // 普通局部變量
    static int static_local_int = 0x05; // 靜態局部變量
    const int const_local_int = 0x06;   // const局部變量

    printf("%d, %d, %d\n", local_int, static_local_int, const_local_int);
}

// 全局變量展示
void global_variable_demo()
{
    printf("%d, %d, %d\n", g_global_int, g_static_global_int, g_const_global_int);
}

int main()
{
    local_variable_demo();
    global_variable_demo();
    return 0;
}

這段代碼看起來平平無奇,但當我們用x64dbg調試器看它的反彙編時,各種變量的"小動作"就藏不住了。

局部變量:棧上的"臨時住户"

先看local_variable_demo函數的反彙編,重點觀察三種局部變量的存儲差異。

普通局部變量:棧空間的"臨時租客"

反彙編裏有這樣幾條關鍵指令:

  • sub esp, 0xD8:給棧頂指針減0xD8,相當於在棧上開闢一塊內存空間
  • mov dword ptr ss:[ebp-0x8], 0x4:把0x04(初始值)寫入棧上ebp-0x8的位置
  • mov edx, dword ptr ss:[ebp-0x8]:從棧上讀取值到寄存器,再作為參數壓棧

結論:普通局部變量存放在棧上,函數調用時創建,函數結束後自動釋放,生命週期僅限函數內部。

靜態局部變量:數據段的"常住民"

靜態局部變量的反彙編很簡單,只有一條讀取指令:mov ecx, dword ptr ds:[0xBAA028]

找不到初始化的代碼?因為靜態局部變量在編譯時就完成了初始化:

  • 非零初始值存放在.data段(可寫數據段)
  • 零初始值存放在.bss段(未初始化數據段)

結論:靜態局部變量雖然定義在函數內,但存儲在全局數據區,生命週期和程序一樣長,只會初始化一次。

const局部變量:棧上的"帶鎖抽屜"

反彙編裏const局部變量和普通局部變量的存儲方式完全一樣,都是存在棧上。

那為什麼不能修改?其實是編譯器在編譯階段加了"保護鎖"——當你嘗試修改const局部變量時,編譯器會直接報錯,但從內存層面看,這些數據和普通局部變量沒有本質區別。

全局變量:數據段的"固定產權房"

再看global_variable_demo函數的反彙編,三種全局變量都直接從內存地址讀取數據,但地址位置大有講究。

通過內存佈局分析發現:

  • 普通全局變量(g_global_int)和靜態全局變量(g_static_global_int)擠在.data段(可寫)
  • const全局變量(g_const_global_int)單獨住在.rdata段(只讀)

關鍵差異

  • 靜態全局變量和普通全局變量的區別不在存儲區域,而在作用域——靜態全局變量僅限當前文件訪問
  • const全局變量因為只讀特性,被編譯器分配到更安全的只讀數據段,防止意外修改

變量存儲總結:一張表看懂本質

變量類型 存儲區域 生命週期 初始化時機 訪問限制
普通局部變量 函數調用期間 運行時初始化 函數內部
靜態局部變量 .data/.bss 整個程序運行期間 編譯時初始化 函數內部
普通全局變量 .data/.bss 整個程序運行期間 編譯時初始化 所有文件(extern可見)
靜態全局變量 .data/.bss 整個程序運行期間 編譯時初始化 當前文件
const全局變量 .rdata 整個程序運行期間 編譯時初始化 所有文件(extern可見)

額外思考:變量安全防護

知道了變量的存儲規律,反過來想:既然內存中的數據能被輕易查找和修改,如何保護程序的關鍵數據?

可以藉助專業的程序保護工具,通過調試保護、內存校驗等技術,增加逆向分析的難度,讓核心數據更安全。

理解變量的底層存儲,不僅能幫我們寫出更高效的代碼,還能從逆向角度思考程序的安全性——這大概就是深入底層帶來的雙重收穫吧。

user avatar shiwangdehuangdou_bpfcez 头像
点赞 1 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.