プログラムを騙して 32 ビットで実行されていると思わせるにはどうすればよいでしょうか?

プログラムを騙して 32 ビットで実行されていると思わせるにはどうすればよいでしょうか?

基本的に、私の 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 を反映するようにフックを制限できます。

以下に、その方法についての簡単なガイドを示します。

  1. フックの戻りアドレスを取得し、フックされた関数を呼び出したモジュールを見つけます。

    wchar_t RetAdr[256];
    wsprintf(RetAdr, L"%p", _ReturnAddress());
    
    HMODULE hModule;
    GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, RetAdr , &hModule);
    
  2. 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 ビット プロセスで実行するように強制する

関連情報