获取所有进程的进程ID和EXE文件名
方式1:通过进程快照CreateToolhelp32Snapshot(),获取所有进程的ID和进程EXE名(不是路径)
#include <tlHelp32.h>
#include <vector>
void MyTools::GetPEntryList(OUT std::vector<PROCESSENTRY32*>& list)
{
HANDLE handle;
handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32* info = new PROCESSENTRY32;
info->dwSize = sizeof(PROCESSENTRY32);
Process32First(handle, info);
while (Process32Next(handle, info) != FALSE)
{
DWORD PID = info->th32ProcessID;
wchar_t* ExeName = info->szExeFile;
PROCESSENTRY32* copyInfo = new PROCESSENTRY32;
*copyInfo = *info;
list.push_back(copyInfo);
}
delete(info);
CloseHandle(handle);
return;
}
方式2:通过枚举进程EnumProcesses(),只能获取所有进程的ID
void GetPIDList(OUT std::vector<int>& PIDList)
{
DWORD PIDs[500];
DWORD NeededSize;
EnumProcesses(OUT PIDs, sizeof(PIDs), OUT & NeededSize);
int numberOfPID = (NeededSize / sizeof(DWORD));
for (int i = 0; i < numberOfPID; i++)
{
PIDList.push_back(PIDs[i]);
}
return;
}
- 注意,不论是CreateToolhelp32Snapshot()还是EnumProcesses(),得到的进程数量都是一样的。盲猜CreateToolhelp32Snapshot的内部是调用了EnumProcesses()。
打开进程句柄(通过进程ID)
- OpenProcess() 打开某进程,且声明需要的权限,一般可以声明PROCESS_ALL_ACCESS即所有权限。
- 有的进程无法打开,尝试用管理员身份运行EXE后可以打开一部分进程(如svhost.exe),但仍有一些进程无法打开(如System、smss.exe等)。
void OpenProcessByPID(int PID,OUT HANDLE& hProcess)
{
hProcess = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);
if (hProcess == 0)
{
MessageBox(0, L"打开进程失败:是否开启管理员身份?是否在32位进程中尝试打开64位进程?", 0, 0);
}
return;
}
- 打开当前进程的句柄
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,GetCurrentProcessId());
- 32位进程中无法打开64位进程,而64位进程既可以打开32位进程也可以打开64位进程。
- 可以使用IsWow64Process宏判断目标进程的位数。
BOOL Wow64Process;
IsWow64Process(hProcess, &Wow64Process);
if(Wow64Process==TRUE){printf("目标进程是32位进程");}
- 提权函数:经测试发现没有任何效果,可能win10不再需要提权令牌了?只需管理员权限就够了?
bool UpPrivileges()
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
TOKEN_PRIVILEGES oldtp;
DWORD dwSize = sizeof(TOKEN_PRIVILEGES);
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
MessageBox(0, L"OpenProcessToken is FALSE ", 0, 0);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
printf("OpenProcessToken GetLastError() == ERROR_CALL_NOT_IMPLEMENTED \n");
return true;
}
else
{
printf("OpenProcessToken GetLastError() ==Others \n");
return false;
}
}
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
CloseHandle(hToken);
MessageBox(0, L"LookupPrivilegeValue is FALSE ", 0, 0);
return false;
}
ZeroMemory(&tp, sizeof(tp));
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
/* Adjust Token Privileges */
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) {
CloseHandle(hToken);
MessageBox(0, L"AdjustTokenPrivileges == FALSE ", 0, 0);
return false;
}
printf("UpPrivileges Success ! \n");
CloseHandle(hToken);
return true;
}
打开模块句柄/基址(根据进程句柄、模块名)
- 通过GetModuleHandle(NULL)只能获取当前进程的模块基址,参数为NULL表示获取主模块基址
- 通过EnumProcessModulesEx()可以枚举任意进程的所有模块句柄,其中首个模块句柄就是主模块的基址。
void OpenModuleByName(HANDLE hProcess, wchar_t* destModuleName, OUT HMODULE& hModule)
{
if (hProcess == 0) { hModule = 0; return; }
HMODULE moduleArray[500] = { 0 };
DWORD neededSize = 0;
EnumProcessModulesEx(hProcess, OUT moduleArray, sizeof(moduleArray), OUT & neededSize, LIST_MODULES_ALL);
if (destModuleName == NULL)
{
hModule = moduleArray[0];
}
else
{
int NumOfModule = neededSize / sizeof(HMODULE);
for (int i = 0; i < NumOfModule; i++)
{
WCHAR moduleFileName[50] = { 0 };
MyTools::GetModuleName(hProcess, moduleArray[i], moduleFileName);
if (wcscmp(moduleFileName, destModuleName) == 0) { hModule = moduleArray[i]; return; }
}
}
}
获取模块的文件全路径(根据进程句柄、模块句柄)
- 获取目标进程的主模块全路径(根据模块句柄)
- 参数hModule表示模块的在目标进程的载入地址/基址+
- 如果传入hModule=NULL,则表示获取主模块全路径,即进程全路径。
WCHAR filePath[200] = { 0 };
GetModuleFileNameEx(hProcess, hModule,OUT filePath, sizeof(filePath) );
获取模块的文件名(根据进程句柄、模块句柄)
- 通过截取模块的文件全路径可以得到模块文件名
- 传入模块句柄=NULL表示主模块的文件名,即’进程名’。
void MyTools::GetModuleName(HANDLE hProcess, HMODULE hModule, OUT WCHAR* ModuleFileName)
{
if (hProcess == 0)return;
WCHAR fullPath[200] = { 0 };
DWORD bufferSize = GetModuleFileNameEx(hProcess, hModule, OUT fullPath, sizeof(fullPath));
int len = wcslen(fullPath);
for (int i = len - 1; i >= 0; i--)
{
if (fullPath[i] == L'\\')
{
wcscpy(ModuleFileName, &fullPath[i + 1]);
break;
}
}
}
获取模块的镜像大小、入口地址(通过进程句柄、模块起始地址)
- GetModuleInformation()实际上是通过分析模块的PE头结构,从而返回ImageSize和EntryPoint的,所以参数hModule必须是模块的起始镜像地址,所以传入hModule=NULL并不能得到主模块的信息。
MODULEINFO moduleInfo = { 0 };
GetModuleInformation(hProcess, hModule, OUT & moduleInfo, sizeof(moduleInfo));
moduleInfo.lpBaseOfDll;
moduleInfo.SizeOfImage;
moduleInfo.EntryPoint;
读取进程的内存
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);
LPVOID destAddr=(LPVOID)0x7ff7e1e40000;
BYTE buffer[1024] = { 0 };
unsigned __int64 numberOfReadedByte = 0;
ReadProcessMemory(hProcess, destAddr, OUT buffer, sizeof(buffer), &numberOfReadedByte );
if (numberOfReadedByte == 0)
{
DWORD code = GetLastError();
MessageBox(0, L"读取进程内存失败", 0, 0);
return false;
}
获取进程的所有模块的句柄
HMODULE moduleArray[500] = { 0 };
DWORD neededSize = 0;
EnumProcessModulesEx(hProcess, OUT moduleArray, sizeof(moduleArray), OUT & neededSize, LIST_MODULES_ALL);
HMODULE moduleArray[500] = { 0 };
DWORD neededSize = 0;
HANDLE hCurrentProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,GetCurrentProcessId());
EnumProcessModulesEx(hCurrentProcess , OUT moduleArray, sizeof(moduleArray), OUT & neededSize, LIST_MODULES_ALL);