C++/CLI 支援 GC、泛型等現代特性,但混合模式下原生代碼仍面臨緩衝區溢出威脅。本文實測 Visual Studio 2005 混合組件在 /GS(緩衝區安全檢查)與 /clr 組合下的脆弱性。
char buff[1028];
bool checkpassword() {
char password[10];
gets(password); // 危險:無邊界檢查
return strcmp(password, "NCC-1701") == 0;
}
int main() {
gets(buff); // 另一處溢出點
if (!checkpassword()) { /* 記錄失敗 */ exit(-1); }
}
編譯選項 /GS- /clr 關閉保護。輸入超長密碼覆蓋返回位址至 0x00408130(shellcode),函數返回時跳轉執行任意代碼。/GS 啟用時會在堆疊陣列後插入 Cookie,檢測覆蓋並終止程式,但:
Win32 應用程式中,全域緩衝區 lpszPassword[16] 緊鄰 userP、userNameLen、userPasswordLen。對話方塊 EM_GETLINE 訊息未限制長度,溢出覆蓋相鄰變數。攻擊者構造輸入:
userP 指向可控記憶體。userNameLen 為目標返回位址。userP->len = userNameLen 形成任意記憶體寫入,修改堆疊返回位址至 shellcode。全程未觸動堆疊 Cookie(因溢出源在資料段),/GS 完全無效。
*((WORD*)(&lpszPassword)) = (sizeof(lpszPassword)/sizeof(TCHAR)) - 1; // 設定最大長度
LRESULT ret = SendDlgItemMessage(hDlg, IDC_EDIT1, EM_GETLINE, 0, (LPARAM)lpszPassword);
lpszPassword[ret] = '\0'; // 手動加終結符
正確使用 EM_GETLINE 協定:首字設緩衝區大小,呼叫後依回傳長度加終結符。
/GS 非銀彈,僅緩解堆疊陣列溢出。gets_s、strcpy_s、StringCchCopy 等)。