C/C++ 進程線程操作技術


手動創建單進程: 下面通過一個實例來分別演示進程的創建函數.

#include <windows.h>
#include <stdio.h>

BOOL WinExec(char *pszExePath, UINT uiCmdShow)
{
	UINT uiRet = 0;
	uiRet = ::WinExec(pszExePath, uiCmdShow);
	if (31 < uiRet)
	{
		return TRUE;
	}
	return FALSE;
}

BOOL ShellExecute(char *pszExePath, UINT uiCmdShow)
{
	HINSTANCE hInstance = 0;
	hInstance = ::ShellExecute(NULL, NULL, pszExePath, NULL, NULL, uiCmdShow);
	if (32 < (DWORD)hInstance)
	{
		return TRUE;
	}
	return FALSE;
}

BOOL Exec_Run(LPCSTR exe_file)
{
	PROCESS_INFORMATION pi = { 0 };
	STARTUPINFO si = { 0 };
	si.cb = sizeof(STARTUPINFO);

	BOOL bRet = CreateProcessA(exe_file,
		NULL, NULL, NULL, FALSE,
		NULL, NULL, NULL, &si, &pi);

	if (bRet != FALSE)
	{
		CloseHandle(pi.hThread);
		CloseHandle(pi.hProcess);
		return TRUE;
	}
	return FALSE;
}

int main(int argc, char * argv[])
{
	int ret = 0;
	ret = Exec_Run("c:\\windows\\system32\\notepad.exe");
	printf("執行狀態: %d \n", ret);

	system("pause");
	return 0;
}

手動創建多線程: 多線程的創建需要使用CreateThread()其內部應該傳遞進去ThreadProc()線程執行函數,運行結束后恢復.

#include <Windows.h>
#include <iostream>

int Global_One = 0;
CRITICAL_SECTION g_cs;

// 定義一個線程函數
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
	// 加鎖防止線程數據沖突
	EnterCriticalSection(&g_cs);
	for (int x = 0; x < 10; x++)
	{
		Global_One++;
		Sleep(1);
	}
	// 執行完修改以后,需要釋放鎖
	LeaveCriticalSection(&g_cs);
	return 0;
}

int main()
{
	// 初始化鎖
	InitializeCriticalSection(&g_cs);

	HANDLE hThread[10] = { 0 };

	for (int x = 0; x < 10; x++)
	{
		// 循環創建線程
		hThread[x] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
	}
	// 等待多個線程執行結束.
	WaitForMultipleObjects(10, hThread, TRUE, INFINITE);

	// 最后循環釋放資源
	for (int x = 0; x < 10; x++)
	{
		CloseHandle(hThread[x]);
	}

	printf("Global: %d \n", Global_One);
	DeleteCriticalSection(&g_cs);

	system("pause");
	return 0;
}

強制終止一個進程: 在進程正常進行退出時,會調用ExitProcess()正常關閉程序,也可以調用TerminateProcess()強制銷毀進程.

#include <windows.h>
#include <stdio.h>

int Get_ProcessID(LPCSTR path)
{
	HWND hWnd = FindWindow(NULL, path);
	if (hWnd != NULL)
	{
		DWORD dwPid = 0;
		GetWindowThreadProcessId(hWnd, &dwPid);
		if (dwPid != 0)
			return dwPid;
	}
	return -1;
}

int main(int argc,char * argv [])
{
	int pid = 0;

	pid = Get_ProcessID("新建文本文檔.txt - 記事本");
	printf("進程PID為: %d \n", pid);

	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
	if (hProcess != NULL)
	{
		TerminateProcess(hProcess, 0);   // 終止進程
	}
	
	system("pause");
	return 0;
}

判斷進程是否存在: 通過循環遍歷所有進程,並對比szExeFile名稱是否與pName一致,來實現判斷進程是否正在運行中.

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

int Get_Process_Status(const char *procressName)
{
	char pName[MAX_PATH];
	strcpy(pName, procressName);                           // 拷貝數組
	CharLowerBuff(pName, MAX_PATH);                        // 將名稱轉換為小寫
	
	PROCESSENTRY32 currentProcess;                                    // 存放快照進程信息的一個結構體
	currentProcess.dwSize = sizeof(currentProcess);                   // 在使用這個結構之前,先設置它的大小
	HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 給系統內的所有進程拍一個快照

	if (INVALID_HANDLE_VALUE != hProcess)
	{
		BOOL bMore = Process32First(hProcess, &currentProcess);
		while (bMore)
		{
			CharLowerBuff(currentProcess.szExeFile, MAX_PATH);        // 將進程名轉換為小寫
			if (strcmp(currentProcess.szExeFile, pName) == 0)         // 比較是否存在此進程
			{
				CloseHandle(hProcess);
				return 1;
			}
			bMore = Process32Next(hProcess, &currentProcess);
		}
		CloseHandle(hProcess);
	}
	return -1;
}

int main(int argc,char * argv [])
{
	int ret = Get_Process_Status("qq.exe");

	if (ret == 1)
		printf("正在運行. \n");
	else
		printf("沒有運行. \n");

	system("pause");
	return 0;
}

遍歷獲取進程PID:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

DWORD FindProcessID(LPCTSTR szProcessName)
{
	DWORD dwPID = 0xFFFFFFFF;
	HANDLE hSnapShot = INVALID_HANDLE_VALUE;
	PROCESSENTRY32 pe;
	pe.dwSize = sizeof(PROCESSENTRY32);
	hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
	Process32First(hSnapShot, &pe);
	do
	{
		if (!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile))
		{
			dwPID = pe.th32ProcessID;
			break;
		}
	} while (Process32Next(hSnapShot, &pe));
	CloseHandle(hSnapShot);
	return dwPID;
}

int main(int argc,char *argv[])
{
	DWORD PID = FindProcessID(L"qq.exe");
	printf("該進程PID是: %d \n", PID);

	system("pause");
	return 0;
}

枚舉系統中所有進程:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int EnumProcess()
{
	PROCESSENTRY32 pe32 = { 0 };
	pe32.dwSize = sizeof(PROCESSENTRY32);

	// 獲取全部進程快照
	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE != hProcessSnap)
	{
		// 獲取快照中第一條信息
		BOOL bRet = Process32First(hProcessSnap, &pe32);
		while (bRet)
		{
			printf("進程ID: %-5d --> 進程名: %s \n", pe32.th32ProcessID, pe32.szExeFile);
			// 獲取快照中下一條信息
			bRet = Process32Next(hProcessSnap, &pe32);
		}
		CloseHandle(hProcessSnap);
	}
	return -1;
}

int main(int argc,char * argv [])
{
	EnumProcess();

	system("pause");
	return 0;

}

枚舉指定進程中的DLL模塊: 枚舉出指定PID進程中所加載的DLL

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int EnumProcessModule(DWORD Pid)
{
	MODULEENTRY32 me32 = { 0 };
	me32.dwSize = sizeof(MODULEENTRY32);
	// 獲取指定進程全部模塊的快照
	HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Pid);

	if (INVALID_HANDLE_VALUE != hModuleSnap)
	{
		// 獲取快照中第一條信息
		BOOL bRet = Module32First(hModuleSnap, &me32);
		while (bRet)
		{
			printf("模塊基址: 0x%p --> 大小: %-8d --> 模塊名: %-25s -> 路徑: %s \n",
				me32.modBaseAddr, me32.modBaseSize, me32.szModule,me32.szExePath);

			// 獲取快照中下一條信息
			bRet = Module32Next(hModuleSnap, &me32);
		}
		CloseHandle(hModuleSnap);
		return 0;
	}
	return -1;
}

int main(int argc,char * argv [])
{
	EnumProcessModule(1920);

	system("pause");
	return 0;
}

枚舉進程中線程ID:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int EnumThread(DWORD Pid)
{
	THREADENTRY32 te32 = { 0 };
	te32.dwSize = sizeof(THREADENTRY32);
	int index = 0;

	// 獲取全部線程快照
	HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (INVALID_HANDLE_VALUE != hThreadSnap)
	{
		// 獲取快照中第一條信息
		BOOL bRet = Thread32First(hThreadSnap, &te32);
		while (bRet)
		{
			// 只過濾出 Owner Process ID = pid 的線程ID
			if (Pid == te32.th32OwnerProcessID)
			{
				printf("線程ID: %6d --> 大小: %d \n", te32.th32ThreadID,te32.dwSize);
				++index;
			}

			// 獲取快照中下一條信息
			bRet = Thread32Next(hThreadSnap, &te32);
		}
		CloseHandle(hThreadSnap);
		return index;
	}
	return -1;
}

int main(int argc,char * argv [])
{
	int tid_count = EnumThread(9868);
	printf("線程數: %d \n", tid_count);

	system("pause");
	return 0;
}

判斷進程是否重復運行:

#include <Windows.h>
#include <stdio.h>

// 判斷是否重復運行
BOOL IsAlreadyRun()
{
	HANDLE hMutex = NULL;
	hMutex = CreateMutex(NULL, FALSE, "RUN");
	if (hMutex)
	{
		if (ERROR_ALREADY_EXISTS == GetLastError())
			return TRUE;
	}
	return FALSE;
}

int main(int argc, const char * argv[])
{
	if (IsAlreadyRun() == TRUE)
		printf("重復運行 \n");
	else
		printf("沒有重復運行 \n");

	system("pause");
	return 0;
}

循環干掉特定進程: 該方式只能干掉普通的檢測程序,無法干掉帶有自保護的殺軟,需要加載驅動。

#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>

int Kill_AV_Process(char *kill_list[],int Count)
{
	PROCESSENTRY32 currentProcess;
	currentProcess.dwSize = sizeof(currentProcess); 
	HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

	if (INVALID_HANDLE_VALUE != hProcess)
	{
		BOOL bMore = Process32First(hProcess, &currentProcess);
		while (bMore)
		{
			CharLowerBuff(currentProcess.szExeFile, MAX_PATH);
			
			for (int each = 0; each < Count; each++)
			{
				if (strcmp(currentProcess.szExeFile, kill_list[each]) == 0)
				{
					// printf("干掉進程 --> %s \n", kill_list[each]);
					HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, currentProcess.th32ProcessID);
					TerminateProcess(hProcess, 0);
				}
			}
			bMore = Process32Next(hProcess, &currentProcess);
		}
		CloseHandle(hProcess);
	}
	return -1;
}

int main(int argc, char * argv[])
{
	// 填寫殺毒軟件的進程名稱,然后循環干掉進程
	char *fuck[10] = { "chrome.exe", "360.exe","qqpctray.exe","qqpcrtp.exe","qmdl.exe" };
	Kill_AV_Process(fuck,5);

	system("pause");
	return 0;
}

暫停/恢復指定的線程:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int Start_Stop_Thread(DWORD Pid,DWORD ThreadID)
{
	THREADENTRY32 te32 = { 0 };
	te32.dwSize = sizeof(THREADENTRY32);

	// 獲取全部線程快照
	HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (INVALID_HANDLE_VALUE != hThreadSnap)
	{
		// 獲取快照中第一條信息
		BOOL bRet = Thread32First(hThreadSnap, &te32);
		while (bRet)
		{
			// 只過濾出 pid 里面的線程
			if (Pid == te32.th32OwnerProcessID)
			{
				// 判斷是否為ThreadID,暫停指定的TID
				if (ThreadID == te32.th32ThreadID)
				{
					// 打開線程
					HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
					
					SuspendThread(hThread);     // 暫停線程
					//ResumeThread(hThread);    // 恢復線程
					CloseHandle(hThreadSnap);
				}
			}
			// 獲取快照中下一條信息
			bRet = Thread32Next(hThreadSnap, &te32);
		}
		return 0;
	}
	return -1;
}

int main(int argc, char * argv[])
{
	// 暫停或恢復進程ID = 4204 里面的線程ID = 10056
	int ret = Start_Stop_Thread(4204,10056);
	printf("狀態: %d \n", ret);

	system("pause");
	return 0;
}

枚舉進程內存權限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h>

