7

В основном у меня есть 3 исполняемых файла в моей Windows 7 64-битных, это:

Loader.exe -> Это 32-битный exe 

x86.exe -> Это 32-битный exe

x64.exe -> Это 64-битный exe

Когда запускается Loader.exe, он определяет, является ли система 32-разрядной или 64-разрядной, и загружает соответствующий файл (x86.exe или x64.exe), так как я использую 64-разрядную операционную систему, x64.exe будет Начните.

Я хотел бы знать, как Loader.exe определяет, если моя система 32 или 64? Что скорее всего через API-вызов Kernel32.IsWow64Process()

Теперь я должен сделать так, чтобы эта функция всегда возвращала FALSE в глобальном масштабе, а не только для Loader.exe, поэтому я надеялся на что-то вроде «глобального API-хука», который заставляет функцию всегда возвращать FALSE.

Но я не знаю, как это сделать, последний раз, когда я что-то подключал, был в Windows 98, и с тех пор все изменилось.

Так вы случайно не знаете, как подключить IsWow64Process() и тем самым заставить процесс поверить, что он работает в 32-битной среде?

2 ответа2

7

После нескольких часов работы над Windows API (и недокументированным API), а также указателями и прочим, я наконец-то узнал, как это сделать. Это было довольно сложно, потому что IsWow64Process () вызывается Windows на каждом исполняемом файле еще до того, как программа достигает ее EntryPoint, если вы просто отразите FALSE, то произойдет сбой.

Но я заметил, что вызовы Window поступают из загруженных модулей, и таким образом я могу ограничить свой хук только отражением FALSE, если вызывающий является исполняемым файлом.

Вот небольшое руководство о том, как это было сделано:

  1. Получите адрес возврата моего хука и выясните, какой модуль вызвал мою перехваченную функцию:

    wchar_t RetAdr[256];
    wsprintf(RetAdr, L"%p", _ReturnAddress());
    
    HMODULE hModule;
    GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, RetAdr , &hModule);
    
  2. Возьмите 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;
}
0

Вы никогда не сможете принудительно запустить 64-битную программу как 32-битную. Потому что 64-битные программы собираются как 64-битные инструкции одновременно.Но когда вы запускаете 32-битную программу на 64-битном процессоре, ОС конвертирует 32-битные системные вызовы в 64-битный формат. Здесь ответили на тот же вопрос. Принудительно запустить приложение в 32-битном процессе в 64-битной Windows

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .