特洛伊木馬 為了在受害者電腦長期駐留,必須隱藏自身蹤跡。本文深入分析 VC++ 開發的木馬程式在 Windows 9x 環境下,如何透過修改視窗擴充樣式隱藏「工作列按鈕」,以及利用 RegisterServiceProcess 系統服務註冊機制隱藏「工作管理員進程列表」的技術細節,並提供對應防範建議。
主視窗建立時預設會在工作列顯示按鈕。隱藏手段有二:
LONG exStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
exStyle &= ~WS_EX_APPWINDOW; // 移除「應用程式視窗」屬性
exStyle |= WS_EX_TOOLWINDOW; // 加入「工具視窗」屬性
SetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
WS_EX_TOOLWINDOW 視窗不會在工作列顯示,且不會出現在 Alt+Tab 切換清單。
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) {
cs.style = WS_POPUP;
cs.dwExStyle |= WS_EX_TOOLWINDOW;
return CFrameWnd::PreCreateWindow(cs);
}
本質相同,皆為調整擴充視窗樣式。另需於 InitInstance 中將 ShowWindow(SW_HIDE) 隱藏主視窗,避免啟動瞬間閃現。
Windows 9x 透過 KERNEL32.DLL 匯出的 RegisterServiceProcess 管理「服務進程」。未註冊為服務的進程不會出現在 Ctrl+Alt+Del 的工作管理員清單中。木馬利用此特性,啟動時動態載入並呼叫該函式將自身「註銷」。
DWORD RegisterServiceProcess(DWORD dwProcessId, DWORD dwType);
// dwProcessId: 0 = 目前進程
// dwType: RSP_SIMPLE_SERVICE (1) 註冊為服務 / RSP_UNREGISTER_SERVICE (0) 註銷
// 動態取得函式位址
HMODULE hKernel = GetModuleHandle(_T("KERNEL32.DLL"));
typedef DWORD (WINAPI *RSP)(DWORD, DWORD);
RSP pRSP = (RSP)GetProcAddress(hKernel, "RegisterServiceProcess");
pRSP(GetCurrentProcessId(), 1); // 1 = 隱藏 (RSP_UNREGISTER_SERVICE 常定義為 1)
注意:RSP_UNREGISTER_SERVICE 數值在不同 SDK 定義可能為 0 或 1,實務上需測試確認。Windows NT/2000/XP 已移除此 API,改用服務控制管理器 (SCM)。
ShowWindowAsync(hWnd, SW_HIDE); // 某些木馬啟動新執行緒建立隱藏視窗
利用非同步視窗顯示狀態變更,配合特定旗標繞過工作管理員枚舉。
msconfig、登錄表 Run/RunOnce、排程任務、服務 (services.msc)。netstat -ano 對應 PID,發現不明外連立即調查。RegisterServiceProcess 呼叫、視窗樣式異常修改等行為進行啟發式攔截。RegisterServiceProcess,並強化進程存取控制 (ACL),大幅提高隱藏難度。理解隱藏原理可用於開發背景監控服務、無介面自動化工具、系統托盤常駐程式等合法軟體。但務必遵循「使用者知情同意、提供明確退出機制、數位簽章驗證」原則,避免被誤判為惡意程式。