Как заставить программы думать, что они работают под 32-битной версией?

16294
Æless Norm

В основном у меня есть 3 исполняемых файла в моей Windows 7 64-битных, это:

Loader.exe -> Это 32-битный exe 

x86.exe -> Это 32-битный exe

x64.exe -> Это 64-битный exe

Когда запускается Loader.exe, он определяет, является ли система 32-разрядной или 64-разрядной, и загружает соответствующий файл ( x86.exe или x64.exe ), так как я использую 64-разрядную операционную систему, x64.exe будет Начните.

Я хотел бы знать, как Loader.exe определяет, если моя система 32 или 64? Что, скорее всего, через вызов API Kernel32.IsWow64Process ()

Теперь я должен сделать так, чтобы эта функция всегда возвращала FALSE в глобальном масштабе, а не только для Loader.exe, поэтому я надеялся на что-то вроде «глобального API-хука», который заставляет функцию всегда возвращать FALSE.

Но я не знаю, как это сделать, последний раз, когда я что-то подключал, был в Windows 98, и с тех пор все изменилось.

Так вы случайно не знаете, как подключить IsWow64Process () и тем самым заставить процесс поверить, что он работает в 32-битной среде?

7
Это зависит от ОС. Большинство программ просто распространяют отдельный двоичный файл для 32/64-битных систем, при этом метод распространения решает, какой из них использовать (что опять-таки зависит от ОС) Bob 11 лет назад 0
Sorry I forgot to mention it is Windows 7. And there is a "loader" executable which decides which version to run Æless Norm 11 лет назад 0
Я думаю, что для того, чтобы ответы имели смысл, вам нужно объяснить, почему вы хотите «обмануть программы в мышление ... 32-битные» Martin 11 лет назад 0
can you please edit your question & move the answer to the answers section? Sathya 11 лет назад 4
*> I'd like to know how [to make] Kernel32.IsWow64Process()… always return FALSE, on a global scale.*     That is impossible; the system would crash horribly (if it can even boot up) and may possibly even explode or infect you with Ebola. Synetech 11 лет назад 0
@ ÆlessNorm, если вы когда-нибудь вернетесь, оставьте комментарий здесь, и мы сможем переназначить ответ вашей учетной записи пользователя. nhinkle 11 лет назад 1

2 ответа на вопрос

7
Æless Norm

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; } 
0
arundevma

Вы никогда не сможете принудительно запустить 64-битную программу как 32-битную. Потому что 64-битные программы собираются как 64-битные инструкции за раз. Но когда вы запускаете 32-битную программу на 64-битном процессоре, ОС конвертирует 32-битные системные вызовы в 64-битный формат. Здесь ответили на тот же вопрос. Принудительно запустить приложение в 32-битном процессе в 64-битной Windows

Точно, если не подражать, но это сделало бы это очень медленно ... Tom Wijsman 11 лет назад 1
Пожалуйста, помечайте дубликаты как таковые, а не отвечайте на них. Спасибо. ChrisF 11 лет назад 7
Поймите меня правильно, я не заставляю 64-битную скомпилированную программу работать в 32-битной среде. Я заставляю loader.exe полагать, что система 32-битная, и поэтому загружаю 32-битную версию программы вместо 64-битной. Æless Norm 11 лет назад 1
@Æ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 11 лет назад 4
@ ÆlessNorm Позвольте мне задать вам один вопрос, если вы хотите всегда запускать 32-битную программу, почему бы вам не удалить x64.exe и использовать только x32.exe. arundevma 11 лет назад 0
@gladiator2345 Think of it as if Loader.exe creates those files at run-time, theres no way for me to just double-click x32.exe and start it. Either way, I found out how to force 32-bit after hours of wrapping my head around pointers, but I wont bother answering my own question as this topic is now closed for no reason. Æless Norm 11 лет назад 0
@less Norm You should have asked it in stackoverflow rather than in superuser as it is related to programming. That is why your question was misinterpreted by most of us. If you had asked in stack overflow it would have got good responses. arundevma 11 лет назад 0