如何判断线程是否启用了WOW文件系统重定向?

时间:2015-05-07 19:36:25

标签: c++ windows winapi ntfs kernel32

说,我可以使用Wow64DisableWow64FsRedirection API来禁用文件系统重定向,但是有没有办法知道线程当前是否被重定向?换句话说,是否有像event = Event.new(name: 'Party').audiences.build(name: 'Party People') event.save # saves both event and audiences

这样的API

3 个答案:

答案 0 :(得分:2)

没有API函数报告此状态。您应该记住您禁用了重定向。

答案 1 :(得分:0)

另一种方法是检查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
  • 所示实施

答案 2 :(得分:0)

很抱歉,忘记发布后续消息。正如公认的答案所暗示的那样,没有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());
}