如何判断线程是否启用了 WOW 文件系统重定向?
How to tell if WOW file system redirection is on for a thread?
说,我可以使用 Wow64DisableWow64FsRedirection API 来禁用文件系统重定向,但是有没有办法知道线程当前是否正在被重定向?换句话说,有没有像GetWow64FsRedirection
这样的API?
没有 API 报告此状态的函数。您应该记住您禁用了重定向。
另一种方法是检查 Windows System32 目录中是否存在 wow32.dll
(通常是 C:\Windows\System32
)。
在 64 位系统上,此文件应位于 SysWOW64
目录中,因此如果启用文件重定向,将会找到它。
同样,可以检查 wow64.dll
是否存在,它位于 64 位系统的 System32 目录中,如果找不到,则启用重定向。
伪代码为:
bool IsWow64FileSystemRedirectionEnabled()
{
if (!Is64BitOS()) return false;
if (FileExists(GetSystem32Directory() + "\wow32.dll")) return true;
return false;
}
其中:
Is64BitOS
可以实现如图here
FileExists
可以实现如图here
GetSystem32Directory
- 可以如图所示实现 here
抱歉,忘了 post 跟进。正如公认的答案所暗示的那样,没有 API 可以检测到这一点。太糟糕了,因为信息就存储在线程 TEB
struct 的未记录部分中。 (请参阅我在代码中的注释。)
下面的代码将检索它。
我必须先说明一下,它是通过反转上述 API 得到的。所以这是一个高度未记录的东西,可能会在 OS 的未来版本中被破坏。所以一定要在使用前做好版本保障。不过,对于 Windows 的所有已发布版本应该没问题,包括 Windows 10 build 17134:
enum YESNOERR{
ERR = -1,
NO = 0,
YES = 1,
};
struct PROC_STATS{
BOOL b32BitProcessOn64BitOS;
DWORD dwOS_Major;
DWORD dwOS_Minor;
DWORD dwOS_Build;
PROC_STATS()
{
BOOL (WINAPI *pfnIsWow64Process)(HANDLE, PBOOL);
(FARPROC&)pfnIsWow64Process = ::GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");
BOOL bWow64 = FALSE;
b32BitProcessOn64BitOS = pfnIsWow64Process && pfnIsWow64Process(::GetCurrentProcess(), &bWow64) && bWow64;
LONG (WINAPI *pfnRtlGetVersion)(RTL_OSVERSIONINFOEXW*);
(FARPROC&)pfnRtlGetVersion = ::GetProcAddress(::GetModuleHandle(_T("ntdll.dll")), "RtlGetVersion");
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(osvi);
pfnRtlGetVersion(&osvi);
dwOS_Major = osvi.dwMajorVersion;
dwOS_Minor = osvi.dwMinorVersion;
dwOS_Build = osvi.dwBuildNumber;
}
};
PROC_STATS procStats;
YESNOERR __cdecl GetWow64FsRedirection()
{
//Checks if Wow64 file system redirection is on for the current thread
YESNOERR res = ERR;
__try
{
if(procStats.b32BitProcessOn64BitOS)
{
//Really easy pre-Win10 v.10.0.10041.0
if(procStats.dwOS_Major < 10 ||
(procStats.dwOS_Major == 10 && procStats.dwOS_Build <= 10041))
{
//Win XP, 7, 8.1 & earlier builds of Win10
__asm
{
mov eax, fs:18h ; TEB
mov eax, [eax + 0F70h]
mov eax, [eax + 14C0h]
xor ecx, ecx
test eax, eax ; 0=Wow64FsRedir is on, 1=Off
setz cl
mov [res], ecx
}
}
else
{
//Latest builds of Win10 have a separate WoW TEB block
__asm
{
mov eax, fs:18h ; TEB
mov ecx, [eax + 0FDCh] ; WowTebOffset
test ecx, ecx
jns lbl_no_offset ; it must precede TEB
add eax, ecx
lbl_no_offset:
cmp eax, [eax + 18h] ; pick version of the struct
jz lbl_alt
mov eax, [eax + 14C0h]
jmp lbl_check
lbl_alt:
mov eax, [eax + 0E30h]
lbl_check:
xor ecx, ecx
test eax, eax ; 0=Wow64FsRedir is on, 1=Off
setz cl
mov [res], ecx
}
}
}
else
{
//It's off by default
res = NO;
}
}
__except(1)
{
//Oops, too far in the future -- this no longer works
res = ERR;
}
return res;
}
您可以通过以下方式对其进行测试:
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
void* pOldV;
if(::Wow64DisableWow64FsRedirection(&pOldV))
{
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
::Wow64RevertWow64FsRedirection(pOldV);
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
}
else
{
_tprintf(L"ERROR: (%d) API Failed\n", ::GetLastError());
}
说,我可以使用 Wow64DisableWow64FsRedirection API 来禁用文件系统重定向,但是有没有办法知道线程当前是否正在被重定向?换句话说,有没有像GetWow64FsRedirection
这样的API?
没有 API 报告此状态的函数。您应该记住您禁用了重定向。
另一种方法是检查 Windows System32 目录中是否存在 wow32.dll
(通常是 C:\Windows\System32
)。
在 64 位系统上,此文件应位于 SysWOW64
目录中,因此如果启用文件重定向,将会找到它。
同样,可以检查 wow64.dll
是否存在,它位于 64 位系统的 System32 目录中,如果找不到,则启用重定向。
伪代码为:
bool IsWow64FileSystemRedirectionEnabled()
{
if (!Is64BitOS()) return false;
if (FileExists(GetSystem32Directory() + "\wow32.dll")) return true;
return false;
}
其中:
Is64BitOS
可以实现如图hereFileExists
可以实现如图hereGetSystem32Directory
- 可以如图所示实现 here
抱歉,忘了 post 跟进。正如公认的答案所暗示的那样,没有 API 可以检测到这一点。太糟糕了,因为信息就存储在线程 TEB
struct 的未记录部分中。 (请参阅我在代码中的注释。)
下面的代码将检索它。
我必须先说明一下,它是通过反转上述 API 得到的。所以这是一个高度未记录的东西,可能会在 OS 的未来版本中被破坏。所以一定要在使用前做好版本保障。不过,对于 Windows 的所有已发布版本应该没问题,包括 Windows 10 build 17134:
enum YESNOERR{
ERR = -1,
NO = 0,
YES = 1,
};
struct PROC_STATS{
BOOL b32BitProcessOn64BitOS;
DWORD dwOS_Major;
DWORD dwOS_Minor;
DWORD dwOS_Build;
PROC_STATS()
{
BOOL (WINAPI *pfnIsWow64Process)(HANDLE, PBOOL);
(FARPROC&)pfnIsWow64Process = ::GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");
BOOL bWow64 = FALSE;
b32BitProcessOn64BitOS = pfnIsWow64Process && pfnIsWow64Process(::GetCurrentProcess(), &bWow64) && bWow64;
LONG (WINAPI *pfnRtlGetVersion)(RTL_OSVERSIONINFOEXW*);
(FARPROC&)pfnRtlGetVersion = ::GetProcAddress(::GetModuleHandle(_T("ntdll.dll")), "RtlGetVersion");
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(osvi);
pfnRtlGetVersion(&osvi);
dwOS_Major = osvi.dwMajorVersion;
dwOS_Minor = osvi.dwMinorVersion;
dwOS_Build = osvi.dwBuildNumber;
}
};
PROC_STATS procStats;
YESNOERR __cdecl GetWow64FsRedirection()
{
//Checks if Wow64 file system redirection is on for the current thread
YESNOERR res = ERR;
__try
{
if(procStats.b32BitProcessOn64BitOS)
{
//Really easy pre-Win10 v.10.0.10041.0
if(procStats.dwOS_Major < 10 ||
(procStats.dwOS_Major == 10 && procStats.dwOS_Build <= 10041))
{
//Win XP, 7, 8.1 & earlier builds of Win10
__asm
{
mov eax, fs:18h ; TEB
mov eax, [eax + 0F70h]
mov eax, [eax + 14C0h]
xor ecx, ecx
test eax, eax ; 0=Wow64FsRedir is on, 1=Off
setz cl
mov [res], ecx
}
}
else
{
//Latest builds of Win10 have a separate WoW TEB block
__asm
{
mov eax, fs:18h ; TEB
mov ecx, [eax + 0FDCh] ; WowTebOffset
test ecx, ecx
jns lbl_no_offset ; it must precede TEB
add eax, ecx
lbl_no_offset:
cmp eax, [eax + 18h] ; pick version of the struct
jz lbl_alt
mov eax, [eax + 14C0h]
jmp lbl_check
lbl_alt:
mov eax, [eax + 0E30h]
lbl_check:
xor ecx, ecx
test eax, eax ; 0=Wow64FsRedir is on, 1=Off
setz cl
mov [res], ecx
}
}
}
else
{
//It's off by default
res = NO;
}
}
__except(1)
{
//Oops, too far in the future -- this no longer works
res = ERR;
}
return res;
}
您可以通过以下方式对其进行测试:
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
void* pOldV;
if(::Wow64DisableWow64FsRedirection(&pOldV))
{
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
::Wow64RevertWow64FsRedirection(pOldV);
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
}
else
{
_tprintf(L"ERROR: (%d) API Failed\n", ::GetLastError());
}