
基本的に、私の Windows 7 64 ビットには 3 つの実行可能ファイルがあります。
ローダー.exe-> これは32ビットのexeです
実行ファイル-> これは32ビットのexeです
64ビット-> これは64ビットのexeです
いつローダー.exe起動すると、システムが32ビットか64ビットかを判断し、適切なファイル(実行ファイルまたは64ビット)、64ビットオペレーティングシステムを実行しているため、64ビット始まります。
方法を知りたいローダー.exeシステムが32か64かを判断するには?どちらがAPI呼び出しによる可能性が高いかカーネル32.IsWow64Process()
今、私はその関数が常にFALSEを返すようにしなければなりません。ローダー.exeそこで、関数が常に FALSE を返すような「グローバル API フック」のようなものを期待していました。
しかし、私はこれをどうやって行うのか分かりません。私が最後に何かをフックしたのは Windows 98 のときで、それ以来状況は変わっています。
フックのやり方をご存知ですか?IsWow64Process()それによって、プロセスは 32 ビット環境で実行されていると認識するのでしょうか?
答え1
Windows API(および文書化されていないAPI)やポインターなどについて何時間も頭を悩ませた後、ようやくやり方がわかりました。ちょっと難しかったのですが、IsWow64Process()プログラムが EntryPoint に到達する前であっても、すべての実行可能ファイルで Windows によって呼び出されます。FALSE を反映するだけではクラッシュしてしまいます。
しかし、ウィンドウの呼び出しはロードされたモジュールから行われていることに気づいたので、この方法では、呼び出し元が実行可能ファイルの場合にのみ 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 ビットかどうかを実際にチェックするほとんどのプログラムは、その機能を実行せず、代わりにその機能が使用可能かどうかを尋ねて、システムが 32 ビットか 64 ビットかを判断します。
彼らがこれを行う方法は、プロセスアドレスを取得する()。
残念ながら、プロセスアドレスを取得する()私のソースコードでは関数のアドレスを見つけるために使用されており、関数をフックすると当然望ましくない動作が発生します。そこで、文書化されていないAPIをもう少し詳しく調べると、Kernel32.GetProcAddress()通話ntdll.LdrGetProcedureAddress()。
ネットで少し読んだ後、フックしても安全だと確信しましたLdrGetProcedureAddress()。
私たちの夢中になったLdrGetProcedureAddress()関数は呼び出し側が要求しているかどうかをチェックしますIsWow64プロセスそして、関数がない存在する!
さて、私たちはフックをすべての(新しい)プロセスに注入する必要があるので、AppInit_DLLsこの方法は、すでによく知っているし、非常にうまく機能するからです。
たくさんの情報がありますAppInit_DLLsウェブ上では、それらはすべて 32 ビットを参照しており、それらのソリューションは私の Windows 7 64 ビット OS では実際には機能しません。簡単にするために、32 ビットおよび 64 ビットの AppInit_DLL の正しいレジストリ パスを以下に示します。
32ビット: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows
64ビット: HKEY_LOCAL_MACHINE\ソフトウェア\ワオ6432ノード\Microsoft\Windows NT\現在のバージョン\Windows
私たちはLoadAppInit_DLLs0x1にAppInit_DLLsDLL パスに追加します。
これが最終的なソースコードです。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;
}
答え2
64 ビット プログラムを 32 ビットとして実行するように強制することはできません。64 ビット プログラムは、一度に 64 ビット命令としてアセンブルされるためです。ただし、32 ビット プログラムを 64 ビット プロセッサで実行すると、OS は 32 ビット システム コールを 64 ビット形式に変換します。同じ質問に対する回答がここにあります。こちらを確認してください。 64 ビット Windows 上でアプリケーションを 32 ビット プロセスで実行するように強制する