32位程式獲取32/64位進程文件地址通用方法
32位程式獲取32/64位進程文件地址通用方法
引子
一般來說,限於32位程式GetModuleFileNameEx對於64位程式來說是不管用的,我們如果需要在32位程式獲得64位進程的運行目錄可能需要用到wow64或者是QueryFullProcessImageName。
但是
前者雖然通用,但是實現起來過於複雜,還需要用到彙編,後者
Minimum supported client | Windows Vista [desktop apps only] |
---|---|
Minimum supported server | Windows Server 2008 [desktop apps only] |
上為ms docs給出的限制條件,顯然無法支援到諸如XP之類的系統
顯然這個API不是通用的,那麼如果我們需要一個通用且方便的方法怎麼辦呢?
這時候就可以祭出我們的GetProcessImageFileNameA
Minimum supported client | Windows XP [desktop apps only] |
---|---|
Minimum supported server | Windows Server 2003 [desktop apps only] |
Target Platform | Windows |
Header | psapi.h |
Library | Kernel32.lib on Windows 7 and Windows Server 2008 R2; Psapi.lib (if PSAPI_VERSION=1) on Windows 7 and Windows Server 2008 R2; Psapi.lib on Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP |
DLL | Kernel32.dll on Windows 7 and Windows Server 2008 R2; Psapi.dll (if PSAPI_VERSION=1) on Windows 7 and Windows Server 2008 R2; Psapi.dll on Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP |
支援還是蠻全的
但是注意到這個API返回的是Native Path(\\**\****),而不是我們熟悉的Dos Path(X:\**\***)
所以我們還需要QueryDosDeviceA進行轉換
值得一提的是,根據這個API所屬DLL的變更,我們有理由認為QueryFullProcessImageName實際上就是這個API的封裝
程式碼實現
/*
Created on: 2022-02-01
Created by: Icys
*/
#include <iostream>
#include <cstring>
#include <windows.h>
#include <psapi.h>
#include <cstring>
//將Nt文件路徑轉為Dos文件路徑
std::string NTFilePath2DosFilePath(std::string name)
{
char szDriveStr[MAX_PATH] = {0};
char szDeviceStr[MAX_PATH] = {0};
char szDrive[3] = {0};
int cchDevName = 0;
if (GetLogicalDriveStringsA(sizeof(szDriveStr), szDriveStr) == 0)
{
return "";
}
for (int i = 0; szDriveStr[i]; i += 4)
{
memcpy(szDrive, szDriveStr + i, 2);
if (!QueryDosDeviceA(szDrive, szDeviceStr, sizeof(szDeviceStr)))
{
return "";
}
cchDevName = lstrlenA(szDeviceStr);
if (strnicmp(szDeviceStr, name.c_str(), cchDevName) == 0) //比較前綴
{
name.replace(0, cchDevName, szDrive);
return name;
}
}
return "";
}
std::string GetProcessPath(int PID)
{
auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
if (!hProcess)
return "";
char *FileNativePath = new char[MAX_PATH + 1];
if (!GetProcessImageFileNameA(hProcess, FileNativePath, MAX_PATH + 1))
return "";
std::string FilePath = NTFilePath2DosFilePath(FileNativePath);
delete[] FileNativePath;
return FilePath;
}
int main()
{
std::cout << GetProcessPath(15572) << std::endl;
return 0;
}
後記
本文由Icys編纂並發表,僅發表於CNBLOG,如果在其他地方所見,均為未經允許的盜竊。