Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Basically I have 3 executables in my Windows 7 64-bit, those are:

Loader.exe -> This is a 32-bit exe 

x86.exe -> This is a 32-bit exe

x64.exe -> This is a 64-bit exe

When Loader.exe starts it determines if the system is 32-bit or 64-bit and loads the appropriate file (either x86.exe or x64.exe), since I'm running a 64-bit operating system the x64.exe will start.

I'd like to know how Loader.exe determines if my system 32 or 64? Which is most likely through the API call Kernel32.IsWow64Process()

Now I have to make that function always return FALSE, on a global scale and not just for Loader.exe, So I was hoping something along the lines of a "global api hook" which makes the function always return FALSE.

But I do not know how to do this, the last time I ever hooked something was in Windows 98 and things have changed since then.

So do you happen to know how to Hook IsWow64Process() and thereby making the process believe it is running in a 32bit environment?

share|improve this question
    
This varies depending on the OS. Most programs just distribute a separate binary for 32/64 bit systems, with the distribution method deciding which to use (which, again, varies by OS) –  Bob Jul 4 '12 at 11:27
    
Sorry I forgot to mention it is Windows 7. And there is a "loader" executable which decides which version to run –  Æless Norm Jul 4 '12 at 11:28
    
I think for answers to make sense you need to explain why you would want to "trick programs into thinking ... 32bit" –  Martin Jul 4 '12 at 11:34
4  
can you please edit your question & move the answer to the answers section? –  Sathya Jul 6 '12 at 4:50
1  
@ÆlessNorm if you ever happen to return, leave a comment here and we can re-attribute the answer to your user account. –  nhinkle Jul 28 '12 at 18:26

2 Answers 2

After hours of wrapping my head around the Windows API (and undocumented API), as well as pointers and what not, I finally found out how to do it. It was kinda tricky, because IsWow64Process() is called by Windows on every executable even before the program reaches it's EntryPoint, if you just reflect FALSE it is going to crash.

But I noticed that the Window's calls are coming from loaded modules, and in this way I can restrict my hook to only reflect FALSE if the caller is an executable.

Here is a small guide on how it was done:

  1. Get the return address of my hook, and find out which module called my hooked function:

    wchar_t RetAdr[256];
    wsprintf(RetAdr, L"%p", _ReturnAddress());
    
    HMODULE hModule;
    GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, RetAdr , &hModule);
    
  2. Take the ModuleFileName, check if it contains ".exe" and put "Wow64Process" variable to FALSE if it is an executable:

    wchar_t mName[MAX_PATH];
    GetModuleFileName(hModule, mName, sizeof(mName));
    
    const wchar_t *shortName = L".exe";
    BOOL res = TRUE;
    
    if(wcsstr(mName,shortName) == NULL)
         res = Orig_IsWow64Process(hProcess, Wow64Process);
    else
        *Wow64Process = FALSE;
    
    
    return res;
    

But here is another problem, IsWow64Process() does only exist on Windows 64-bit operating systems, so most programs that actually check if the operating system is 64-bit do not run that function, instead they ask if the function is available and thereby determine if the system is 32-bit or 64-bit.

The way they do this is by calling GetProcAddress().

Unfortunately, GetProcAddress() is used in my source code to find function addresses, and hooking the function will of course result in undesired behaviour, so we delve a little deeper into the undocumented API and we find out that Kernel32.GetProcAddress() calls ntdll.LdrGetProcedureAddress().

After reading abit on the net, I am now sure that it is safe to hook LdrGetProcedureAddress().

In our hooked LdrGetProcedureAddress() function we check if the caller is asking for IsWow64Process and tell the caller that the function does NOT exist!

Now, we need to inject our hook into every (new) process, I decided to use the AppInit_DLLs method because I am already familiar with it and it does the job very well.

Theres alot of information about AppInit_DLLs on the web, but all of them refer to 32bit and their solution does not really work on my Windows 7 64-bit OS. To make it easier for you, here are the correct registry paths for 32-bit and 64-bit AppInit_DLLs:

32-bit: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows

64-bit: HKEY_LOCAL_MACHINE\Software\ Wow6432Node \Microsoft\Windows NT\CurrentVersion\Windows

We set LoadAppInit_DLLs to 0x1 and AppInit_DLLs to our DLL path.

Here is the final source code, it uses mhook library :

#include "stdafx.h"
#include "mhook/mhook-lib/mhook.h"

#include <intrin.h>

#ifdef __cplusplus
extern "C"
#endif
void * _ReturnAddress(void);

