Como fazer com que os programas pensem que estão rodando em 32 bits?

Como fazer com que os programas pensem que estão rodando em 32 bits?

Basicamente eu tenho 3 executáveis ​​no meu Windows 7 de 64 bits, são eles:

Carregador.exe-> Este é um exe de 32 bits 

x86.exe-> Este é um exe de 32 bits

x64.exe-> Este é um exe de 64 bits

QuandoCarregador.exeinicia, determina se o sistema é de 32 ou 64 bits e carrega o arquivo apropriado (sejax86.exeoux64.exe), como estou executando um sistema operacional de 64 bits, ox64.exevai começar.

Eu gostaria de saber comoCarregador.exedetermina se meu sistema é 32 ou 64? O que provavelmente ocorre por meio da chamada da APIKernel32.IsWow64Process()

Agora tenho que fazer com que essa função retorne sempre FALSE, em escala global e não apenas paraCarregador.exe, Então, eu esperava algo parecido com um "gancho de API global" que faz com que a função sempre retorne FALSE.

Mas não sei como fazer isso, a última vez que fisguei algo foi no Windows 98 e as coisas mudaram desde então.

Então você sabe como engancharIsWow64Process()e assim fazer o processo acreditar que está sendo executado em um ambiente de 32 bits?

Responder1

Depois de horas pensando na API do Windows (e na API não documentada), bem como em dicas e tudo o mais, finalmente descobri como fazer isso. Foi meio complicado, porqueIsWow64Process()é chamado pelo Windows em todos os executáveis, mesmo antes de o programa atingir seu EntryPoint; se você apenas refletir FALSE, ele travará.

Mas percebi que as chamadas do Windows vêm de módulos carregados e, dessa forma, posso restringir meu gancho para refletir FALSE apenas se o chamador for um executável.

Aqui está um pequeno guia sobre como isso foi feito:

  1. Obtenha o endereço de retorno do meu gancho e descubra qual módulo chamou minha função de gancho:

    wchar_t RetAdr[256];
    wsprintf(RetAdr, L"%p", _ReturnAddress());
    
    HMODULE hModule;
    GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, RetAdr , &hModule);
    
  2. Pegue o ModuleFileName, verifique se contém ".exe" e coloque a variável "Wow64Process" como FALSE se for um executável:

    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;
    

Mas aqui está outro problema,IsWow64Process()existe apenas em sistemas operacionais Windows de 64 bits, portanto, a maioria dos programas que realmente verificam se o sistema operacional é de 64 bits não executam essa função; em vez disso, perguntam se a função está disponível e, assim, determinam se o sistema é de 32 bits ou 64 bits.

A maneira como eles fazem isso é ligandoGetProcAddress().

Infelizmente,GetProcAddress()é usado em meu código-fonte para encontrar endereços de funções, e conectar a função resultará em comportamento indesejado, então nos aprofundamos um pouco mais na API não documentada e descobrimos queKernel32.GetProcAddress()chamadasntdll.LdrGetProcedureAddress().

Depois de ler um pouco na net, agora tenho certeza de que é seguro fisgarLdrGetProcedureAddress().

Em nosso fisgadoLdrGetProcedureAddress()função, verificamos se o chamador está solicitandoÉWow64Processe diga ao chamador que a função fazNÃOexistir!

Agora, precisamos injetar nosso gancho em cada (novo) processo, decidi usar oAppInit_DLLsmétodo porque já estou familiarizado com ele e ele faz o trabalho muito bem.

Tem muita informação sobreAppInit_DLLsna web, mas todos eles se referem a 32 bits e sua solução realmente não funciona no meu sistema operacional Windows 7 de 64 bits. Para facilitar para você, aqui estão os caminhos de registro corretos para AppInit_DLLs de 32 e 64 bits:

32 bits: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows

64 bits: HKEY_LOCAL_MACHINE\Software\Uau6432Node\Microsoft\Windows NT\CurrentVersion\Windows

MontamosLoadAppInit_DLLspara 0x1 eAppInit_DLLspara o nosso caminho DLL.

Aqui está o código-fonte final, ele usabiblioteca 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;
}

Responder2

Você nunca pode forçar um programa de 64 bits a ser executado como 32 bits. Porque os programas de 64 bits são montados como instruções de 64 bits por vez. Mas quando você executa um programa de 32 bits em um processador de 64 bits, o sistema operacional converte as chamadas do sistema de 32 bits para o formato de 64 bits. A mesma pergunta foi respondida aqui, verifique isso. Forçar a execução do aplicativo em processo de 32 bits no Windows de 64 bits

informação relacionada