void ScanMemoryAttribute()
{
	DWORD Addres = 0, Size = 0;
	MEMORY_BASIC_INFORMATION Basicinfo = {};

	// 遍歷進程所有分頁, 輸出內容
	while (VirtualQuery((LPCVOID)Addres, &Basicinfo, sizeof(MEMORY_BASIC_INFORMATION)))
	{
		Size = Basicinfo.RegionSize;
		printf("地址: %08p 類型: %7d 大小: %7d 狀態: ", Basicinfo.BaseAddress,Basicinfo.Type,Basicinfo.RegionSize);
		switch (Basicinfo.State)
		{
		case MEM_FREE:      printf("空閑 \n"); break;
		case MEM_RESERVE:   printf("保留 \n"); break;
		case MEM_COMMIT:    printf("提交 \n"); break;
		default: printf("未知 \n"); break;
		}

		// 如果是提交狀態的內存區域,那么遍歷所有塊中的信息
		if (Basicinfo.State == MEM_COMMIT)
		{
			// 遍歷所有基址是 Address
			LPVOID BaseBlockAddress = (LPVOID)Addres;
			DWORD BlockAddress = Addres;
			DWORD dwBlockSize = 0;
			// 遍歷大內存塊中的小內存塊
			while (VirtualQuery((LPVOID)BlockAddress, &Basicinfo, sizeof(Basicinfo)))
			{
				if (BaseBlockAddress != Basicinfo.AllocationBase)
				{
					break;
				}
				printf("--> %08X", BlockAddress);
				// 查看內存狀態,映射方式
				switch (Basicinfo.Type)
				{
				case MEM_PRIVATE:   printf("私有  "); break;
				case MEM_MAPPED:    printf("映射  "); break;
				case MEM_IMAGE:     printf("鏡像  "); break;
				default: printf("未知  "); break;
				}

				if (Basicinfo.Protect == 0)
					printf("---");
				else if (Basicinfo.Protect & PAGE_EXECUTE)
					printf("E--");
				else if (Basicinfo.Protect & PAGE_EXECUTE_READ)
					printf("ER-");
				else if (Basicinfo.Protect & PAGE_EXECUTE_READWRITE)
					printf("ERW");
				else if (Basicinfo.Protect & PAGE_READONLY)
					printf("-R-");
				else if (Basicinfo.Protect & PAGE_READWRITE)
					printf("-RW");
				else if (Basicinfo.Protect & PAGE_WRITECOPY)
					printf("WCOPY");
				else if (Basicinfo.Protect & PAGE_EXECUTE_WRITECOPY)
					printf("EWCOPY");
				printf("\n");

				// 計算所有相同塊大小
				dwBlockSize += Basicinfo.RegionSize;
				// 累加內存塊的位置
				BlockAddress += Basicinfo.RegionSize;
			}
			// 內有可能大小位空
			Size = dwBlockSize ? dwBlockSize : Basicinfo.RegionSize;
		}
		// 下一個區域內存信息
		Addres += Size;
	}
}

int main(int argc, char * argv[])
{
	ScanMemoryAttribute();
	system("pause");
	return 0;
}

查詢進程所具備的權限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h>

BOOL QueryPrivileges()
{
	// 1. 獲得本進程的令牌
	HANDLE hToken = NULL;
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
		return false;
	
	// 2. 獲取提升類型
	TOKEN_ELEVATION_TYPE ElevationType = TokenElevationTypeDefault;
	BOOL  bIsAdmin = false;
	DWORD dwSize = 0;

	if (GetTokenInformation(hToken, TokenElevationType, &ElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize))
	{
		// 2.1 創建管理員組的對應SID
		BYTE adminSID[SECURITY_MAX_SID_SIZE];
		dwSize = sizeof(adminSID);
		CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID, &dwSize);

		// 2.2 判斷當前進程運行用戶角色是否為管理員
		if (ElevationType == TokenElevationTypeLimited)
		{
			// a. 獲取連接令牌的句柄
			HANDLE hUnfilteredToken = NULL;
			GetTokenInformation(hToken, TokenLinkedToken, (PVOID)&hUnfilteredToken, sizeof(HANDLE), &dwSize);
			// b. 檢查這個原始的令牌是否包含管理員的SID
			if (!CheckTokenMembership(hUnfilteredToken, &adminSID, &bIsAdmin))
				return false;
			CloseHandle(hUnfilteredToken);
		}
		else
		{
			bIsAdmin = IsUserAnAdmin();
		}
	}

	// 3. 判斷具體的權限狀況
	BOOL bFullToken = false;
	switch (ElevationType) 
	{
		case TokenElevationTypeDefault: /* 默認的用戶或UAC被禁用 */
			if (IsUserAnAdmin())
				bFullToken = true;      // 默認用戶有管理員權限
			else
				bFullToken = false;     // 默認用戶不是管理員組
			break;
		
		case TokenElevationTypeFull:    /* 已經成功提高進程權限 */
			if (IsUserAnAdmin())
				bFullToken = true;      // 當前以管理員權限運行
			else
				bFullToken = false;     // 當前未以管理員權限運行
			break;

		case TokenElevationTypeLimited: /* 進程在以有限的權限運行 */
			if (bIsAdmin)
				bFullToken = false;     // 用戶有管理員權限,但進程權限有限
			else
				bFullToken = false;     // 用戶不是管理員組,且進程權限有限
			break;
	}
	return bFullToken;
}

