- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试使用以下代码从 64 位应用程序中枚举 32 位进程模块名称:
if (EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNeeded, LIST_MODULES_ALL))
{
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH] = { 0 };
if (GetModuleFileNameEx(hProcess, hMods[i], szModName,
sizeof(szModName) / sizeof(TCHAR)))
{
printf("module name is: %S", szModName);
}
}
}
代码在 Windows 7 中按预期工作,部分结果为:
...
C:\Windows\**SysWOW64**\ntdll.dll
...
在 Windows 10 中,上述代码返回完整路径,但使用的是 System32 而不是 SysWOW64。例如,
...
C:\Windows\**System32**\ntdll.dll
...
深入了解原因,我注意到 GetModuleFileNameEx 读取远程进程 PEB 和 LDR_TABLE_ENTRY,从 Windows 10 开始,LDR_TABLE_ENTRY 包含 System32 而不是 SysWOW64 的完整路径 - 也适用于 32 位应用程序。
我也尝试使用 GetMappedFileName,但将路径从 dos 路径 (\device\harddiskvolume) 转换为标准 (c:\) 路径并不直接且高效。
我想知道是否有任何其他简单的方法来提取完整的 syswow64 路径。
最佳答案
从文件 nt-path 获取有效的 win32 文件路径 - 最简单的方法 - 添加 L"\\\\?\\globalroot"
(\\?\globalroot
) 前缀。这是因为 CreateFileW
从 \??\
目录中查找并且 globalroot
是符号的\??\
中的链接让 as 跳转到 nt 命名空间的根目录。
例如 - \Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll
是 nt 绝对路径。 \\?\globalroot\Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll
是 CreateFileW
的有效 win32 路径 - 此 api 转换良好已知前缀 \\?\
到 nt 前缀 \??\
和密码名称 \??\globalroot\Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll
到内核。解析此名称时 - 在处理指向命名空间根的符号链接(symbolic link) globalroot
之后 - 我们再次得到 \Device\HarddiskVolume9\Windows\SysWOW64\ntdll .dll
- 正确的 nt 路径。
因此,如果我们需要在 CreateFileW
中使用有效的 win32 路径 - 只需将此前缀附加到 nt 路径即可。然而一些 shell32 api 不接受这个表单路径。在 UI 中看起来也不好看。如果我们想要获得 DOS 驱动器号形式的路径(这是有效 win32 路径的子集)- 我们可以使用 IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
将设备名称转换为驱动器号。此 ioctl 将 MOUNTDEV_NAME
作为输入(在 mountmgr.h 中声明),输出缓冲区为 MOUNTMGR_VOLUME_PATHS
。 MOUNTDEV_NAME
中的缓冲区必须是准确的设备名称,没有文件路径。所以我们需要打破返回的 nt 路径到 2 个组件。例如在 \Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll
中:
\Device\HarddiskVolume9
- 设备路径\Windows\SysWOW64\ntdll.dll
- 文件系统路径这里的正确方法是首先打开文件并使用 FileNameInfo
调用 GetFileInformationByHandleEx
- 我们在输出中得到了文件系统路径。有了这个,我们可以使用 wcsstr
作为单独的设备路径。同样,如果我们打开文件句柄 - 我们可以在调用 GetFinalPathNameByHandleW
和 VOLUME_NAME_DOS
时使用它。这个 api 做的正是我们要做的——查询文件路径、分离设备路径并调用 IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
。 + 打开/关闭安装管理器。
但通常的 nt 文件路径从 \Device\HarddiskVolumeX
开始。这允许首先尝试快速方法 - 避免打开文件并查询它的路径。
所以首先我们需要打开挂载管理器:
#include <mountmgr.h>
HANDLE hMountManager = CreateFile(MOUNTMGR_DOS_DEVICE_NAME,
0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
然后我们可以运行下一段代码:
void dumpModules(HANDLE hMountManager, HANDLE hProcess)
{
ULONG cb = 0, cbNeeded = 16;
volatile static UCHAR guz;
PVOID stack = alloca(guz);
HMODULE *hMods, hmod;
__continue:
// cumulative allocate memory in stack, not need free it
cb = RtlPointerToOffset(hMods = (HMODULE*)alloca(cbNeeded - cb), stack);
if (EnumProcessModulesEx(hProcess, hMods, cb, &cbNeeded, LIST_MODULES_32BIT))
{
if (cb < cbNeeded)
{
goto __continue;
}
if (cbNeeded /= sizeof(HMODULE))
{
//i use hard coded size buffers, for reduce code and show main idea
#define FILE_NAME_INFO_buffer_size FIELD_OFFSET(FILE_NAME_INFO, FileName[MAX_PATH])
#define MOUNTDEV_NAME_buffer_size FIELD_OFFSET(MOUNTDEV_NAME, Name[MAX_PATH])
#define MOUNTMGR_VOLUME_PATHS_buffer_size FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz[64])
// + space for 0 at the end
PFILE_NAME_INFO pfni = (PFILE_NAME_INFO)alloca(FILE_NAME_INFO_buffer_size + sizeof(WCHAR));
PMOUNTMGR_VOLUME_PATHS pmvp = (PMOUNTMGR_VOLUME_PATHS)alloca(MOUNTMGR_VOLUME_PATHS_buffer_size);
PMOUNTDEV_NAME pmdn = (PMOUNTDEV_NAME)alloca(MOUNTDEV_NAME_buffer_size);
static WCHAR globalroot[] = L"\\\\.\\globalroot";
alloca(sizeof(globalroot));
PWSTR win32Path = pmdn->Name - RTL_NUMBER_OF(globalroot) + 1;
memcpy(win32Path, globalroot, sizeof(globalroot));
USHORT NameLength = pmdn->NameLength;
do
{
hmod = *hMods++;
if (GetMappedFileNameW(hProcess, hmod, pmdn->Name, MAX_PATH))
{
DbgPrint("%p %S\n",hmod, pmdn->Name);
PWSTR c = 0;
static const WCHAR HarddiskVolume[] = L"\\Device\\HarddiskVolume";
// fast way
if (!memcmp(pmdn->Name, HarddiskVolume, sizeof(HarddiskVolume) - sizeof(WCHAR)))
{
c = wcschr(pmdn->Name + RTL_NUMBER_OF(HarddiskVolume) - 1, '\\');
}
// else - for demo
{
pmdn->NameLength = NameLength;
HANDLE hFile = CreateFile(win32Path, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
//++ just for demo
WCHAR DosPath[MAX_PATH];
if (GetFinalPathNameByHandleW(hFile, DosPath, RTL_NUMBER_OF(DosPath), VOLUME_NAME_DOS))
{
DbgPrint("%S\n", DosPath);
}
RtlGetLastNtStatus();
//-- just for demo
BOOL fOk = GetFileInformationByHandleEx(hFile, FileNameInfo, pfni, FILE_NAME_INFO_buffer_size);
CloseHandle(hFile);
if (fOk)
{
// FileName not 0 terminated
pfni->FileName[pfni->FileNameLength/sizeof(WCHAR)] = 0;
c = wcsstr(pmdn->Name, pfni->FileName);
}
}
}
if (c)
{
pmdn->NameLength = (USHORT)RtlPointerToOffset(pmdn->Name, c);
if (DeviceIoControl(hMountManager, IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
pmdn, MOUNTDEV_NAME_buffer_size,
pmvp, MOUNTMGR_VOLUME_PATHS_buffer_size, &cb, NULL))
{
DbgPrint("%S%S\n", pmvp->MultiSz, c);
}
}
}
} while (--cbNeeded);
}
}
}
和记事本的演示输出:
0000000000170000 \Device\HarddiskVolume9\Windows\SysWOW64\notepad.exe
\\?\C:\Windows\SysWOW64\notepad.exe
C:\Windows\SysWOW64\notepad.exe
0000000077A90000 \Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll
\\?\C:\Windows\SysWOW64\ntdll.dll
0000000075460000 \Device\HarddiskVolume9\Windows\SysWOW64\kernel32.dll
\\?\C:\Windows\SysWOW64\kernel32.dll
C:\Windows\SysWOW64\kernel32.dll
0000000074A30000 \Device\HarddiskVolume9\Windows\SysWOW64\KernelBase.dll
\\?\C:\Windows\SysWOW64\KernelBase.dll
C:\Windows\SysWOW64\KernelBase.dll
00000000749B0000 \Device\HarddiskVolume9\Windows\SysWOW64\advapi32.dll
\\?\C:\Windows\SysWOW64\advapi32.dll
关于windows - GetModuleFileNameEx 从 Windows 10 上的 64 位进程获取 32 位进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46403532/
我试图从进程 ID 中获取进程名称,我使用了 GetModuleFileNameEx 并编写了这个函数。 char* ProcessName(ULONG_PTR ProcessId) { ch
我正在尝试获取所有打开进程的名称。这是我的: #include "stdafx.h" #include int WINAPI WinMain(HINSTANCE hInstance, HINS
我创建了这个函数来获取各种网络进程的路径,例如 svchost、Firefox 等。代码如下: function GetProcessPath(var pId:Integer):String; var
我正在尝试获取线程 ID 的文件路径。我希望这会起作用..但事实并非如此 NtOpenThread(@hProc, THREAD_ALL_ACCESS, @ObjAttr, @ClientID) ;
我在 64 位 Windows 10 上从 32 位进程运行以下命令: #ifndef _DEBUG WCHAR buffPath[MAX_PATH] = {0}; FARPROC p
这是我的代码: TCHAR szProcessName[MAX_PATH] = TEXT(""); GetModuleFileNameEx (hProcess, NULL, szProcessName
成功调用 CreateProcess 后,我尝试使用 GetModuleFileNameEx 获取创建的进程的路径(lpApplicationName 和 lpCommandLine 参数可以变化或为
我正在尝试导入 GetModuleFileNameEx在java应用程序中。函数的定义是: DWORD WINAPI GetModuleFileNameEx( _In_ HANDLE h
我正在使用不具备完整功能的 MinGW。例如。它没有 wchar_t 流支持。我已经设法通过编写一组小型操纵器(下面代码中的 wcusT())来解决这个问题。但我发现我再次受阻于 GetModuleF
我有这个 function NazwaProcesu(const uchwyt: Thandle): string; var pid: DWORD; hProcess: Thandle;
我正在尝试使用以下代码从 64 位应用程序中枚举 32 位进程模块名称: if (EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNee
我是一名优秀的程序员,十分优秀!