Всем привет!
Сейчас будет разбор решения для ByPassMe из этой темы - [BypassMe] Interium Game
Я создал отдельную тему так как здесь будет демонстрироваться 1 из путей обхода проверки CRC в VMProtect 3.X
Таргет напичкан различными анти-дебаг триками, и при срабатывании одного из них отладчик сообщает нам о каком то непонятном исключении:
Исключение происходит во время трассировки кода, это значит что оно срабатывает из другого потока. Следуя логике ставим бряк на CreateThread и выходим на код создающий исключение при срабатывании одного из анти-дебаг трика:
Автор этого байпассми сказал что в программе используется пользовательская ВМ. Что это значит? Это значит что для каждого вызова (call) есть свой хендлер, если мы протрассируем код из скрина выше то наткнёмся на тот самый хендлер:
Теперь наша задача сделать патч всего этого дела. Мешают сделать патч здесь 2 вещи:
1) Проверка CRC от VMProtect
2) Хук на NtProtectVirtualMemory для выдачи прав на запись региону памяти.
Начнём с первого пункта. Все ведь знают что винда при загрузке длл из таблицы импорта сначала ищет её в папке с exe? Будем использовать этот стандартный метод атаки (с его помощью кстати часто повышают привилегии в UNIX системе). Смотрим таблицу импорта и видим дллку которая вообще не используется в программе вместе с импортом:
Создаём проект в визуалке и добавляем эту функцию в экспорт:
Компилируем длл с именем "WTSAPI32.dll" и суём её в папку с exe. Теперь винда будет грузить нашу длл вместо оригинальной и мы можем прописать в ней всё что душе угодно.
Теперь второй пункт, автор хукнул NtProtectVirtualMemory что б нам жизнь малиной не казалась. Обходим это через шеллкод, ниже код из нашей длл-заглушки:
Теперь отрубаем все плагины и запускаем софт в отладчике:
Сейчас будет разбор решения для ByPassMe из этой темы - [BypassMe] Interium Game
Я создал отдельную тему так как здесь будет демонстрироваться 1 из путей обхода проверки CRC в VMProtect 3.X
Таргет напичкан различными анти-дебаг триками, и при срабатывании одного из них отладчик сообщает нам о каком то непонятном исключении:
Исключение происходит во время трассировки кода, это значит что оно срабатывает из другого потока. Следуя логике ставим бряк на CreateThread и выходим на код создающий исключение при срабатывании одного из анти-дебаг трика:
Автор этого байпассми сказал что в программе используется пользовательская ВМ. Что это значит? Это значит что для каждого вызова (call) есть свой хендлер, если мы протрассируем код из скрина выше то наткнёмся на тот самый хендлер:
Теперь наша задача сделать патч всего этого дела. Мешают сделать патч здесь 2 вещи:
1) Проверка CRC от VMProtect
2) Хук на NtProtectVirtualMemory для выдачи прав на запись региону памяти.
Начнём с первого пункта. Все ведь знают что винда при загрузке длл из таблицы импорта сначала ищет её в папке с exe? Будем использовать этот стандартный метод атаки (с его помощью кстати часто повышают привилегии в UNIX системе). Смотрим таблицу импорта и видим дллку которая вообще не используется в программе вместе с импортом:
Создаём проект в визуалке и добавляем эту функцию в экспорт:
C++:
#define DLL_EXPORT extern "C" __declspec( dllexport )
DLL_EXPORT BOOL WTSSendMessageW(
HANDLE hServer,
DWORD SessionId,
LPWSTR pTitle,
DWORD TitleLength,
LPWSTR pMessage,
DWORD MessageLength,
DWORD Style,
DWORD Timeout,
DWORD* pResponse,
BOOL bWait
)
{
return TRUE;
}
Компилируем длл с именем "WTSAPI32.dll" и суём её в папку с exe. Теперь винда будет грузить нашу длл вместо оригинальной и мы можем прописать в ней всё что душе угодно.
Теперь второй пункт, автор хукнул NtProtectVirtualMemory что б нам жизнь малиной не казалась. Обходим это через шеллкод, ниже код из нашей длл-заглушки:
C++:
int StartRoutine()
{
HMODULE main_module = GetModuleHandleA( 0 );
if ( main_module )
{
//
// Ждём распаковки оригинального кода программы
//
uintptr_t patch_addr = (uintptr_t)main_module + 0x7179;
while ( *(WORD*)( patch_addr ) != 0x50FF )
{
Sleep( 100 );
}
//
// Ждём установку хука
//
FARPROC nt_protect = GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "NtProtectVirtualMemory" );
while ( *(BYTE*)nt_protect == 0xE9 )
{
Sleep( 100 );
}
Sleep( 500 ); // Дополнительный слип так как триггерится CRC VMProtect'a если патчить сразу после распаковки кода
//
// Шеллкод для вызова NtProtectVirtualMemory
//
unsigned char shell_syscall[] = {
0xB8, 0x50, 0x00, 0x00, 0x00, // mov eax, number ($+0x00)
0xBA, 0x40, 0x8D, 0x70, 0x77, // mov edx, Wow64Transition ($+0x05)
0xFF, 0xD2, // call edx ($+0x0A)
0xC2, 0x14, 0x00 // ret 0x14 ($+0x0C)
};
//
// Заполняем шеллкод нужными данными
//
uintptr_t shell_mem = (uintptr_t)VirtualAlloc( 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
memcpy( (void*)shell_mem, shell_syscall, sizeof( shell_syscall ) );
*(uint32_t*)( shell_mem + 0x1 ) = GetSystemNumber( "NtProtectVirtualMemory" );
*(uintptr_t*)( shell_mem + 0x6 ) = *(uintptr_t*)( GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "Wow64Transition" ) );
t_NtProtectVirtualMemory m_NtProtectVirtualMemory = (t_NtProtectVirtualMemory)shell_mem;
//
// Выдаём региону памяти права на запись через шеллкод
//
PVOID BaseAddress = (PVOID)patch_addr;
SIZE_T RegionSize = 0x1000;
ULONG oldProtect = 0;
m_NtProtectVirtualMemory( NtCurrentProcess, &BaseAddress, &RegionSize, PAGE_EXECUTE_READWRITE, &oldProtect );
//
// Патч vm_call
//
memset( (void*)patch_addr, 0x90, 3 );
}
return 0;
}
Теперь отрубаем все плагины и запускаем софт в отладчике: