Skip to content

Commit ec9696d

Browse files
committed
fix can not use createwith api to start all kinds of .net exe, like Reflector.exe, it can be install by https://download.red-gate.com/ReflectorInstaller.exe
1 parent 81e6a5f commit ec9696d

File tree

2 files changed

+78
-62
lines changed

2 files changed

+78
-62
lines changed

src/creatwth.cpp

Lines changed: 75 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -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
//
535562
BOOL 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)) {

src/modules.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
858858
if (pder->pclr != NULL && pder->clr.Flags != ((PDETOUR_CLR_HEADER)pder->pclr)->Flags) {
859859
// If we had to promote the 32/64-bit agnostic IL to 64-bit, we can't restore
860860
// that.
861+
//Now we have supported the recovery of CLR header data in the above situation (IL code of unknown target bit is compiled into native code of 64-bit process by instant compilation)
861862
fUpdated32To64 = TRUE;
862863
}
863864

@@ -869,7 +870,8 @@ BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
869870
CopyMemory(pder->pidh, &pder->idh, pder->cbidh);
870871
CopyMemory(pder->pinh, &pder->inh, pder->cbinh);
871872

872-
if (pder->pclr != NULL && !fUpdated32To64) {
873+
//It can be restored now when fUpdated32To64 is TRUE. At present, only the clr.Flags field is restored.
874+
if (pder->pclr != NULL /*&& !fUpdated32To64*/) {
873875
if (DetourVirtualProtectSameExecute(pder->pclr, pder->cbclr,
874876
PAGE_EXECUTE_READWRITE, &dwPermClr)) {
875877
CopyMemory(pder->pclr, &pder->clr, pder->cbclr);

0 commit comments

Comments
 (0)