@@ -408,7 +408,8 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
408408 //
409409 inh64.Signature = inh32.Signature ;
410410 inh64.FileHeader = inh32.FileHeader ;
411- inh64.FileHeader .Machine = machine;
411+ inh64.FileHeader .Machine = machine;// If inh32.FileHeader.Machine is assigned here, the PE loader of win7 and below will not be able to pass,
412+ // It will report an error STATUS_INVALID_IMAGE_FORMAT, so you need to save the value of Machine in the original PE header in dep, that is, the value of inh32.FileHeader.Machine,
412413 inh64.FileHeader .SizeOfOptionalHeader = sizeof (IMAGE_OPTIONAL_HEADER64);
413414
414415 inh64.OptionalHeader .Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
@@ -476,6 +477,10 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
476477 if (!RecordExeRestore (hProcess, hModule, der)) {
477478 return FALSE ;
478479 }
480+ // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
481+ // After the above RecordExeRestore call, the 64-bit PE header is saved in dep, so it is necessary to restore the Machine value of the PE header saved in der, so that the PE parser of .NET can load the CLR file normally
482+ der.inh .FileHeader .Machine = inh32.FileHeader .Machine ;
483+ // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
479484
480485 // Remove the import table.
481486 if (der.pclr != NULL && (der.clr .Flags & COMIMAGE_FLAGS_ILONLY)) {
@@ -499,37 +504,59 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
499504}
500505#endif // DETOURS_64BIT
501506
502- typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
503-
504- static BOOL IsWow64ProcessHelper (HANDLE hProcess,
505- PBOOL Wow64Process)
507+ namespace Detour
506508{
507- #ifdef _X86_
508- if (Wow64Process == NULL ) {
509- return FALSE ;
510- }
511-
512- // IsWow64Process is not available on all supported versions of Windows.
513- //
514- HMODULE hKernel32 = LoadLibraryW (L" KERNEL32.DLL" );
515- if (hKernel32 == NULL ) {
516- DETOUR_TRACE ((" LoadLibraryW failed: %d\n " , GetLastError ()));
517- return FALSE ;
518- }
519-
520- LPFN_ISWOW64PROCESS pfnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress (
521- hKernel32, " IsWow64Process" );
522-
523- if (pfnIsWow64Process == NULL ) {
524- DETOUR_TRACE ((" GetProcAddress failed: %d\n " , GetLastError ()));
525- return FALSE ;
526- }
527- return pfnIsWow64Process (hProcess, Wow64Process);
528- #else
529- return IsWow64Process (hProcess, Wow64Process);
509+ #ifndef PROCESSOR_ARCHITECTURE_ARM64
510+ #define PROCESSOR_ARCHITECTURE_ARM64 12
530511#endif
512+ BOOL Is64BitOS ()
513+ {
514+ BOOL bRet = FALSE ;
515+ HMODULE hModule = GetModuleHandle (TEXT (" kernel32.dll" ));
516+ if (!hModule)
517+ {
518+ return bRet;
519+ }
520+ VOID (WINAPI * _GetNativeSystemInfo)(OUT LPSYSTEM_INFO lpSystemInfo) = (void (__stdcall *)(LPSYSTEM_INFO))GetProcAddress (hModule, " GetNativeSystemInfo" );
521+ if (!_GetNativeSystemInfo)
522+ {
523+ return bRet;
524+ }
525+
526+ SYSTEM_INFO si;
527+ _GetNativeSystemInfo (&si);
528+ if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64 ||
529+ si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA64)
530+ {
531+ bRet = TRUE ;
532+ }
533+ return bRet;
534+ };
535+ // The process handle hProcess needs to have PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access rights
536+ BOOL Is64BitProcess (HANDLE hProcess)
537+ {
538+ BOOL bRet = FALSE ;
539+ if (hProcess)
540+ {
541+ if (Is64BitOS ())
542+ {
543+ HMODULE hModule = GetModuleHandle (TEXT (" kernel32.dll" ));
544+ if (hModule)
545+ {
546+ BOOL (WINAPI * _IsWow64Process)(IN HANDLE hProcess,
547+ OUT PBOOL Wow64Process)
548+ = (BOOL (__stdcall*)(HANDLE, PBOOL))GetProcAddress (hModule, " IsWow64Process" );
549+ BOOL b32BitProcessRunAt64BitOS;
550+ if (_IsWow64Process && _IsWow64Process (hProcess, &b32BitProcessRunAt64BitOS) && b32BitProcessRunAt64BitOS == FALSE )
551+ {
552+ bRet = TRUE ;
553+ }
554+ }
555+ }
556+ }
557+ return bRet;
558+ }
531559}
532-
533560// ////////////////////////////////////////////////////////////////////////////
534561//
535562BOOL WINAPI DetourUpdateProcessWithDll (_In_ HANDLE hProcess,
@@ -538,8 +565,9 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
538565{
539566 // Find the next memory region that contains a mapped PE image.
540567 //
568+ BOOL bHas64BitDll = FALSE ;
569+ BOOL bHas32BitExe = FALSE ;
541570 BOOL bIs32BitProcess;
542- BOOL bIs64BitOS = FALSE ;
543571 HMODULE hModule = NULL ;
544572 HMODULE hLast = NULL ;
545573
@@ -557,46 +585,30 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
557585
558586 if ((inh.FileHeader .Characteristics & IMAGE_FILE_DLL) == 0 ) {
559587 hModule = hLast;
588+ if (inh.OptionalHeader .Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC
589+ && inh.FileHeader .Machine != 0 ) {
590+
591+ bHas32BitExe = TRUE ;
592+ }
560593 DETOUR_TRACE ((" %p Found EXE\n " , hLast));
561594 }
595+ else {
596+ if (inh.OptionalHeader .Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC
597+ && inh.FileHeader .Machine != 0 ) {
598+
599+ bHas64BitDll = TRUE ;
600+ }
601+ }
562602 }
563603
564604 if (hModule == NULL ) {
565605 SetLastError (ERROR_INVALID_OPERATION);
566606 return FALSE ;
567607 }
568608
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 ;
582- }
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) {
592- if (!IsWow64ProcessHelper (hProcess, &bIs32BitProcess)) {
593- return FALSE ;
594- }
595- } else {
596- bIs32BitProcess = TRUE ;
597- }
609+ bIs32BitProcess = !Detour::Is64BitProcess (hProcess);
598610
599- DETOUR_TRACE ((" 32BitExe=%d 32BitProcess\n " , bHas32BitExe, bIs32BitProcess));
611+ DETOUR_TRACE ((" 32BitExe=%d 32BitProcess=%d \n " , bHas32BitExe, bIs32BitProcess));
600612
601613 return DetourUpdateProcessWithDllEx (hProcess,
602614 hModule,
@@ -630,7 +642,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
630642 bIs32BitExe = TRUE ;
631643 }
632644
633- DETOUR_TRACE ((" 32BitExe=%d 32BitProcess\n " , bIs32BitExe, bIs32BitProcess));
645+ DETOUR_TRACE ((" 32BitExe=%d 32BitProcess=%d \n " , bIs32BitExe, bIs32BitProcess));
634646
635647 if (hModule == NULL ) {
636648 SetLastError (ERROR_INVALID_OPERATION);
@@ -714,6 +726,8 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
714726 DETOUR_CLR_HEADER clr;
715727 CopyMemory (&clr, &der.clr , sizeof (clr));
716728 clr.Flags &= ~COMIMAGE_FLAGS_ILONLY; // Clear the IL_ONLY flag.
729+ // The above sentence clears the IL_ONLY flag, so we need to restore the IL_ONLY flag after the IAT is restored after starting the process completion
730+ // Not clearing the IL_ONLY flag will result in the inability to start the process, because we replaced the original IAT with the new IAT containing the name of our DLL
717731
718732 DWORD dwProtect;
719733 if (!DetourVirtualProtectSameExecuteEx (hProcess, der.pclr , sizeof (clr), PAGE_READWRITE, &dwProtect)) {
0 commit comments