1. 需求背景
在使用DLL注入时,进程需要获取目标进程的位数,来决定注入32位/64位的DLL
2. 实现原理
先使用自身进程
的句柄调用IsWow64Process
得到当前操作系统位数,
再调用IsWow64Process
来获得目的进程ID的进程位数。
3. 代码如下
#include <windows.h>
#include <tchar.h>
/*
* 作者: shang_cm
* 时间: 2019-10-09
* 函数功能: 获取指定PID进程的位数
* 参数: _uProcessID 目标进程ID
* 返回值: 0 获取失败
* 32 32位程序
* 64 64位程序
*/
UINT GetProcessPlatform(DWORD dwProcessID)
{
typedef BOOL(WINAPI * LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
static LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
if (NULL == fnIsWow64Process)
{
HMODULE hKernel32 = GetModuleHandle(_T("kernel32"));
if (NULL == hKernel32)
{
return 0;
}
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hKernel32, "IsWow64Process");
if (NULL == fnIsWow64Process)
{
return 0;
}
}
static UINT OSPlatform = 0;
if (0 == OSPlatform)
{
HANDLE hCurProcess = GetCurrentProcess();
if (NULL == hCurProcess)
{
return 0;
}
BOOL bWow64 = FALSE;
BOOL bError = fnIsWow64Process(hCurProcess, &bWow64);
CloseHandle(hCurProcess);
if (FALSE == bError)
{
return 0;
}
#ifdef _WIN64
OSPlatform = 64;
#else
OSPlatform = bWow64 ? 64 : 32;
#endif // _WIN64
}
if (32 == OSPlatform)
{
return 32;
}
UINT uRet = 0;
HANDLE hDstProcess = NULL;
BOOL bError = FALSE;
BOOL bWow64 = FALSE;
hDstProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
if (NULL == hDstProcess)
{
goto FUN_CLEANUP;
}
bError = fnIsWow64Process(hDstProcess, &bWow64);
if (FALSE == bError)
{
goto FUN_CLEANUP;
}
uRet = bWow64 ? 32 : 64;
FUN_CLEANUP:
if (NULL != hDstProcess)
{
CloseHandle(hDstProcess);
hDstProcess = NULL;
}
return uRet;
}
4. 注意事项
- 一定要采用动态加载
IsWow64Process
函数指针的方式实现,不能直接使用此函数,因为在Windows XP SP2及以下的kernel32.dll
中并不存在此函数,会导致整个程序无法加载起来 IsWow64Process
并不是直接给出对应进程是不是64位的,而是判断一个程序是否运行在Wow64位兼容模式下。- 不同操作系统上运行不同位数进程,调用
IsWow64Process
结果如下:
32位操作系统 | 64位操作系统 | |
---|---|---|
32位应用程序 | FALSE | TRUE |
64位应用程序 | 无法运行 | FALSE |