web-dev-qa-db-ja.com

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

基本的に、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ビット環境で実行されていると信じ込ませますか?

7
Æless Norm

何時間もWindowsAPI(および文書化されていないAPI)とポインターなどに頭を悩ませた後、私はついにそれを行う方法を見つけました。 IsWow64Process()は、プログラムがEntryPointに到達する前であっても、すべての実行可能ファイルでWindowsによって呼び出されるため、ちょっと注意が必要でした。FALSEを反映するだけで、クラッシュする。

しかし、Windowの呼び出しがロードされたモジュールからのものであることに気付きました。このようにして、呼び出し元が実行可能ファイルである場合にのみ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であるかどうかを実際にチェックするほとんどのプログラム-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;
}
7
Æless Norm

64ビットプログラムを32ビットとして強制的に実行することはできません。 64ビットプログラムは一度に64ビット命令としてアセンブルされるためですが、64ビットプロセッサで32ビットプログラムを実行すると、osは32ビットシステム呼び出しを64ビット形式に変換します。同じ質問がここで答えられましたこれをチェックしてください。 64ビットWindowsでアプリケーションを32ビットプロセスで実行するように強制する

0
arundevma