Skip to content

Commit

Permalink
fix can not use createwith api to start all kinds of .net exe, like R…
Browse files Browse the repository at this point in the history
…eflector.exe, it can be install by https://download.red-gate.com/ReflectorInstaller.exe
  • Loading branch information
sonyps5201314 committed Sep 4, 2020
1 parent 62b7fbf commit 8e5ef0e
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 63 deletions.
155 changes: 93 additions & 62 deletions src/creatwth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,8 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
//
inh64.Signature = inh32.Signature;
inh64.FileHeader = inh32.FileHeader;
inh64.FileHeader.Machine = machine;
inh64.FileHeader.Machine = machine;//If inh32.FileHeader.Machine is assigned here, the PE loader of win7 and below will not be able to pass,
//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,
inh64.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64);

inh64.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
Expand Down Expand Up @@ -476,6 +477,10 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
if (!RecordExeRestore(hProcess, hModule, der)) {
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//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
der.inh.FileHeader.Machine = inh32.FileHeader.Machine;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Remove the import table.
if (der.pclr != NULL && (der.clr.Flags & COMIMAGE_FLAGS_ILONLY)) {
Expand All @@ -499,37 +504,59 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
}
#endif // DETOURS_64BIT

typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);

static BOOL IsWow64ProcessHelper(HANDLE hProcess,
PBOOL Wow64Process)
namespace Detour
{
#ifdef _X86_
if (Wow64Process == NULL) {
return FALSE;
}

// IsWow64Process is not available on all supported versions of Windows.
//
HMODULE hKernel32 = LoadLibraryW(L"KERNEL32.DLL");
if (hKernel32 == NULL) {
DETOUR_TRACE(("LoadLibraryW failed: %d\n", GetLastError()));
return FALSE;
}

LPFN_ISWOW64PROCESS pfnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
hKernel32, "IsWow64Process");

if (pfnIsWow64Process == NULL) {
DETOUR_TRACE(("GetProcAddress failed: %d\n", GetLastError()));
return FALSE;
}
return pfnIsWow64Process(hProcess, Wow64Process);
#else
return IsWow64Process(hProcess, Wow64Process);
#ifndef PROCESSOR_ARCHITECTURE_ARM64
#define PROCESSOR_ARCHITECTURE_ARM64 12
#endif
BOOL Is64BitOS()
{
BOOL bRet = FALSE;
HMODULE hModule = GetModuleHandle(TEXT("kernel32.dll"));
if (!hModule)
{
return bRet;
}
VOID(WINAPI * _GetNativeSystemInfo)(OUT LPSYSTEM_INFO lpSystemInfo) = (void(__stdcall *)(LPSYSTEM_INFO))GetProcAddress(hModule, "GetNativeSystemInfo");
if (!_GetNativeSystemInfo)
{
return bRet;
}

SYSTEM_INFO si;
_GetNativeSystemInfo(&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64 ||
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA64)
{
bRet = TRUE;
}
return bRet;
};
//The process handle hProcess needs to have PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access rights
BOOL Is64BitProcess(HANDLE hProcess)
{
BOOL bRet = FALSE;
if (hProcess)
{
if (Is64BitOS())
{
HMODULE hModule = GetModuleHandle(TEXT("kernel32.dll"));
if (hModule)
{
BOOL(WINAPI * _IsWow64Process)(IN HANDLE hProcess,
OUT PBOOL Wow64Process)
= (BOOL(__stdcall*)(HANDLE, PBOOL))GetProcAddress(hModule, "IsWow64Process");
BOOL b32BitProcessRunAt64BitOS;
if (_IsWow64Process && _IsWow64Process(hProcess, &b32BitProcessRunAt64BitOS) && b32BitProcessRunAt64BitOS == FALSE)
{
bRet = TRUE;
}
}
}
}
return bRet;
}
}

//////////////////////////////////////////////////////////////////////////////
//
BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
Expand All @@ -538,8 +565,9 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
{
// Find the next memory region that contains a mapped PE image.
//
BOOL bHas64BitDll = FALSE;
BOOL bHas32BitExe = FALSE;
BOOL bIs32BitProcess;
BOOL bIs64BitOS = FALSE;
HMODULE hModule = NULL;
HMODULE hLast = NULL;

Expand All @@ -557,46 +585,47 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,

if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
hModule = hLast;
if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC
&& inh.FileHeader.Machine != 0) {

bHas32BitExe = TRUE;
}
DETOUR_TRACE(("%p Found EXE\n", hLast));
}
else {
if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC
&& inh.FileHeader.Machine != 0) {

bHas64BitDll = TRUE;
}
}
}

if (hModule == NULL) {
SetLastError(ERROR_INVALID_OPERATION);
return FALSE;
}

// Determine if the target process is 32bit or 64bit. This is a two-stop process:
//
// 1. First, determine if we're running on a 64bit operating system.
// - If we're running 64bit code (i.e. _WIN64 is defined), this is trivially true.
// - If we're running 32bit code (i.e. _WIN64 is not defined), test if
// we're running under Wow64. If so, it implies that the operating system
// is 64bit.
//
#ifdef _WIN64
bIs64BitOS = TRUE;
#else
if (!IsWow64ProcessHelper(GetCurrentProcess(), &bIs64BitOS)) {
return FALSE;
}
#endif

// 2. With the operating system bitness known, we can now consider the target process:
// - If we're running on a 64bit OS, the target process is 32bit in case
// it is running under Wow64. Otherwise, it's 64bit, running natively
// (without Wow64).
// - If we're running on a 32bit OS, the target process must be 32bit, too.
//
if (bIs64BitOS) {
if (!IsWow64ProcessHelper(hProcess, &bIs32BitProcess)) {
return FALSE;
}
} else {
bIs32BitProcess = TRUE;
}

DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bHas32BitExe, bIs32BitProcess));
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Commented out code
//The following code cannot correctly determine whether the started process is 32-bit
//if (!bHas32BitExe) {
// bIs32BitProcess = FALSE;
//}
//else if (!bHas64BitDll) {
// bIs32BitProcess = TRUE;
//}
//else {
// if (!IsWow64Process(hProcess, &bIs32BitProcess)) {
// return FALSE;
// }
//}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Added code
bIs32BitProcess = !Detour::Is64BitProcess(hProcess);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

return DetourUpdateProcessWithDllEx(hProcess,
hModule,
Expand Down Expand Up @@ -630,7 +659,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
bIs32BitExe = TRUE;
}

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

if (hModule == NULL) {
SetLastError(ERROR_INVALID_OPERATION);
Expand Down Expand Up @@ -714,6 +743,8 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
DETOUR_CLR_HEADER clr;
CopyMemory(&clr, &der.clr, sizeof(clr));
clr.Flags &= ~COMIMAGE_FLAGS_ILONLY; // Clear the IL_ONLY flag.
//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
//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

DWORD dwProtect;
if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &dwProtect)) {
Expand Down
4 changes: 3 additions & 1 deletion src/modules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,7 @@ BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
if (pder->pclr != NULL && pder->clr.Flags != ((PDETOUR_CLR_HEADER)pder->pclr)->Flags) {
// If we had to promote the 32/64-bit agnostic IL to 64-bit, we can't restore
// that.
//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)
fUpdated32To64 = TRUE;
}

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

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

0 comments on commit 8e5ef0e

Please sign in to comment.