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,如果在其他地方所见,均为未经允许的盗窃。