Windows 服務通常在背景以 LocalSystem 高權限運行,無使用者介面。若服務需與登入使用者互動,微軟早期提供「允許服務與桌面互動」選項 (登錄 Type & 0x0100 或 CreateService SERVICE_INTERACTIVE_PROCESS),讓服務開啟互動式桌面視窗。
WM_COMMAND、WM_TIMER 等),竄改服務行為、提權或導致崩潰。若程式碼含以下特徵,立即重構:
OpenWindowStation/GetThreadDesktop 取得互動式桌面MessageBox 且 uType 包含 MB_SERVICE_NOTIFICATION 以外旗標OpenDesktop("winsta0", ...) 建立 UIOpenDesktop 取得的桌面上 LoadLibrary/GetProcAddressMessageBox(..., MB_SERVICE_NOTIFICATION) (僅限 NT 4.0 SP3+)。
void func(char* szData) {
PVOID p = _alloca(lstrlen(szData)); // 攻擊者傳入超大字串 → 堆疊耗盡 → 例外 → 程式終止
// use p
}
若在服務程式中,將導致服務掛掉,造成嚴重拒絕服務。
void func(char* szData) {
__try {
PVOID p = _alloca(lstrlen(szData));
// use p
}
__except ((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
_resetstkoflw(); // 重置堆疊狀態,避免後續 Guard Page 失效
}
}
A2W、W2A、CW2CT 等巨集內部使用 _alloca。服務端程式碼嚴禁直接用於不可信輸入長度的字串。必須先驗證長度上限,或改用堆積配置 (new/malloc) 的安全轉換函式。
加密流程若「同一緩衝區先存明文、再加密、再發送」,多執行緒下可能發生指令重排:
正常:載入明文 → 加密 → 發送密文 競態:載入明文 → 發送(明文!) → 加密
此錯誤曾存在於 IIS 4.0 SSL 實作,極罕見負載下洩漏一封明文封包。修正:嚴格分離明文緩衝區與密文緩衝區,發送前確認密文緩衝區已填充。
void ShuffleAndUpdate(char* szName, char* szPwd, DWORD index, DWORD d) {
DWORD dwArray[32]; ZeroMemory(dwArray, sizeof(dwArray));
BOOL fAllowAccess = FALSE;
if (IsValidUser(szName, szPwd)) {
fAllowAccess = TRUE;
ShuffleArray(dwArray, szName);
}
dwArray[index] = d; // 潛在索引越界 (index >= 32)
if (fAllowAccess) { /* 敏感操作 */ }
}
答案: 1) index 未驗證邊界,導致緩衝區溢位。2) ShuffleArray 若修改 dwArray 大小/邏輯,後續 dwArray[index] 更不可預期。3) 敏感操作應在驗證通過且所有輸入經過完整性檢查後才執行。