int main(int argc, char * argv[])
{
	BOOL ret = QueryPrivileges();
	printf("具備權限: %d \n", ret);

	system("pause");
	return 0;
}

枚舉指定進程權限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h>

void ShowPrviliges(HANDLE process)
{
	// 通過進程句柄獲取到進程令牌
	HANDLE hToken;
	OpenProcessToken(process, TOKEN_QUERY, &hToken);

	// 獲取查詢道德令牌信息
	DWORD dwSize;
	GetTokenInformation(hToken,TokenPrivileges, NULL, NULL, &dwSize);
	
	// 根據令牌中的大小分配空間
	char *pBuf = new char[dwSize] {};
	GetTokenInformation(hToken,TokenPrivileges, pBuf, dwSize, &dwSize);

	// 將內存中的內容用要查詢數據結構體解析
	TOKEN_PRIVILEGES* pTp = (TOKEN_PRIVILEGES*)pBuf;
	DWORD dwCount = pTp->PrivilegeCount;               // 解析出權限個數
	LUID_AND_ATTRIBUTES* pluid = pTp->Privileges;      // 具備的權限類型

	for (int i = 0; i < dwCount; i++, pluid++)
	{
		char szName[100] = {};
		DWORD dwLen = sizeof(szName);
		LookupPrivilegeNameA(0, &pluid->Luid, szName, &dwLen);
		switch (pluid->Attributes)
		{
		case 0:
			printf("[ID: %3d] ---> [關閉]      ---> %s \n", i,szName); break;
		case 1:
			printf("[ID: %3d] ---> [默認]      ---> %s \n", i,szName); break;
		case 2:
			printf("[ID: %3d] ---> [開啟]      ---> %s \n", i,szName); break;
		case 3:
			printf("[ID: %3d] ---> [默認開啟]  ---> %s \n", i,szName); break;
		}
	}
	delete pBuf;
}

int main(int argc ,char *argv[])
{
	// 拿到PID為9656程序的句柄
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 9656);
	ShowPrviliges(hProcess);

	// 拿到自身程序的句柄
	HANDLE LocalProcess = GetCurrentProcess();
	ShowPrviliges(LocalProcess);

	system("pause");
	return 0;
}

提升指定進程權限:

#include <windows.h>
#include <stdio.h>

int EnbalePrivileges(HANDLE hProcess, char *pszPrivilegesName)
{
	HANDLE hToken = NULL;
	LUID luidValue = { 0 };
	TOKEN_PRIVILEGES tokenPrivileges = { 0 };
	BOOL bRet = FALSE;
	DWORD dwRet = 0;

	// 打開進程令牌並獲取具有 TOKEN_ADJUST_PRIVILEGES 權限的進程令牌句柄
	bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
	if (bRet != FALSE)
	{
		// 獲取本地系統的 pszPrivilegesName 特權的LUID值
		bRet = LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue);
		if (bRet == FALSE)
			return -1;
	}

	// 設置提升權限信息
	tokenPrivileges.PrivilegeCount = 1;
	tokenPrivileges.Privileges[0].Luid = luidValue;
	tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	// 提升進程令牌訪問權限
	bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL);
	if (bRet != FALSE)
	{
		// 根據錯誤碼判斷是否特權都設置成功
		dwRet = GetLastError();
		if (ERROR_SUCCESS == dwRet)
		{
			return 1;
		}
	}
	return -1;
}

int main(int argc,char * argv [])
{
	// 獲取當前自身進程句柄
	HANDLE Local_Pid = GetCurrentProcess();

	// 修改當前進程令牌訪問權限
	if (FALSE != EnbalePrivileges(Local_Pid, SE_DEBUG_NAME))
		printf("提權成功 \n");

	system("pause");
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM