Windows编程之进程篇

    Windows系统中,进程是一个很重要的部分,进程与进程内核对象对应,同时也拥有许多属性,我们必须一一地去熟悉他们,从而来感知系统。

  • 进程属性                                                                                                                                                       进程属性进程拥有许多属性,此处讲解关键属性。 
    1. 进程对话;会话(session)是由进程和其他的系统对象(比如窗口站、桌面和窗口)构成的,它们代表了一个用户的工作站登录会话。用户登陆到windows系统之后,不管该用户是本地登陆的,还是远程登陆,系统都会为这个用户分配一个新的会话ID(SID),也就是说会话与用户的登录是相关连的,没有用户登录就不存在会话。      
    2. 进程名称
    3. 进程命令行;CreateProcess()中最终以命令行为具体启动目标,命令行中非程序名内容作为参数启动命令行行传递给子进程
    4. 进程的环境变量;如果CreateProcess()中传入NULL,子进程继承父进程的环境字符串。其实,子进程之所以和父进环境字符串(公共)部分相同,是因为session ID相同而导致的,session ID相同,则环境变量会(公共)部分相同,因为进程是为了内部的执行的线程提供一个空间和环境,而session则是为内部所有的进程提供一个执行的空间和环境,所以具有相同session ID的进程具有相同的(公共)环境字符串。        
    5. 进程当前驱动器和目录;同理,当传入NULL时,子进程与父进程的目录一样。      
    6. 进程的STARTUPINFO中的hStdInput等句柄;此I/O句柄仅仅用于控制台,指定到控制台输入输出缓冲区句柄,子进程I/O重定向时科直接运用。PS:需要设置为可继承 
    7. 进程优先级;表示进程在系统中的优先级,可用于争取执行时间
    8. 进程完整性;默认情况下,系统会为普通进程分配级别为“中”的完整性级别。级别低的进程无法访问或修改级别高的进程的资源。进程完整性是访问资源的第二道门槛。                             
  • 终止进程                                                                                                                                  
    1. 通过主线程入口的函数返回;只有通过入口的函数返回,C++对象资源才能被正确析构和释放,之后C++运行库才会再调用ExitProcess()  
    2. 进程中一个线程调用ExitProcess();线程调用此函数时,再也不会返回到当前函数调用,系统直接清理所有进程资源                                                                                
    3. 另一个进程的线程调用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:如有不对,敬请指出,谢谢~

​​​​

猜你喜欢

转载自my.oschina.net/u/3281747/blog/1154587