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

深度解析 Windows 任務管理器的開發原理與核心實現

     編輯:關於VC++

Windows 2000/XP 內建的任務管理器是系統管理員和開發人員最常用的工具之一。XP 版本相比 2000 功能更強大、資訊更詳細,但你是否覺得它仍缺少某些關鍵資訊?或者覺得系統管理工具過於分散?本文將帶你深入探討任務管理器的開發原理,並動手實作一個功能更完整的任務管理器。我們將調用 Win32 API 實現核心功能,後續還將深入探討 Windows 核心機制。

核心功能模組:進程管理

進程管理是任務管理器最熟悉的功能。當懷疑中毒或遭遇木馬時,檢查運行中的進程是首要步驟。除了進程名稱,我們還需要獲取:

  • 進程標識符 (Process ID)
  • 用戶資訊 (User Name)
  • CPU 使用時間 (CPU Time)
  • 記憶體使用情況 (Memory Usage)
  • 基礎優先權 (Base Priority)

CPU 和記憶體資訊有助於分析進程運行狀態,優先權則反映進程在處理器調度中的優先級。此外,父進程 ID、創建時間、完整程式路徑等資訊在排查問題時同樣關鍵。

深度效能資訊

Windows 採用雙模式架構:核心模式和用戶模式。進程在兩者間頻繁切換,我們可以分別統計其在各模式下的 CPU 時間。記憶體管理相關指標包括:工作集、分頁池、非分頁池、頁面檔案使用量。I/O 操作統計涵蓋讀/寫/其他操作的次數與傳輸位元組數。

安全分析功能:模組與線程枚舉

若懷疑某進程為木馬,僅有名稱遠遠不夠。獲取可執行檔完整路徑有助於確認程式身份。針對「創建遠程線程」等注入技術,枚舉進程加載的所有模組(主要是 DLL)至關重要。線程是 Windows 的執行實體,進程提供運行環境。枚舉進程內所有線程資訊,配合掛起/恢復/終止操作,構成完整的進程控制能力。值得注意的是,Windows 2000 下某些系統關鍵進程在原生任務管理器中無法終止,但我們的實作可突破此限制。

桌面窗口資訊

桌面窗口是主要交互介面。獲取窗口標題、關聯進程/線程 ID、窗口句柄屬性等資訊,功能類似 VC++ 的 Spy++ 工具,但整合在單一介面中更方便。

系統效能監控

涵蓋系統句柄總數、進程/線程計數、物理記憶體總量/使用量、系統快取大小、認可記憶體狀態、核心分頁/非分頁池使用量等,幾乎囊括 Windows 記憶體管理的所有核心指標。

磁碟資訊

一次性查看所有磁碟(軟碟、硬碟、光碟等)的容量、使用量、檔案系統類型(FAT/NTFS/CDFS 等)及磁碟標籤,避免重複進入「我的電腦」查看。

環境變數管理

環境塊包含環境變數字串,對應控制面板「系統/進階」中的設定。支援新增、刪除、編輯系統環境變數。

事件日誌分析

事件日誌分為應用程式、系統、安全三類,每類包含資訊、警告、錯誤類型。關鍵欄位:記錄序號、事件類型、事件 ID、來源、生成時間、用戶名、描述資訊。網管人員不可或缺的分析工具。

網路適配器與流量統計

獲取網卡詳細資訊:名稱、描述、硬體位址、IP/子網路遮罩、閘道、DHCP 伺服器位址。同時統計收發廣播/非廣播資料報、錯誤計數、總收發位元組數,掌握網路流量狀況。

網路共享管理

列舉所有共享資源的路徑、類型,支援刪除不必要的共享以防資料洩露。

用戶帳號資訊

Windows NT 核心支援多用戶。獲取密碼過期時間、用戶/群組 SID、帳號類型(權限區分)、磁碟配額限制、登入次數與時間等,便於審計用戶行為。

服務與驅動程式控制

探測每個服務/驅動的啟動路徑、狀態、類型、啟動方式,支援啟動、停止、刪除操作。更多細節請參考《淺析 Windows 2000/XP 服務與後門技術》。

進階關機選項

支援註銷、鎖定、定時關機/重啟(含訊息提示)、休眠、冬眠。Windows 2000 也能享用 XP 風格的倒數計時關機功能。

系統版本資訊

作業系統指紋、註冊組織/用戶、主機名、系統目錄等固定資訊。


核心 API 實現詳解

1. 窗口資訊枚舉

HDESK hDesk = OpenDesktop(lpszDesktop, 0, FALSE, DESKTOP_ENUMERATE);
// 開啟預設桌面
EnumDesktopWindows(hDesk, (WNDENUMPROC)EnumWindowProc, 0);
// 枚舉桌面所有窗口,透過回調函數處理

BOOL __stdcall EnumWindowProc(HWND hWnd, LPARAM lParam) {
    GetWindowText(hWnd, szWindowText, dwMaxCount); // 獲取標題
    GetWindowThreadProcessId(hWnd, &dwPID); // 獲取進程/線程 ID
    return TRUE;
}

2. 服務與驅動程式枚舉

SC_HANDLE schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
// 以完整權限開啟服務控制管理器
EnumServicesStatus(schManager, dwDeviceType, dwDeviceState,
    EnumStatus, dwBufSize, &dwBytesNeeded,
    &dwDevicesReturned, &dwResumeHandle);
// 枚舉所有裝置驅動程式狀態
CloseServiceHandle(schManager); // 關閉句柄

SC_HANDLE schDevice = OpenService(schManager, szDeviceName, SERVICE_ALL_ACCESS);
// 開啟特定驅動程式
QueryServiceConfig(schDevice, lpDeviceConfig, 1024*8, &dwBytesNeeded); // 服務配置
QueryServiceStatus(schDevice, &DeviceStatus); // 當前狀態
QueryServiceConfig2(schDevice, SERVICE_CONFIG_DESCRIPTION,
    (LPBYTE)lpDeviceDescription, 8*1024, &dwBytesNeeded); // 描述資訊
StartService(schDevice, 0, NULL); // 啟動
ControlService(schDevice, SERVICE_CONTROL_STOP, &DeviceStatus); // 停止
DeleteService(schDevice); // 刪除

3. 磁碟資訊獲取

GetLogicalDriveStrings(dwBufferLength, lpBuffer); // 獲取邏輯磁碟機字串
GetVolumeInformation(lpRootPathName, lpVolumeNameBuffer, dwVolumeNameSize,
    &dwVolumeSerialNumber, &dwMaximumComponentLength,
    &dwFileSystemFlags, lpFileSystemNameBuffer, dwFileSystemNameSize);
// 獲取磁碟區資訊:卷標、序號、檔案系統類型
GetDiskFreeSpaceEx(lpRootPathName, &FreeBytesAvailable,
    &TotalNumberOfBytes, &TotalNumberOfFreeBytes); // 空間使用情況

4. 環境變數操作

RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegKey, 0, KEY_QUERY_VALUE, &hKey);
// 開啟註冊表鍵:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
RegEnumValue(hKey, dwIndex, EnvironVariable, &dwVariableLength, NULL, NULL, NULL, NULL);
// 枚舉環境變數名稱
GetEnvironmentVariable(EnvironVariable, EnvironString, 1024); // 獲取變數值

5. 事件日誌讀取

HANDLE hEvent = OpenEventLog(NULL, szLog); // 開啟日誌
GetOldestEventLogRecord(hEvent, &dwThisRecord); // 獲取最舊記錄位置
ReadEventLog(hEvent, EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
    0, pEventLogRecord, 1024*32, &dwRead, &dwNeeded); // 讀取記錄
LookupAccountSid(NULL, pSid, szName, &dwName, szDomain, &dwDomain, &SNU); // SID 轉用戶名
GetNumberOfEventLogRecords(hEvent, &dwTotal); // 總記錄數
CloseEventLog(hEvent); // 關閉

6. 網路共享枚舉

NetShareEnum(NULL, dwLevel, (PBYTE*)&pBuf, MAX_PREFERRED_LENGTH,
    &entriesread, &totalentries, &resume); // 級別 2 共享枚舉
NetApiBufferFree(pBuf); // 釋放緩衝區
NetShareDel(NULL, (char*)lpShareNameW, 0); // 刪除共享

7. 網路適配器資訊

GetAdaptersInfo(&AdapterInfo, &OutBufLen); // 獲取網卡資訊

8. 系統效能資訊

GetPerformanceInfo(&PerfInfo, sizeof(PERFORMACE_INFORMATION));
// 獲取系統效能資訊

9. 進程/線程/模組完整枚舉

// 提升權限以獲取完整資訊
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken);
AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
// 啟用 SeDebugPrivilege

// 進程快照與枚舉
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
Process32First(hProcessSnap, &pe32);
do {
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
    GetProcessTimes(hProcess, &CreateTime, &ExitTime, &KernelTime, &UserTime); // 時間資訊
    GetProcessMemoryInfo(hProcess, &PMCounter, sizeof(PMCounter)); // 記憶體資訊
    GetPriorityClass(hProcess); // 優先權
    GetProcessIoCounters(hProcess, &IoCounters); // I/O 計數器

    // 模組枚舉
    HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe32.th32ProcessID);
    MODULEENTRY32 me32 = { sizeof(MODULEENTRY32) };
    Module32First(hModuleSnap, &me32);
    do { /* 處理模組資訊 */ } while (Module32Next(hModuleSnap, &me32));

    // 線程枚舉
    HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    THREADENTRY32 te32 = { sizeof(THREADENTRY32) };
    Thread32First(hThreadSnap, &te32);
    do {
        if (te32.th32OwnerProcessID == pe32.th32ProcessID) {
            HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
            // 可執行 SuspendThread/ResumeThread/TerminateProcess 等控制
        }
    } while (Thread32Next(hThreadSnap, &te32));

} while (Process32Next(hProcessSnap, &pe32));

10. 關機與電源控制

AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
// 調整權限支援關機
ExitWindowsEx(EWX_LOGOFF, 0); // 註銷
LockWorkStation(); // 鎖定工作站
InitiateSystemShutdown(NULL, szMessage, dwTimeout, FALSE, bSig); // 定時關機/重啟
SetSystemPowerState(bSig, FALSE); // 休眠/冬眠

11. 用戶帳號枚舉

NetUserEnum(NULL, dwLevel, FILTER_NORMAL_ACCOUNT, (LPBYTE*)&pBuf,
    dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries, &dwResumeHandle);
// 枚舉用戶資訊
NetUserDel(NULL, lpUserNameW); // 刪除用戶

12. 系統版本資訊

GetVersionEx((LPOSVERSIONINFO)&osviex); // OS 版本
// 註冊表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
GetTickCount(); // 開機時間
GetComputerName(szInfo, &dwInfo); // 電腦名
GetUserName(szInfo, &dwInfo); // 用戶名
GetWindowsDirectory(szInfo, MAX_PATH+1); // Windows 目錄
GetSystemDirectory(szInfo, MAX_PATH+1); // System 目錄

總結與展望

雖然我們已實現超越原生任務管理器的功能,但代碼多為直接調用 Win32 API。真正的系統程式設計師應深入探究核心機制:這些 API 內部如何實現?物件管理器、進程/線程調度、記憶體管理器的運作細節才是關鍵。微軟隱藏了大量內部細節,但這正是驅動我們深入研究 Windows 核心的動力。

本文配套完整原始碼供下載參考。

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