C++/C++ 코드 기록

32bit 프로세스가 System32 폴더에 접근 하는 방법

lwj789 2022. 11. 4. 16:35

32bit로 빌드한 프로세스로 System32 폴더를 접근을 하면 정상적으로 접근하지 못한다는 사실을 발견할 수 있습니다.

하지만 경로명을 로그로 찍어보면 정상적으로 찍혀 있어 더 혼란스러운 경험을 느낄 수 있습니다.

 

그 이유는 리디렉션(Redirection)을하기 때문입니다. 즉, 로그 기록은 System32폴더로 찍고 있지만 사실은 SysWow64폴더로 접근하기 때문입니다.

64bit -> System32폴더로 접근

32bit -> SysWow64폴더로 접근

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <stdio.h>
#include <Windows.h>
 
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
 
 
int main() 
{
    // case 1
    BOOL bRet = PathFileExistsA("C:\\Windows\\System32\\Test_Notepade.txt");
    printf("bRet : %d\n", bRet);
 
    // case 2
    char s[64];
    GetSystemDirectory(s, 64);
    std::string path(s);
    path += "\\Test_Notepade.txt";
    
    BOOL bRet_2 = PathFileExistsA(path.c_str());
    char str[128= { 0, };
    sprintf(str, "[path : %s] [bRet : %d]", path.c_str(), bRet_2);
    printf("%s\n", str);
    
    // case 3
    char s2[64];
    GetSystemWow64DirectoryA(s2, 64);
    std::string path2(s2);
    path2 += "\\Test_Notepade.txt";
 
    BOOL bRet_3 = PathFileExistsA(path2.c_str());
    char str2[128= { 0, };
    sprintf(str2, "[path : %s] [bRet : %d]", path2.c_str(), bRet_3);
    printf("%s\n", str2);
   
    printf("\n");
 
    return 0;
}
cs

System32폴더에 Test_Notepade.txt 파일이 존재한 상태입니다.

위 결과 사진을 보면 Test_Notepade.txt파일을 찾지 못한 결과를 확인 할 수 있습니다.

 

아래 코드 처럼 32bit 프로세스가 System32 폴더에 접근하고 싶다면 Wow64EnableWow64FsRedirection API를 사용해 리다이렉트 기능을 끄고 강제로 접근하면됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <stdio.h>
#include <Windows.h>
 
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
 
 
bool IsOnlySearchSystem32File(const char *exe_filename)
{
    typedef BOOL(WINAPI *FWOW64DISABLEWOW64FSREDIRECTION)(PVOID *);
    typedef BOOL(WINAPI *FWOW64REVERTWOW64FSREDIRECTION)(PVOID);
 
    PVOID OldValue = NULL;
    HMODULE hMod = GetModuleHandle("Kernel32.dll");
    
    if (!hMod)
        return false;
 
    FWOW64DISABLEWOW64FSREDIRECTION fWow64DisableWow64FsRedirection;
    fWow64DisableWow64FsRedirection = (FWOW64DISABLEWOW64FSREDIRECTION)GetProcAddress(hMod, "Wow64DisableWow64FsRedirection");
    fWow64DisableWow64FsRedirection(&OldValue); // off
        
    WIN32_FIND_DATA find_data;
    memset(&find_data, 0sizeof(find_data));
    HANDLE hExist = FindFirstFile(exe_filename, &find_data);
    if (hExist == INVALID_HANDLE_VALUE) // fail
    {
        printf("cannot found file\n");
        FindClose(hExist);    
        FWOW64REVERTWOW64FSREDIRECTION fWow64RevertWow64FsRedirection;
        fWow64RevertWow64FsRedirection = (FWOW64REVERTWOW64FSREDIRECTION)GetProcAddress(hMod, "Wow64RevertWow64FsRedirection");
        fWow64RevertWow64FsRedirection(OldValue); // on          
        return FALSE;
    }
 
    printf("find file!! success (%s)\n", find_data.cFileName);
    FindClose(hExist);
    FWOW64REVERTWOW64FSREDIRECTION fWow64RevertWow64FsRedirection;
    fWow64RevertWow64FsRedirection = (FWOW64REVERTWOW64FSREDIRECTION)GetProcAddress(hMod, "Wow64RevertWow64FsRedirection");
    fWow64RevertWow64FsRedirection(OldValue); // on   
    return TRUE;
}
 
int main() 
{
    // case 1
    BOOL bRet = PathFileExistsA("C:\\Windows\\System32\\Test_Notepade.txt");
    printf("bRet : %d\n", bRet);
 
    // case 2
    char s[64];
    GetSystemDirectory(s, 64);
    std::string path(s);
    path += "\\Test_Notepade.txt";
    
    BOOL bRet_2 = PathFileExistsA(path.c_str());
    char str[128= { 0, };
    sprintf(str, "[path : %s] [bRet : %d]", path.c_str(), bRet_2);
    printf("%s\n", str);
    
    // case 3
    char s2[64];
    GetSystemWow64DirectoryA(s2, 64);
    std::string path2(s2);
    path2 += "\\Test_Notepade.txt";
 
    BOOL bRet_3 = PathFileExistsA(path2.c_str());
    char str2[128= { 0, };
    sprintf(str2, "[path : %s] [bRet : %d]", path2.c_str(), bRet_3);
    printf("%s\n", str2);
   
    printf("\n");
 
    // case 5
    IsOnlySearchSystem32File("C:\\Windows\\System32\\Test_Notepade.txt");
    
    // case 6
    // 이 코드는 비스타 이후에 추가된 내용이라 xp에서는 지원 불가능
    PVOID old_value;
    Wow64DisableWow64FsRedirection(&old_value); // 끄기
 
    WIN32_FIND_DATA find_data;
    memset(&find_data, 0sizeof(find_data));
 
    HANDLE hExist = FindFirstFile("C:\\Windows\\System32\\Test_Notepade.txt"&find_data);
    if(hExist == INVALID_HANDLE_VALUE) // fail
    {        
        printf("cannot found file\n");
        Wow64RevertWow64FsRedirection(old_value); // 활성화
        FindClose(hExist);
    }
    else
        printf("find file!! success (%s)\n", find_data.cFileName);
    
    FindClose(hExist);
    Wow64RevertWow64FsRedirection(old_value); // 활성화
 
    return 0;
}
cs

 

참고

https://learn.microsoft.com/ko-kr/windows/win32/winprog64/file-system-redirector?redirectedfrom=MSDN 

 

파일 시스템 리렉터 - Win32 apps

windir \\System32 디렉터리가 64비트 Windows 64비트 애플리케이션용으로 예약되어 있습니다.

learn.microsoft.com

http://www.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=1177 

 

볼랜드포럼: 64Bit 윈도에서 32Bit 어플로 Windows/System32 내의 실행화일 구동방법.

WinExec 나 ShellExecute로 실행하려고 하면 안됩니다. 32bit 어플에서는 윈도 시스템 디렉토리에 있는 파일을 실행하려고 하면 실행할수 없다는 메시지를 받게 됩니다. 이는 OS가 64Bit이기 때문에 시스

cbuilder.borlandforum.com

 

 

 

 

 

더보기

bool   RunWow64Exe(char *exe_filename)
{
    typedef BOOL (WINAPI *FWOW64DISABLEWOW64FSREDIRECTION)(PVOID *);
    typedef BOOL (WINAPI *FWOW64REVERTWOW64FSREDIRECTION)(PVOID);
 
    PVOID OldValue = NULL;
    HMODULE hMod = GetModuleHandle("Kernel32.dll");
    if ( !hMod )
    {
           return false;
    }
 
    {
        FWOW64DISABLEWOW64FSREDIRECTION fWow64DisableWow64FsRedirection;
        fWow64DisableWow64FsRedirection = (FWOW64DISABLEWOW64FSREDIRECTION)GetProcAddress(hMod, "Wow64DisableWow64FsRedirection");
        if (fWow64DisableWow64FsRedirection && fWow64DisableWow64FsRedirection(&OldValue) )
        {
            SHELLEXECUTEINFO info;
            memset(&info, 0, sizeof(SHELLEXECUTEINFO));
            info.cbSize = sizeof(SHELLEXECUTEINFO);
            info.fMask = SEE_MASK_NOCLOSEPROCESS;
            info.hwnd = NULL;
 
            info.lpVerb = "open";
            info.lpFile = exe_filename;
            info.lpDirectory = "C:\\Windows\\system32";  // 이건 시스템 폴더를 얻어서 더 정확히 하는게 좋음.
            info.lpParameters = "";
            info.nShow = SW_SHOW;
            info.hInstApp = NULL;
 
            ShellExecuteEx(&info);
 
            {
                FWOW64REVERTWOW64FSREDIRECTION fWow64RevertWow64FsRedirection;
                fWow64RevertWow64FsRedirection = (FWOW64REVERTWOW64FSREDIRECTION)GetProcAddress(hMod, "Wow64RevertWow64FsRedirection");
 
                // Revert Redirection
                if( !fWow64RevertWow64FsRedirection(&OldValue) )
                {
                      return false;
                }
            }
            return true;
        }
    }
    return false;
}