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:
-
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);
-
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;
}