32bit 프로세스가 System32 폴더에 접근 하는 방법
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 |
위 결과 사진을 보면 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, 0, sizeof(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, 0, sizeof(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;
}