Речь пойдёт об устройстве wow64 в винде. Для неосведомлённых: wow64 - это подсистема x64 винды для запуска x86 приложений. Всё далее описанное относится к x64 винде.
Для начала, смотрим разницу syscall'ov между x86 и x64 приложениями:
x64:
x86:
По fs:[c0h] прыжок в cs:33 для перехода в x64
Т.е. сисколл из x86 приложения в итоге заканчивается переходом в x64, сисколлом и возвращением обратно. Это означает, что можно спокойно выполнять x64 код в контексте приложения x86. Открывать велосипед не буду - подробно разбирал этот механизм rewolf, создав данный проект:
Я хотел бы рассказать про то, что происходит при запуске x86 приложения. А при запуске x86 приложения первым делом инициализируется процесс функцией ntdll!LdrpInitializeProcess, которая в свою очередь уходит в ntdll!Wow64LdrpInitialize:
Данная функция уходит в wow64!ProcessInit, а та в wow64!Wow64pLoadLogDll
Эта функция подгружает C:\Windows\System32\wow64log.dll
После этого произойдёт попытка получить адреса функций: Wow64LogSystemService, Wow64LogMessageArgList, Wow64LogTerminate, Wow64LogInitialize, если все нашлись ,то передача управления на Wow64LogInitialize
Т.к. я ни разу не замечал wow64log.dll в system32, то логично предположить, что её там просто напросто нет и предназначена эта тема была скорее всего для отладки. Нам же это даёт возможность выполнять свой код при старте каждого x86 процесса, правда с серьёзными ограничениями в виде отсутствия возможности использовать апи как привычно ибо мы находимся в контексте x86 приложения. Большого кода как пример эксплуатации данной возможности я не писал, вот пример длл (проект приложен внизу статьи):
C++:
#include <Windows.h>
#include <winternl.h>
typedef NTSTATUS(NTAPI *T_NtDelayExecution)(
IN BOOLEAN Alertable,
IN PLARGE_INTEGER DelayInterval);
EXTERN_C __declspec(dllexport) void WINAPI Wow64LogSystemService() {}
EXTERN_C __declspec(dllexport) void WINAPI Wow64LogMessageArgList() {}
EXTERN_C __declspec(dllexport) void WINAPI Wow64LogTerminate() {}
EXTERN_C __declspec(dllexport) void WINAPI Wow64LogInitialize()
{
T_NtDelayExecution NtDelayExecution = (T_NtDelayExecution)0x7ffe2fe80a10;
LARGE_INTEGER lTime;
lTime.QuadPart = 5000 * -10000;
NtDelayExecution(FALSE, &lTime);
}
BOOL WINAPI _DllMainCRTStartup(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}
После дропа данной длл с именем wow64log.dll в system32, я мог наблюдать таймаут на запуск каждого нового x86 процесса длительностью в 5 секунд.
Утилита для получения адреса функции в архиве, для неё как раз была использована wow64ext. Здесь не путать адрес от GetProcAddress x64 процесса с адресом от этой утилиты, т.к. x64 ntdll маппится в x86 процесс по другому адресу.
Пример предназначен как POC использования, поэтому динамического получения адресов здесь не было, это можно написать на основе исходов wow64ext.
Для начала, смотрим разницу syscall'ov между x86 и x64 приложениями:
x64:
x86:
По fs:[c0h] прыжок в cs:33 для перехода в x64
Т.е. сисколл из x86 приложения в итоге заканчивается переходом в x64, сисколлом и возвращением обратно. Это означает, что можно спокойно выполнять x64 код в контексте приложения x86. Открывать велосипед не буду - подробно разбирал этот механизм rewolf, создав данный проект:
Я хотел бы рассказать про то, что происходит при запуске x86 приложения. А при запуске x86 приложения первым делом инициализируется процесс функцией ntdll!LdrpInitializeProcess, которая в свою очередь уходит в ntdll!Wow64LdrpInitialize:
Данная функция уходит в wow64!ProcessInit, а та в wow64!Wow64pLoadLogDll
Эта функция подгружает C:\Windows\System32\wow64log.dll
После этого произойдёт попытка получить адреса функций: Wow64LogSystemService, Wow64LogMessageArgList, Wow64LogTerminate, Wow64LogInitialize, если все нашлись ,то передача управления на Wow64LogInitialize
Т.к. я ни разу не замечал wow64log.dll в system32, то логично предположить, что её там просто напросто нет и предназначена эта тема была скорее всего для отладки. Нам же это даёт возможность выполнять свой код при старте каждого x86 процесса, правда с серьёзными ограничениями в виде отсутствия возможности использовать апи как привычно ибо мы находимся в контексте x86 приложения. Большого кода как пример эксплуатации данной возможности я не писал, вот пример длл (проект приложен внизу статьи):
C++:
#include <Windows.h>
#include <winternl.h>
typedef NTSTATUS(NTAPI *T_NtDelayExecution)(
IN BOOLEAN Alertable,
IN PLARGE_INTEGER DelayInterval);
EXTERN_C __declspec(dllexport) void WINAPI Wow64LogSystemService() {}
EXTERN_C __declspec(dllexport) void WINAPI Wow64LogMessageArgList() {}
EXTERN_C __declspec(dllexport) void WINAPI Wow64LogTerminate() {}
EXTERN_C __declspec(dllexport) void WINAPI Wow64LogInitialize()
{
T_NtDelayExecution NtDelayExecution = (T_NtDelayExecution)0x7ffe2fe80a10;
LARGE_INTEGER lTime;
lTime.QuadPart = 5000 * -10000;
NtDelayExecution(FALSE, &lTime);
}
BOOL WINAPI _DllMainCRTStartup(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}
После дропа данной длл с именем wow64log.dll в system32, я мог наблюдать таймаут на запуск каждого нового x86 процесса длительностью в 5 секунд.
Утилита для получения адреса функции в архиве, для неё как раз была использована wow64ext. Здесь не путать адрес от GetProcAddress x64 процесса с адресом от этой утилиты, т.к. x64 ntdll маппится в x86 процесс по другому адресу.
Пример предназначен как POC использования, поэтому динамического получения адресов здесь не было, это можно написать на основе исходов wow64ext.