Windows程式設計之程序篇
阿新 • • 發佈:2018-11-25
Windows系統中,程序是一個很重要的部分,程序與程序核心物件對應,同時也擁有許多屬性,我們必須一一地去熟悉他們,從而來感知系統。
- 程序屬性 程序屬性程序擁有許多屬性,此處講解關鍵屬性。
- 程序對話;會話(session)是由程序和其他的系統物件(比如視窗站、桌面和視窗)構成的,它們代表了一個使用者的工作站登入會話。使用者登陸到windows系統之後,不管該使用者是本地登陸的,還是遠端登陸,系統都會為這個使用者分配一個新的會話ID(SID),也就是說會話與使用者的登入是相關連的,沒有使用者登入就不存在會話。
- 程序名稱
- 程序命令列;CreateProcess()中最終以命令列為具體啟動目標,命令列中非程式名內容作為引數啟動命令列行傳遞給子程序
- 程序的環境變數;如果CreateProcess()中傳入NULL,子程序繼承父程序的環境字串。其實,子程序之所以和父進環境字串(公共)部分相同,是因為session ID相同而導致的,session ID相同,則環境變數會(公共)部分相同,因為程序是為了內部的執行的執行緒提供一個空間和環境,而session則是為內部所有的程序提供一個執行的空間和環境,所以具有相同session ID的程序具有相同的(公共)環境字串。
- 程序當前驅動器和目錄;同理,當傳入NULL時,子程序與父程序的目錄一樣。
- 程序的STARTUPINFO中的hStdInput等控制代碼;此I/O控制代碼僅僅用於控制檯,指定到控制檯輸入輸出緩衝區控制代碼,子程序I/O重定向時科直接運用。PS:需要設定為可繼承
- 程序優先順序;表示程序在系統中的優先順序,可用於爭取執行時間
- 程序完整性;預設情況下,系統會為普通程序分配級別為“中”的完整性級別。級別低的程序無法訪問或修改級別高的程序的資源。程序完整性是訪問資源的第二道門檻。
- 終止程序
- 通過主執行緒入口的函式返回;只有通過入口的函式返回,C++物件資源才能被正確析構和釋放,之後C++執行庫才會再呼叫ExitProcess()
- 程序中一個執行緒呼叫ExitProcess();執行緒呼叫此函式時,再也不會返回到當前函式呼叫,系統直接清理所有程序資源
- 另一個程序的執行緒呼叫TerminateProcess();任何執行緒都可以呼叫TerminateProcess()終止另一個程序或自己的程序,同時TerminateProcess()是非同步的,呼叫之後不能馬上終止程序
- PS:程序在終止之後絕對不會洩露任何東西,同時程序終止執行時,核心物件的計數減一,狀態變為已觸發狀態
- 程序許可權控制 Windows中,程序許可權控制主要靠3個部分。安全描述符、訪問控制列表(Access Control List ACL)和完整性級別;其中安全描述符(SID)由User產生的,這表面每一個session ID都會對應一個獨一無二的SID,這意味著每個程序由使用者(啟動者)賦予許可權。當程序訪問資源時,系統會檢查ACL來核對當前SID是否擁有許可權訪問資源,如果通過檢查之後再進行完整性檢驗。檢視程序的完整性級別和訪問目標的完整性級別,如果後者高於前者,則拒絕訪問,否則訪問成功。簡而言之,Windows通過SID來標識使用者賦予程序的許可權,又通過完整性檢驗來進行第二道訪問檢查。
- 列舉程序以及程序模組
//設定當前程序優先順序為Real-time if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) cout << "Failed to set priority of current process!" << endl; DWORD parent_exp_PID = -1; string parent_name = ""; HANDLE snap_handle = NULL; snap_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (snap_handle == INVALID_HANDLE_VALUE) cout << "Create process snapshot unsuccessfully!" << "\t Error Code: " << GetLastError() << endl; PROCESSENTRY32 process_info = { 0 }; MODULEENTRY32 module_info = { 0 }; process_info.dwSize = sizeof(PROCESSENTRY32); module_info.dwSize = sizeof(MODULEENTRY32); cout << "Process Name" << "\t\t" << "Process ID" << "Parent PID" << endl; if (Process32First(snap_handle, &process_info)) { //通過程序快照控制代碼,遍歷列舉程序 do { cout << process_info.szExeFile << "\t\t" << process_info.th32ProcessID << "\t" << process_info.th32ParentProcessID << endl; //通過程序控制代碼,遍歷列舉每個程序有關的模組 //當呼叫程序是一個32-bit程式,而快照程序是一個64-bit程式時候,CreateToolHelp32Snashot將會失敗,GetLastError得到ERROR_PARTIAL_COPY (299) HANDLE mod_snap_handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process_info.th32ProcessID); if (INVALID_HANDLE_VALUE==mod_snap_handle) { DWORD error_code = GetLastError(); continue; } if (Module32First(mod_snap_handle, &module_info)) { do { cout <<"\t"<< module_info.szModule << endl; } while (Module32Next(mod_snap_handle,&module_info)); } CloseHandle(mod_snap_handle); if (0==strcmp(process_info.szExeFile,TEXT("explorer.exe"))) parent_exp_PID = process_info.th32ParentProcessID; if (parent_exp_PID != -1 && process_info.th32ProcessID == parent_exp_PID) parent_name = process_info.szExeFile; } while (Process32Next(snap_handle, &process_info)); CloseHandle(snap_handle); } else cout << "Failed to get process information in the beginning." << "\t Error Code: " << GetLastError() << endl; cout << "Explorer's father process: " << parent_name << "\t" << "PID: " << parent_exp_PID << endl;
- 程序I/O重定向
string file_name = TEXT("Fucker.txt"); HANDLE output_file_handle=NULL, input_file_handle=NULL; SECURITY_ATTRIBUTES handle_sec_attributes = { { 0 } }; handle_sec_attributes.nLength = sizeof(SECURITY_ATTRIBUTES); handle_sec_attributes.bInheritHandle = TRUE; //指定這個輸出檔案控制代碼是可繼承的 handle_sec_attributes.lpSecurityDescriptor = NULL; output_file_handle = CreateFile(file_name.c_str(), GENERIC_WRITE, FILE_SHARE_READ, &handle_sec_attributes, OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == output_file_handle) { cout << "Failed to create file !" << endl; return -1; } TCHAR exe_name[] = TEXT("4s.exe"); STARTUPINFO start_info = { 0 }; start_info.cb = sizeof(STARTUPINFO); start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); start_info.hStdOutput = output_file_handle; start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); start_info.dwFlags = STARTF_USESTDHANDLES; PROCESS_INFORMATION process_info = { 0 }; //isInheritable要設定成TRUE,這樣子程序才能繼承到I/O檔案控制代碼,進而使用它們 if (!CreateProcess(exe_name, NULL, NULL, NULL, TRUE, REALTIME_PRIORITY_CLASS|CREATE_NEW_CONSOLE, NULL, NULL, &start_info, &process_info)) cout << "Failed to create process !" << endl; CloseHandle(output_file_handle); CloseHandle(process_info.hThread); CloseHandle(process_info.hProcess);
PS:如有不對,敬請指出,謝謝~