#pragma intrinsic(_ReturnAddress)

//////////////////////////////////////////////////////////////////////////
// Defines and typedefs
typedef NTSTATUS (NTAPI* _ldrGPA)(IN HMODULE ModuleHandle, IN PANSI_STRING FunctionName                 
OPTIONAL, IN WORD Oridinal OPTIONAL, OUT PVOID *FunctionAddress ); 

typedef BOOL (WINAPI *_IsWow64Process)(
  __in   HANDLE hProcess,
  __out  PBOOL Wow64Process
);


//////////////////////////////////////////////////////////////////////////
// Original function

PVOID HookWow, OrigWow; 

_IsWow64Process Orig_IsWow64Process = (_IsWow64Process)
GetProcAddress(GetModuleHandle(L"Kernel32"), "IsWow64Process");

_ldrGPA Orig_ldrGPA = (_ldrGPA)
GetProcAddress(GetModuleHandle(L"ntdll"), "LdrGetProcedureAddress");

//////////////////////////////////////////////////////////////////////////
// Hooked function
NTSTATUS NTAPI Hooked_ldrGPA(IN HMODULE ModuleHandle, IN PANSI_STRING FunctionName 
OPTIONAL, IN WORD Oridinal OPTIONAL, OUT PVOID *FunctionAddress)
{
//16:00 check if FunctionName equals IsWow64Process then return NULL

return Orig_ldrGPA(ModuleHandle,OPTIONAL FunctionName, OPTIONAL Oridinal,      
                        FunctionAddress); 
}



BOOL WINAPI HookIsWow64Process(
  __in   HANDLE hProcess,
  __out  PBOOL Wow64Process
)
{
HMODULE hModule;

wchar_t RetAdr[256];
wsprintf(RetAdr, L"%p", _ReturnAddress());

GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, RetAdr , &hModule);

wchar_t mName[MAX_PATH];
GetModuleFileName(hModule, mName, sizeof(mName));

const wchar_t *shortName = L".exe";
BOOL res = TRUE;

if(wcsstr(mName,shortName) == NULL)
     res = Orig_IsWow64Process(hProcess, Wow64Process);
else
    *Wow64Process = FALSE;


return res;
}



//////////////////////////////////////////////////////////////////////////
// Entry point

BOOL WINAPI DllMain(
__in HINSTANCE  hInstance,
__in DWORD      Reason,
__in LPVOID     Reserved
)
{        
switch (Reason)
{
case DLL_PROCESS_ATTACH:
    OrigWow = Orig_IsWow64Process;
    HookWow = HookIsWow64Process;
    Mhook_SetHook((PVOID*)&Orig_IsWow64Process, HookIsWow64Process);
    Mhook_SetHook((PVOID*)&Orig_ldrGPA, Hooked_ldrGPA);
    break;

case DLL_PROCESS_DETACH:
    Mhook_Unhook((PVOID*)&Orig_IsWow64Process);
    Mhook_Unhook((PVOID*)&Orig_ldrGPA);
    break;
}

return TRUE;
}
share|improve this answer

You can never force 64 bit program to run as 32 bit. Because 64 bit programs are assembled as 64 bit instructions at a time.But when you run 32 bit program on 64 bit processor the os convert 32 bit system calls to 64 bit format. The same question has been answered here check this out. Force application to run in 32-bit process on 64-bit Windows

share|improve this answer
1  
Exactly, unless emulated but that would make it extremely slow... –  Tom Wijsman Jul 4 '12 at 11:35
7  
Please flag duplicate questions as such rather than answering them. Thank you. –  ChrisF Jul 4 '12 at 11:37
    
Understand me correctly, I'm not forcing a 64-bit compiled program to run under a 32-bit environment. I am forcing a loader.exe to believe the system is 32-bit and therefore load the 32-bit version of the program instead of the 64-bit. –  Æless Norm Jul 4 '12 at 13:01
4  
@ÆlessNorm I thought you explained yourself rather well. You are NOT attempting to force x64.exe to run as 32 bit. You are trying to force Loader.exe, which is a 32 bit program to always choose to load the x86.exe 32 bit program while in a 64 bit environment... I especially don't understand why this answer was voted up, when it provided a link to the same question YOU pointed out that your question was explicitly NOT a duplicate of. –  Bon Gart Jul 4 '12 at 13:38
    
@ÆlessNorm Let me ask you one question, if you want to run 32 bit program always why dont you remove x64.exe and use x32.exe alone. –  ichathan Jul 5 '12 at 5:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.