C 如何为GetModuleFileNameEx禁用WOW64文件系统重定向?
我正在64位Windows 10上通过32位进程运行以下操作:C 如何为GetModuleFileNameEx禁用WOW64文件系统重定向?,c,winapi,wow64,C,Winapi,Wow64,我正在64位Windows 10上通过32位进程运行以下操作: #ifndef _DEBUG WCHAR buffPath[MAX_PATH] = {0}; FARPROC pfn = (FARPROC)::GetModuleHandleEx; HMODULE hMod = NULL; ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX
#ifndef _DEBUG
WCHAR buffPath[MAX_PATH] = {0};
FARPROC pfn = (FARPROC)::GetModuleHandleEx;
HMODULE hMod = NULL;
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)pfn, &hMod);
PVOID pOldVal = NULL;
if(::Wow64DisableWow64FsRedirection(&pOldVal))
{
::GetModuleFileNameEx(::GetCurrentProcess(), hMod, buffPath, _countof(buffPath));
::Wow64RevertWow64FsRedirection(pOldVal);
wprintf(L"Path=%s\n", buffPath);
}
#else
#error run_in_release_mode
#endif
我希望收到的路径是c:\windows\syswow64\KERNEL32.DLL,但它给了我:
Path=C:\Windows\System32\KERNEL32.DLL
知道为什么吗?当我们通过LoadLibrary[Ex]或LdrLoadDll加载dll时-首先是一些预处理传输的dll名称,比如将api-*转换为实际的dll名称或基于清单重定向dll名称-众所周知的示例comctl32.dll,然后使用此可能修改的dll名称将文件加载为dll。但是wow fs重定向-在这个阶段没有预处理。如果dll成功加载-系统分配结构,并在预处理dll名称后按原样保存传输
GetModuleFileNameEx只需遍历双链接列表和搜索条目,其中DllBase==hModule-如果找到-如果缓冲区足够大,则将FullDllName复制到lpFilename。因此,它只返回加载dll期间使用的dll路径。Wow64DisableWow64FsRedirection对该调用没有任何影响
如果我们想获得dll的真正规范完整路径,需要使用GetMappedFileNameW或with
所以,如果我们希望MAX_路径足够的话,代码就可以了
WCHAR path[MAX_PATH];
GetMappedFileNameW(NtCurrentProcess(), hmod, path, RTL_NUMBER_OF(path));
或者,如果使用ntapi并正确处理任何路径长度:
NTSTATUS GetDllName(PVOID AddressInDll, PUNICODE_STRING NtImageName)
{
NTSTATUS status;
union {
PVOID buf;
PUNICODE_STRING ImageName;
};
static volatile UCHAR guz;
PVOID stack = alloca(guz);
SIZE_T cb = 0, rcb = 0x200;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = ZwQueryVirtualMemory(NtCurrentProcess(), AddressInDll,
MemoryMappedFilenameInformation, buf, cb, &rcb)))
{
return RtlDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
ImageName, NtImageName);
}
} while (status == STATUS_BUFFER_OVERFLOW);
return status;
}
UNICODE_STRING NtImageName;
if (0 <= GetDllName(hmod, &NtImageName))
{
RtlFreeUnicodeString(&NtImageName);
}
此外,当我们通过LoadLibrary[Ex]加载dll时,我们还可以将代码更改为MOUNTMGR_IS_VOLUME_NAME&SymbolicLinkName,以获取卷持久名称形式,而不是驱动程序字母形式或LdrLoadDll-首先是一些预处理传输的dll名称,如将api-*转换为实际的dll名称或根据清单重定向dll名称-众所周知的示例comctl32.dll,然后使用此可能修改的dll名称作为dll加载文件。但是wow fs重定向-在这个阶段没有预处理。如果dll成功加载-系统分配结构,并在预处理dll名称后按原样保存传输
GetModuleFileNameEx只需遍历双链接列表和搜索条目,其中DllBase==hModule-如果找到-如果缓冲区足够大,则将FullDllName复制到lpFilename。因此,它只返回加载dll期间使用的dll路径。Wow64DisableWow64FsRedirection对该调用没有任何影响
如果我们想获得dll的真正规范完整路径,需要使用GetMappedFileNameW或with
所以,如果我们希望MAX_路径足够的话,代码就可以了
WCHAR path[MAX_PATH];
GetMappedFileNameW(NtCurrentProcess(), hmod, path, RTL_NUMBER_OF(path));
或者,如果使用ntapi并正确处理任何路径长度:
NTSTATUS GetDllName(PVOID AddressInDll, PUNICODE_STRING NtImageName)
{
NTSTATUS status;
union {
PVOID buf;
PUNICODE_STRING ImageName;
};
static volatile UCHAR guz;
PVOID stack = alloca(guz);
SIZE_T cb = 0, rcb = 0x200;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = ZwQueryVirtualMemory(NtCurrentProcess(), AddressInDll,
MemoryMappedFilenameInformation, buf, cb, &rcb)))
{
return RtlDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
ImageName, NtImageName);
}
} while (status == STATUS_BUFFER_OVERFLOW);
return status;
}
UNICODE_STRING NtImageName;
if (0 <= GetDllName(hmod, &NtImageName))
{
RtlFreeUnicodeString(&NtImageName);
}
此外,我们还可以将代码更改为MOUNTMGR_IS_VOLUME_NAME&SymbolicLinkName for get VOLUME persistent NAME form而不是driver letter formGetModuleHandleEx只返回保存的模块名,用于加载dll。Wow64DisableWow64FsRedirection对此没有也不能有任何影响。您可以使用GetMappedFileName来获取真实的文件系统path@RbMm:它保存在哪里,PEB结构?是的,GetMappedFileName返回了正确的路径。它是设备路径形式。您知道有什么简单的方法可以将其转换为资源管理器使用的格式,即C:\而不是\Device\HardiskVolumeN?顺便说一句,GetMappedFileName不需要Wow64DisableWow64FsRedirectionit保存在GetModuleFileNameEx从这里返回的_LDR_DATA_TABLE_条目中。甚至在文件名/路径中保留大小写。您可以通过自加载一些dll并在name-GetModuleFileNameEx中使用不寻常的大小写组合来轻松测试这一点,并将其返回给您。当GetMappedFileName-返回真实的文件系统时path@RbMm:\u LDR\u DATA\u TABLE\u内核空间中的条目,对吗?当然GetMappedFileName也不依赖于Wow64DisableWow64FsRedirection这是ZwQueryVirtualMemory上的shell,MemoryMappedFileName信息..GetModuleHandlex只返回保存的模块名,用于加载dll。Wow64DisableWow64FsRedirection对此没有也不能有任何影响。您可以使用GetMappedFileName来获取真实的文件系统path@RbMm:它保存在哪里,PEB结构?是的,GetMappedFileName返回了正确的路径。它是设备路径形式。您知道有什么简单的方法可以将其转换为资源管理器使用的格式,即C:\而不是\Device\HardiskVolumeN?顺便说一句,GetMappedFileName不需要Wow64DisableWow64FsRedirectionit保存在GetModuleFileNameEx从这里返回的_LDR_DATA_TABLE_条目中。甚至在文件名/路径中保留大小写。您可以通过自加载一些dll并在name-GetModuleFileNameEx中使用不寻常的大小写组合来轻松测试这一点,并将其返回给您。当GetMappedFileName-返回真实的文件系统时path@RbMm:_LDR_DATA_TABLE_内核空间中的条目,对吗?当然GetMappedFileName也不依赖于WOW64禁用WOW64FSRedirection这是ZwQueryVirtualMemory上的shell,MemoryMappedFileName信息。。