Как обмануть программы, заставив их думать, что они работают под управлением 32-битной ОС?

Как обмануть программы, заставив их думать, что они работают под управлением 32-битной ОС?

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

Загрузчик.exe-> Это 32-битный exe-файл 

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

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

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

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

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

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

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

решение1

После нескольких часов размышлений над Windows API (и недокументированным API), а также указателями и прочим, я наконец понял, как это сделать. Это было довольно сложно, потому чтоIsWow64Process()вызывается Windows для каждого исполняемого файла, даже до того, как программа достигнет точки входа. Если вы просто отразите значение 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().

Почитав немного в сети, я теперь уверен, что это безопасно.LdrGetProcedureAddress().

В нашем зацепленномLdrGetProcedureAddress()функция, мы проверяем, запрашивает ли вызывающийIsWow64Процесси сообщить вызывающему, что функция делаетНЕТсуществовать!

Теперь нам нужно внедрить наш хук в каждый (новый) процесс, я решил использоватьAppInit_DLLметод, потому что я уже с ним знаком и он отлично справляется со своей задачей.

Есть много информации оAppInit_DLLв сети, но все они относятся к 32-битной версии, и их решение на самом деле не работает на моей 64-битной ОС Windows 7. Чтобы облегчить вам задачу, вот правильные пути реестра для 32-битных и 64-битных AppInit_DLL:

32-битный: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows

64-битный: HKEY_LOCAL_MACHINE\Программное обеспечение\Wow6432Node\Microsoft\Windows NT\Текущая версия\Windows

Мы устанавливаемLoadAppInit_DLLк 0x1 иAppInit_DLLк нашему пути 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;
}

решение2

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

Связанный контент