Skip to content

Commit 81e6a5f

Browse files
authored
Improved Detours logic for detection of 32bit processes (#104)
This patch improves the logic for detecting whether the process to be patched is a 32bit or a 64bit process. The old logic would first enumerate the modules in the process and see if: 1. There is a 32bit executable module 2. There is a 64bit DLL module In case 1.) is true and 2.) is false, i.e. a 32bit executable but no 64bit DLL, the process was deemed to be a 32bit process. This seems plausible, but I encountered a case in which it is not true: I launched an IL-only .NET application (a Windows Forms GUI application) in Windows 10. Right after the CreateProcess call, there were just two modules in the process - A 32bit executable - A 32bit ntdll.dll library I.e. the .NET runtime was not loaded yet. Hence, because there *is* a 32bit executable but there is *not* a 64bit DLL, bIs32BitProcess was set to TRUE. However, when resuming the process and inspecting with Process Explorer, it appears that the process executed in 64bit mode! I suppose it would be possible to replicate the behavior of the Windows loader and be a bit smarter about looking for 32bit executables: instead of just looking at the 'machine' flag, also look for a potential IMAGE_COR20_HEADER (which basically acts as the PE header for .NET executables) and see if that requires 32bit. However, I think there is an easier way to check if the process is 32bit or not. The new logic performs two steps: 1. Detect whether the operating system is 64bit. If the code is compiled as 64bit, then the OS is trivially 64bit. If the code does not have _WIN64 defined, i.e. it is 32bit, but it is running under WOW64, then the OS is 64bit, too. 2. Detect if the process to be patched is 32bit. If the OS is *not* 64bit, the process can't possibly be 64bit. So it must be 32bit. If the OS *is* 64bit, we can identify 32bit processes by calling IsWow64Process() again.
1 parent 5f674df commit 81e6a5f

File tree

1 file changed

+25
-20
lines changed

1 file changed

+25
-20
lines changed

src/creatwth.cpp

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -538,9 +538,8 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
538538
{
539539
// Find the next memory region that contains a mapped PE image.
540540
//
541-
BOOL bHas64BitDll = FALSE;
542-
BOOL bHas32BitExe = FALSE;
543541
BOOL bIs32BitProcess;
542+
BOOL bIs64BitOS = FALSE;
544543
HMODULE hModule = NULL;
545544
HMODULE hLast = NULL;
546545

@@ -558,37 +557,43 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
558557

559558
if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
560559
hModule = hLast;
561-
if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC
562-
&& inh.FileHeader.Machine != 0) {
563-
564-
bHas32BitExe = TRUE;
565-
}
566560
DETOUR_TRACE(("%p Found EXE\n", hLast));
567561
}
568-
else {
569-
if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC
570-
&& inh.FileHeader.Machine != 0) {
571-
572-
bHas64BitDll = TRUE;
573-
}
574-
}
575562
}
576563

577564
if (hModule == NULL) {
578565
SetLastError(ERROR_INVALID_OPERATION);
579566
return FALSE;
580567
}
581568

582-
if (!bHas32BitExe) {
583-
bIs32BitProcess = FALSE;
584-
}
585-
else if (!bHas64BitDll) {
586-
bIs32BitProcess = TRUE;
569+
// Determine if the target process is 32bit or 64bit. This is a two-stop process:
570+
//
571+
// 1. First, determine if we're running on a 64bit operating system.
572+
// - If we're running 64bit code (i.e. _WIN64 is defined), this is trivially true.
573+
// - If we're running 32bit code (i.e. _WIN64 is not defined), test if
574+
// we're running under Wow64. If so, it implies that the operating system
575+
// is 64bit.
576+
//
577+
#ifdef _WIN64
578+
bIs64BitOS = TRUE;
579+
#else
580+
if (!IsWow64ProcessHelper(GetCurrentProcess(), &bIs64BitOS)) {
581+
return FALSE;
587582
}
588-
else {
583+
#endif
584+
585+
// 2. With the operating system bitness known, we can now consider the target process:
586+
// - If we're running on a 64bit OS, the target process is 32bit in case
587+
// it is running under Wow64. Otherwise, it's 64bit, running natively
588+
// (without Wow64).
589+
// - If we're running on a 32bit OS, the target process must be 32bit, too.
590+
//
591+
if (bIs64BitOS) {
589592
if (!IsWow64ProcessHelper(hProcess, &bIs32BitProcess)) {
590593
return FALSE;
591594
}
595+
} else {
596+
bIs32BitProcess = TRUE;
592597
}
593598

594599
DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bHas32BitExe, bIs32BitProcess));

0 commit comments

Comments
 (0)