После нескольких часов работы над Windows API (и недокументированным API), а также указателями и прочим, я наконец-то узнал, как это сделать.
Это было довольно сложно, потому что IsWow64Process () вызывается Windows на каждом исполняемом файле еще до того, как программа достигает ее EntryPoint, если вы просто отразите FALSE, то произойдет сбой.
Но я заметил, что вызовы Window поступают из загруженных модулей, и таким образом я могу ограничить свой хук только отражением FALSE, если вызывающий является исполняемым файлом.
Вот небольшое руководство о том, как это было сделано:
Получите адрес возврата моего хука и выясните, какой модуль вызвал мою перехваченную функцию:
wchar_t RetAdr[256];
wsprintf(RetAdr, L"%p", _ReturnAddress());
HMODULE hModule;
GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, RetAdr , &hModule);
Возьмите 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;
Но вот еще одна проблема, IsWow64Process() существует только в 64-битных операционных системах Windows, поэтому большинство программ, которые фактически проверяют, является ли операционная система 64-битной, не запускают эту функцию, вместо этого они спрашивают, доступна ли эта функция и тем самым определить, является ли система 32-битной или 64-битной.
Они делают это путем вызова GetProcAddress().
К сожалению, GetProcAddress() используется в моем исходном коде для поиска адресов функций, и перехват функции, конечно, приведет к нежелательному поведению, поэтому мы углубимся в недокументированный API и обнаружим, что Kernel32.GetProcAddress() вызывает ntdll.LdrGetProcedureAddress().
После прочтения abit в сети я теперь уверен, что перехватить LdrGetProcedureAddress() безопасно.
В нашей перехваченной функции LdrGetProcedureAddress() мы проверяем, запрашивает ли вызывающий объект IsWow64Process, и сообщаем вызывающему, что функция НЕ существует!
Теперь нам нужно внедрить наш хук в каждый (новый) процесс, я решил использовать метод AppInit_DLLs, потому что я уже знаком с ним, и он отлично справляется со своей задачей.
В Интернете много информации о AppInit_DLL , но все они относятся к 32-битной версии, и их решение не работает на моей 64-битной ОС Windows 7. Чтобы вам было проще, вот правильные пути реестра для 32-битных и 64-битных AppInit_DLLs:
32-разрядная версия: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows
64-разрядная версия: HKEY_LOCAL_MACHINE\Software\ Wow6432Node \ Microsoft \ Windows NT \ CurrentVersion \ Windows
Мы устанавливаем LoadAppInit_DLLs в 0x1 и AppInit_DLLs в наш путь к DLL.
Вот окончательный исходный код, он использует библиотеку 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;
}