首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

VC++ /GS 編譯器開關:緩衝區溢位防護原理與最佳實踐

     編輯:關於VC++

緩衝區溢位:資安頭號公敵

緩衝區溢位是 C/C++ 程式最常見的嚴重弱點。駭客透過精心構造的輸入覆寫堆疊上的返回位址或異常處理器指標,劫持程式執行流程。著名的 Code Red、Slammer、Blaster 病毒皆源於此。

編譯器層面的防護演進

版本技術防護重點
VC6.0無完全無防護
VC7.0 (VS.NET 2002)/GS (Security Cookie)堆疊 Cookie 偵測返回位址竄改
VC7.1 (VS.NET 2003)/GS + /SAFESEH移動 SEH 記錄至緩衝區下方 + 安全 SEH 驗證
VC8.0 (VS2005)/GS 強化函數參數複製到區域變數下方,防護函數指標參數竄改
VS2010+/GS + /sdl + /guard:cf控制流程防護 (CFG)、更嚴格的 SDL 檢查

/GS 運作機制(Stack Cookie)

  1. 函數序言:在區域變數(緩衝區)與儲存的基址指標 EBP / 返回位址之間插入一個隨機 Cookie
  2. 函數結尾:檢查 Cookie 是否被改寫
  3. 若 Cookie 損毀 → 呼叫 __report_gsfailure → 觸發安全錯誤處理常式 → 終止程式

// 簡化版堆疊佈局 (高位址 → 低位址)
[函數參數]
[返回位址]        ← 攻擊目標
[儲存的 EBP]
[Security Cookie] ← /GS 插入
[區域變數/緩衝區] ← 溢位源頭

啟用 /GS 的方法

  • 專案屬性 → C/C++ → 代碼產生 → 緩衝區安全性檢查 → 是 (/GS)
  • 預設:Release 開啟,Debug 關閉(建議兩者皆開啟)

/GS 設定介面

自訂安全錯誤處理常式


#include 
#include 

void __cdecl MySecHandler(int code, void*) {
    if (code == _SECERR_BUFFER_OVERRUN) {
        printf("偵測到緩衝區溢位!\n");
        exit(1);
    }
}

int main() {
    _set_security_error_handler(MySecHandler);
    // ... 程式主體
}

/SAFESEH:結構化異常處理防護

  • 連結器選項:進階 → 映像有安全例外處理常式 → 是 (/SAFESEH)
  • 將合法的 SEH 處理常式位址寫入 PE 標頭,OS 例外調度器僅允許呼叫名單內的處理常式
  • Windows XP SP2 / Server 2003 起原生支援

VS2005 新增:參數複製防護

若函數參數包含函數指標或含函數指標的結構體,編譯器會在區域變數區複製一份參數。原始參數若被溢位覆寫,複製本仍完好,函數內部使用複製本,繞過攻擊。

硬體層面補充:DEP / NX Bit

  • 資料執行防護 (DEP) 標記資料頁面為不可執行
  • Windows XP SP2+、現代 CPU (NX/XD bit) 皆支援
  • 編譯器選項 /NXCOMPAT (VS2005+) 標記 PE 相容 DEP

深度防禦清單

  1. ✅ 開啟 /GS (所有配置)
  2. ✅ 開啟 /SAFESEH (Release)
  3. ✅ 使用 安全 CRT 函式 (strcpy_s, sprintf_s, memcpy_s...)
  4. ✅ 靜態分析 /analyze + Code Analysis 規則集
  5. ✅ 啟用 SDL 建議 (/sdl)
  6. ✅ 部署環境強制開啟 DEP (系統預設開啟)
  7. ✅ 考慮 Control Flow Guard (CFG) (/guard:cf, VS2015+)

結語

/GS 不是萬靈丹,但以極低成本(重新編譯即可)大幅提高攻擊門檻。結合安全程式碼撰寫習慣、靜態分析、硬體 DEP,構建多層防禦,才是現代 C/C++ 安全開發的正確路徑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved