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

Windows 進程與執行緒核心概念:CreateProcess 完整實戰解析

     編輯:組合語言

進程定義與組成

進程是正在執行的應用程式實例,擁有:

  • 私有虛擬位址空間 (4GB,用戶模式 2GB/3GB)
  • 可執行代碼映像 (EXE + 載入的 DLL)
  • 系統資源控制代碼表 (檔案、管道、同步物件、記憶體映射等)
  • 至少一條執行緒 (主執行緒,從映像入口點開始)

執行緒是CPU 排程的基本單位,擁有獨立暫存器組、堆疊、TLS、優先權。進程提供資源容器,執行緒在其中運行代碼。

CreateProcess 完整原型與參數詳解

BOOL CreateProcess(
    LPCSTR lpApplicationName,        // 模組路徑 (可為 NULL)
    LPSTR lpCommandLine,             // 命令列字串 (可修改)
    LPSECURITY_ATTRIBUTES lpProcessAttributes,  // 進程安全描述子
    LPSECURITY_ATTRIBUTES lpThreadAttributes,   // 主執行緒安全描述子
    BOOL bInheritHandles,            // 是否繼承父進程可繼承控制代碼
    DWORD dwCreationFlags,           // 建立旗標
    LPVOID lpEnvironment,            // 環境區塊指標
    LPCSTR lpCurrentDirectory,       // 當前目錄
    LPSTARTUPINFO lpStartupInfo,     // 主視窗顯示屬性等
    LPPROCESS_INFORMATION lpProcessInformation // 返回資訊
);

關鍵參數最佳實務

PROCESS_INFORMATION 結構

PROCESS_INFORMATION STRUCT
    hProcess      HANDLE ?   ; 進程控制代碼 (需 CloseHandle)
    hThread       HANDLE ?   ; 主執行緒控制代碼 (需 CloseHandle)
    dwProcessId   DWORD ?    ; 進程 ID (系統全域唯一)
    dwThreadId    DWORD ?    ; 主執行緒 ID
PROCESS_INFORMATION ENDS

控制代碼 ≠ ID:控制代碼是進程私有的間接引用,ID 是系統全域唯一數值。控制代碼需 CloseHandle 釋放核心物件引用計數。

進程生命週期管理

檢查進程是否結束

GetExitCodeProcess PROTO hProcess:DWORD, lpExitCode:DWORD
; 返回 STILL_ACTIVE (259) 表示仍在運行

強制終止進程

TerminateProcess PROTO hProcess:DWORD, uExitCode:DWORD
; ⚠ 粗暴終止:DLL 不會收到 DLL_PROCESS_DETACH,資源可能洩漏,僅作最後手段

完整範例:建立/終止子進程的 GUI 應用程式

資源定義

.const
IDM_CREATE_PROCESS equ 1
IDM_TERMINATE      equ 2
IDM_EXIT           equ 3

主視窗程序

WinMain proc ...
    ; 標準視窗類別註冊、建立、訊息迴路
    invoke GetMenu, hwnd
    mov  hMenu, eax
    .WHILE TRUE
        invoke GetMessage, ADDR msg, NULL, 0, 0
        .BREAK .IF !eax
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
    .ENDW
    ret
WinMain endp

訊息處理:動態選單啟用/禁用

WndProc proc hWnd, uMsg, wParam, lParam
    LOCAL startInfo:STARTUPINFO

    .IF uMsg == WM_DESTROY
        invoke PostQuitMessage, NULL

    .ELSEIF uMsg == WM_INITMENUPOPUP
        ; 選單彈出前動態更新狀態
        invoke GetExitCodeProcess, procInfo.hProcess, ADDR ExitCode
        .IF eax == TRUE
            .IF ExitCode == STILL_ACTIVE
                invoke EnableMenuItem, hMenu, IDM_CREATE_PROCESS, MF_GRAYED
                invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_ENABLED
            .ELSE
                invoke EnableMenuItem, hMenu, IDM_CREATE_PROCESS, MF_ENABLED
                invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_GRAYED
            .ENDIF
        .ELSE
            invoke EnableMenuItem, hMenu, IDM_CREATE_PROCESS, MF_ENABLED
            invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_GRAYED
        .ENDIF

    .ELSEIF uMsg == WM_COMMAND
        mov eax, wParam
        .IF lParam == 0          ; 選單項目
            .IF ax == IDM_CREATE_PROCESS
                ; 清理舊控制代碼
                .IF procInfo.hProcess != 0
                    invoke CloseHandle, procInfo.hProcess
                    mov procInfo.hProcess, 0
                .ENDIF
                invoke GetStartupInfo, ADDR startInfo
                invoke CreateProcess, ADDR programName, NULL, NULL, NULL, FALSE, \
                        NORMAL_PRIORITY_CLASS, NULL, NULL, ADDR startInfo, ADDR procInfo
                invoke CloseHandle, procInfo.hThread  ; 不需主執行緒控制代碼,立即釋放
            .ELSEIF ax == IDM_TERMINATE
                invoke GetExitCodeProcess, procInfo.hProcess, ADDR ExitCode
                .IF ExitCode == STILL_ACTIVE
                    invoke TerminateProcess, procInfo.hProcess, 0
                .ENDIF
                invoke CloseHandle, procInfo.hProcess
                mov procInfo.hProcess, 0
            .ELSE
                invoke DestroyWindow, hWnd
            .ENDIF
        .ENDIF
    .ELSE
        invoke DefWindowProc, hWnd, uMsg, wParam, lParam
        ret
    .ENDIF
    xor eax, eax
    ret
WndProc endp

關鍵細節與常見錯誤

  1. 必須 CloseHandle:CreateProcess 返回的 hProcess、hThread 都是核心物件控制代碼,不釋放會導致物件洩漏(進程結束後核心物件仍駐留)。
  2. 主執行緒控制代碼通常可立即關閉:除非需要 WaitForSingleObject(hThread) 等待執行緒結束或 GetThreadContext 操作暫存器。
  3. GetExitCodeProcess 失敗不代表進程不存在:可能是控制代碼無效、權限不足。結合 OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid) 更可靠。
  4. CREATE_SUSPENDED 技巧:建立暫停狀態進程 → 修改記憶體/暫存器/注入 DLL → ResumeThread 繼續執行,是偵錯器、Hook 工具、加殼器核心技術。
  5. 命令列引號規則:路徑含空格需雙引號包圍:"C:\Program Files\App.exe" arg1。
  6. Unicode 版本:CreateProcessW 支援長路徑 (>260 字元,需 \\?\ 前綴) 與 Unicode 參數。

進階主題

  • 工作物件:CreateJobObject 管理進程群組,統一限制記憶體、CPU、執行時間、強制終止全群組。
  • 受保護進程 (PPL):簽名等級高的進程,受保護免受非信任代碼注入/終止 (反惡意軟體、DRM)。
  • 最小化進程 (Pico Process):WSL 1 使用,核心模式驅動模擬 Linux 系統呼叫。
  • 進程遷移/注入:OpenProcess + VirtualAllocEx + WriteProcessMemory + CreateRemoteThread,攻防核心戰場。

總結

進程是 Windows 資源管理的核心抽象,CreateProcess 是進程創建的唯一權威入口。掌握其參數語意、返回值管理、生命週期控制、錯誤處理模式,是開發啟動器、偵錯器、沙箱、服務管理器、自動化測試框架的必備基礎。本文範例展示了從選單驅動的建立/終止流程到控制代碼正確釋放的完整最佳實務,可直接作為生產代碼骨架。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
參數建議值說明
lpApplicationName完整路徑或 NULLNULL 時從 lpCommandLine 解析模組名
lpCommandLine"app.exe param1 param2"若 lpApplicationName 非 NULL,此參數僅作參數傳遞
lpProcess/ThreadAttributesNULL預設安全描述子,子進程/執行緒不可被其他使用者存取
bInheritHandlesFALSE避免非預期控制代碼洩漏
dwCreationFlagsNORMAL_PRIORITY_CLASS常用組合:DEBUG_PROCESS, CREATE_SUSPENDED, DETACHED_PROCESS, CREATE_NEW_CONSOLE
lpEnvironmentNULL繼承父進程環境變數
lpCurrentDirectoryNULL繼承父進程當前目錄
lpStartupInfoGetStartupInfo 填充指定主視窗顯示狀態 (SW_SHOWDEFAULT 等)、標準輸入/輸出/錯誤控制代碼