基本的に、Windows 764ビットには3つの実行可能ファイルがあります。それらは次のとおりです。
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ビット環境で実行されていると信じ込ませますか?
何時間もWindowsAPI(および文書化されていないAPI)とポインターなどに頭を悩ませた後、私はついにそれを行う方法を見つけました。 IsWow64Process()は、プログラムがEntryPointに到達する前であっても、すべての実行可能ファイルでWindowsによって呼び出されるため、ちょっと注意が必要でした。FALSEを反映するだけで、クラッシュする。
しかし、Windowの呼び出しがロードされたモジュールからのものであることに気付きました。このようにして、呼び出し元が実行可能ファイルである場合にのみFALSEを反映するようにフックを制限できます。
これがどのように行われたかについての小さなガイドです:
フックのリターンアドレスを取得し、フックされた関数を呼び出したモジュールを見つけます。
wchar_t RetAdr[256];
wsprintf(RetAdr, L"%p", _ReturnAddress());
HMODULE hModule;
GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, RetAdr , &hModule);
ModuleFileNameを取得し、「。exe」が含まれているかどうかを確認し、実行可能ファイルの場合は「Wow64Process」変数をFALSEに設定します。
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;
しかし、ここに別の問題があります。IsWow64Process()はWindows 64ビットオペレーティングシステムにのみ存在するため、オペレーティングシステムが64であるかどうかを実際にチェックするほとんどのプログラム-bitはその関数を実行しません。代わりに、関数が使用可能かどうかを尋ね、それによってシステムが32ビットか64ビットかを判断します。
これを行う方法は、GetProcAddress()を呼び出すことです。
残念ながら、GetProcAddress()は関数アドレスを見つけるために私のソースコードで使用されており、関数をフックするともちろん望ましくない動作が発生するため、文書化されていないAPIをもう少し深く掘り下げてみると、Kernel32.GetProcAddress()がntdll.LdrGetProcedureAddress()。
ネットでabitを読んだ後、フックLdrGetProcedureAddress()が安全であると確信しています。
フックされたLdrGetProcedureAddress()関数では、呼び出し元がIsWow64Processを要求しているかどうかを確認します。 -)そして、関数が存在する[〜#〜]存在しない[〜#〜]であることを呼び出し元に伝えます!
今、私たちはすべての(新しい)プロセスにフックを注入する必要があります、私はすでにそれに精通しているのでAppInit_DLLsメソッドを使用することにしました仕事はとても上手です。
Web上にはAppInit_DLLsに関する情報がたくさんありますが、それらはすべて32ビットを参照しており、そのソリューションは私のWindows 764ビットOSでは実際には機能しません。 。簡単にするために、32ビットおよび64ビットのAppInit_DLLの正しいレジストリパスを次に示します。
32ビット:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows
64ビット:HKEY_LOCAL_MACHINE\Software \Wow6432Node\ Microsoft\Windows NT\CurrentVersion\Windows
LoadAppInit_DLLsを0x1に設定し、AppInit_DLLsをDLLパス。
これが最終的なソースコードです。使用します mhookライブラリ :
#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;
}
64ビットプログラムを32ビットとして強制的に実行することはできません。 64ビットプログラムは一度に64ビット命令としてアセンブルされるためですが、64ビットプロセッサで32ビットプログラムを実行すると、osは32ビットシステム呼び出しを64ビット形式に変換します。同じ質問がここで答えられましたこれをチェックしてください。 64ビットWindowsでアプリケーションを32ビットプロセスで実行するように強制する