Como enganar os programas para pensarem que estão rodando em 32 bits?

7

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

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

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

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

Quando o Loader.exe é iniciado, ele determina se o sistema é de 32 bits ou 64 bits e carrega o arquivo apropriado ( x86.exe ou x64 .exe ), como estou executando um sistema operacional de 64 bits, o x64.exe será iniciado.

Gostaria de saber como Loader.exe determina se meu sistema é 32 ou 64? O que é mais provável através da chamada da API Kernel32.IsWow64Process ()

Agora eu tenho que fazer essa função sempre retornar FALSE, em uma escala global e não apenas para Loader.exe , Então, eu estava esperando algo ao longo das linhas de um "gancho de API global" que faz a função sempre retornar FALSE.

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

Então, você sabe como ligar o IsWow64Process () e, assim, fazer com que o processo acredite que está sendo executado em um ambiente de 32 bits?

    
por Æless Norm 04.07.2012 / 13:20

2 respostas

7

Depois de passar a cabeça pela API do Windows (e pela API não documentada), além de ponteiros e outras coisas, finalmente descobri como fazer isso. Foi meio complicado, porque o IsWow64Process () é chamado pelo Windows em todos os executáveis, mesmo antes do programa atingir o seu EntryPoint, se você apenas refletir FALSE, ele irá falhar.

Mas notei que as chamadas do Windows são provenientes de módulos carregados e, dessa forma, posso restringir meu gancho para refletir apenas FALSE 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 chamado minha função viciada:

    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 ele contém ".exe" e coloque "Wow64Process" variável para 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, o 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, portanto, determinam se o sistema é de 32 bits ou 64 bits.

A maneira como eles fazem isso é chamando GetProcAddress () .

Infelizmente, GetProcAddress () é usado no meu código-fonte para encontrar endereços de função, e ligar a função naturalmente resultará em comportamento indesejado, então nós nos aprofundamos um pouco mais na API não documentada e nós descubra que Kernel32.GetProcAddress () chama ntdll.LdrGetProcedureAddress () .

Depois de ler abit na net, agora estou certo de que é seguro ligar LdrGetProcedureAddress () .

Em nossa função LdrGetProcedureAddress () conectada, verificamos se o chamador está solicitando IsWow64Process e informamos ao chamador que a função NOT existe !

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

Há muitas informações sobre AppInit_DLLs na web, mas todas elas se referem a 32 bits e sua solução realmente não funciona no sistema operacional Windows 7 de 64 bits. Para facilitar, aqui estão os caminhos de registro corretos para AppInit_DLLs de 32 bits e 64 bits:

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

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

Definimos LoadAppInit_DLLs como 0x1 e AppInit_DLLs como nosso caminho da DLL.

Aqui está o código-fonte final, ele usa a biblioteca do 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;
}
    
por 28.07.2012 / 20:25
0

Você nunca pode forçar o programa de 64 bits a ser executado como 32 bits. Porque programas de 64 bits são montados como instruções de 64 bits de cada vez.Mas quando você executar o programa de 32 bits no processador de 64 bits, o sistema operacional converter chamadas de sistema de 32 bits para o formato de 64 bits. A mesma pergunta foi respondida aqui, veja isto. Força a execução do aplicativo no processo de 32 bits no Windows de 64 bits

    
por 04.07.2012 / 13:34