¿Cómo engañar a los programas haciéndoles creer que se ejecutan en 32 bits?

¿Cómo engañar a los programas haciéndoles creer que se ejecutan en 32 bits?

Básicamente tengo 3 ejecutables en mi Windows 7 de 64 bits, esos son:

cargador.exe-> Este es un exe de 32 bits 

x86.exe-> Este es un exe de 32 bits

x64.exe-> Este es un exe de 64 bits

Cuandocargador.exeinicia, determina si el sistema es de 32 o 64 bits y carga el archivo apropiado (ya seax86.exeox64.exe), dado que estoy ejecutando un sistema operativo de 64 bits,x64.execomenzará.

me gustaria saber comocargador.exedetermina si mi sistema es 32 o 64? Lo más probable es que sea a través de la llamada API.Kernel32.IsWow64Process()

Ahora tengo que hacer que esa función siempre devuelva FALSO, a escala global y no solo paracargador.exeAsí que esperaba algo parecido a un "enganche de API global" que haga que la función siempre devuelva FALSO.

Pero no sé cómo hacer esto, la última vez que enganché algo fue en Windows 98 y las cosas han cambiado desde entonces.

Entonces, ¿sabes cómo enganchar?EsWow64Process()¿Y así hacer que el proceso crea que se está ejecutando en un entorno de 32 bits?

Respuesta1

Después de horas de entender la API de Windows (y la API no documentada), así como sugerencias y demás, finalmente descubrí cómo hacerlo. Fue un poco complicado, porqueEsWow64Process()Windows lo llama en cada ejecutable incluso antes de que el programa alcance su punto de entrada; si simplemente refleja FALSO, fallará.

Pero noté que las llamadas de Windows provienen de módulos cargados y de esta manera puedo restringir mi gancho para que solo refleje FALSO si la persona que llama es un ejecutable.

Aquí tienes una pequeña guía de cómo se hizo:

  1. Obtenga la dirección del remitente de mi enlace y descubra qué módulo llamó a mi función enlazada:

    wchar_t RetAdr[256];
    wsprintf(RetAdr, L"%p", _ReturnAddress());
    
    HMODULE hModule;
    GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, RetAdr , &hModule);
    
  2. Tome ModuleFileName, verifique si contiene ".exe" y ponga la variable "Wow64Process" en FALSO si es un ejecutable:

    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;
    

Pero aquí hay otro problema,EsWow64Process()solo existe en sistemas operativos Windows de 64 bits, por lo que la mayoría de los programas que realmente verifican si el sistema operativo es de 64 bits no ejecutan esa función, en lugar de eso preguntan si la función está disponible y con ello determinan si el sistema es de 32 bits o 64 bits.

La forma en que lo hacen es llamandoObtenerDirecciónProc().

Desafortunadamente,ObtenerDirecciónProc()se utiliza en mi código fuente para encontrar direcciones de funciones, y conectar la función, por supuesto, dará como resultado un comportamiento no deseado, por lo que profundizamos un poco más en la API no documentada y descubrimos queKernel32.GetProcAddress()llamadasntdll.LdrGetProcedureAddress().

Después de leer un poco en la red, ahora estoy seguro de que es seguro enganchar.LdrGetProcedureAddress().

en nuestro enganchadoLdrGetProcedureAddress()función comprobamos si la persona que llama está solicitandoProceso IsWow64y decirle a la persona que llama que la función noNO¡existir!

Ahora, necesitamos inyectar nuestro gancho en cada (nuevo) proceso, decidí usar elAppInit_DLLmétodo porque ya estoy familiarizado con él y hace el trabajo muy bien.

Hay mucha información sobreAppInit_DLLen la web, pero todos se refieren a 32 bits y su solución realmente no funciona en mi sistema operativo Windows 7 de 64 bits. Para ponérselo más fácil, estas son las rutas de registro correctas para AppInit_DLL de 32 y 64 bits:

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

64 bits: HKEY_LOCAL_MACHINE\Software\Wow6432Nodo\Microsoft\Windows NT\Versión actual\Windows

EstablecimosLoadAppInit_DLLa 0x1 yAppInit_DLLa nuestra ruta DLL.

Aquí está el código fuente final, utilizabiblioteca 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;
}

Respuesta2

Nunca se puede forzar que un programa de 64 bits se ejecute como de 32 bits. Porque los programas de 64 bits se ensamblan como instrucciones de 64 bits a la vez, pero cuando ejecuta un programa de 32 bits en un procesador de 64 bits, el sistema operativo convierte las llamadas al sistema de 32 bits al formato de 64 bits. La misma pregunta ha sido respondida aquí. Mira esto. Forzar la ejecución de la aplicación en un proceso de 32 bits en Windows de 64 bits

información relacionada