프로그램이 32비트에서 실행되고 있다고 생각하도록 속이는 방법은 무엇입니까?

프로그램이 32비트에서 실행되고 있다고 생각하도록 속이는 방법은 무엇입니까?

기본적으로 Windows 7 64비트에는 다음과 같은 3개의 실행 파일이 있습니다.

로더.exe-> 32비트 exe입니다. 

x86.exe-> 32비트 exe입니다.

x64.exe-> 64비트 exe입니다.

언제로더.exe시작하면 시스템이 32비트인지 64비트인지 확인하고 적절한 파일을 로드합니다(둘 중 하나).x86.exe또는x64.exe), 저는 64비트 운영 체제를 실행하고 있으므로x64.exe시작할 것이다.

방법을 알고 싶습니다.로더.exe내 시스템이 32인지 64인지 결정합니까? API 호출을 통해 발생할 가능성이 가장 높습니다.Kernel32.IsWow64Process()

이제 그 함수가 단지 FALSE를 반환하는 것이 아니라 글로벌 규모로 항상 FALSE를 반환하도록 해야 합니다.로더.exe, 그래서 저는 함수가 항상 FALSE를 반환하게 만드는 "글로벌 API 후크" 라인을 따라 무언가를 바라고 있었습니다.

하지만 어떻게 해야 할지 모르겠습니다. 제가 마지막으로 뭔가를 연결한 것은 Windows 98이었고 그 이후로 상황이 바뀌었습니다.

그렇다면 Hook을 사용하는 방법을 아시나요?IsWow64프로세스()그러면 프로세스가 32비트 환경에서 실행되고 있다고 믿게 될까요?

답변1

몇 시간 동안 Windows API(및 문서화되지 않은 API)와 포인터 등을 둘러본 끝에 마침내 그 방법을 알아냈습니다. 좀 까다로웠거든요.IsWow64프로세스()프로그램이 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;
    

그런데 여기서 또 다른 문제가 있는데,IsWow64프로세스()는 Windows 64비트 운영 체제에만 존재하므로 실제로 운영 체제가 64비트인지 확인하는 대부분의 프로그램은 해당 기능을 실행하지 않고 대신 해당 기능을 사용할 수 있는지 묻고 시스템이 32비트인지 또는 32비트인지 확인합니다. 64비트.

그들이 하는 방법은 전화를 하는 것입니다.GetProc주소().

안타깝게도,GetProc주소()내 소스 코드에서 함수 주소를 찾는 데 사용되며, 함수를 연결하면 바람직하지 않은 동작이 발생하므로 문서화되지 않은 API를 좀 더 자세히 살펴보고 다음을 알아냈습니다.Kernel32.GetProcAddress()전화ntdll.LdrGetProcedureAddress().

인터넷에서 abit을 읽은 후 이제 연결해도 안전하다고 확신합니다.LdrGetProcedureAddress().

우리의 푹 빠진LdrGetProcedureAddress()호출자가 요청하는지 확인하는 기능IsWow64프로세스호출자에게 함수가 수행하는 작업을 알려줍니다.아니다존재하다!

이제 우리는 모든 (새로운) 프로세스에 후크를 삽입해야 합니다.AppInit_DLL방법은 이미 익숙하고 작업을 매우 잘 수행하기 때문입니다.

에 관한 정보가 많이 있습니다.AppInit_DLL웹에서는 모두 32비트를 참조하고 있으며 해당 솔루션은 내 Windows 7 64비트 OS에서는 실제로 작동하지 않습니다. 보다 쉽게 ​​작업할 수 있도록 32비트 및 64비트 AppInit_DLL에 대한 올바른 레지스트리 경로는 다음과 같습니다.

32비트: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows

64비트: HKEY_LOCAL_MACHINE\소프트웨어\Wow6432노드\Microsoft\Windows NT\CurrentVersion\Windows

우리는 설정했다LoadAppInit_DLL0x1로 그리고AppInit_DLLDLL 경로로 이동합니다.

다음은 최종 소스 코드입니다.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비트 명령으로 어셈블되기 때문입니다. 그러나 64비트 프로세서에서 32비트 프로그램을 실행하면 OS는 32비트 시스템 호출을 64비트 형식으로 변환합니다. 동일한 질문에 대한 답변이 여기에 나와 있습니다. 이것을 확인하세요. 64비트 Windows에서 애플리케이션을 32비트 프로세스로 강제 실행

관련 정보