• Добро пожаловать на сайт - wlux.net!

    FAQ по форуму

    1. Все сообщения до группы местный проходят модерацию от 1 минуты до 24 часа

    2. Сообщения учитываються в следующих разделах: Читать

    3.Что-бы скачать вложение нужно 2 сообщения.

    4.Личные переписки работают только с Администрацией форума

    5. Запрещено: Просить скрытый текст , спам, реклама, скам, ддос, кардинг и другая чернуха, нарушать любые законы РФ/СНГ = бан аккаунта

    6. Внимание! Мы не удаляем аккаунты с форума! Будьте внимательны ДО регистрации! Как удалить аккаунт на форуме?!

    5.Не понимаю, как и что тут работает у вас?!Как создавать темы, писать сообщения, как получать реакции. Почему не засчитывает сообщения. Все ответы здесь

This is a mobile optimized page that loads fast, if you want to load the real page, click this text.

C++ Исходник Гайд [Reverse-Engineering] Обходим проверку CRC в VMProtect 3.X и решаем ByPassMe [2 способа]

Оффлайн

wlux.net

Где волчьи уши, там волчьи зубы.
Команда форума
LV
7
 
20.06.2022
23 845
218
36
Награды
10
Пол
Муж.

Репутация:

  • Автор темы
  • Администратор
  • Модератор
  • Команда форума
  • #1
1 способ:

Здесь будет демонстрироваться 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;
}

Теперь отрубаем все плагины и запускаем софт в отладчике:


2 способ:

=========================================================

Все опыты проводились на Windows 10 x64 1909 (Сборка ОС 18363.1016) – процессор Intel

Подопытный: C++ x64 PE-файл, максимальный пресет защиты от протектора

TitanHide – не использовался

=========================================================

Давайте разбираться, что же такого завезли нам в новой версии.

Для начала подготовим ScyllaHide:



Далее, в настройках ядра самого отладчика(x64dbg) нужно установить “Тип точек останова по умолчанию” на “UD2”:


Всё дело в том, что UD2 меньше обнаруживается самим VMProtect, пользуйтесь) Наверняка, если хотите, подгрузите TitanHide, но мне не пригодился.

Дело в том, что как вы могли заметить, при отладке какого-либо приложения, защищенного новой версией протектора, вы, как в старых версиях, не получаете 3-nop-исключения. Всё это происходит из-за одного трюка вмпшки, который мы с вами сейчас будем обходить. Плагины тоже не могут это обойти, т.к. вызов происходит непосредственно через SYSCALL.

Ищем все SYSCALL’s путем поиска паттерна “0F0568”, где “0F05” – сама инструкция SYSCALL, а “68” – нужен для отсеивания лишних SYSCALL’s.


Далее, устанавливаем на все наши найденные инструкции брейкпоинты.


И нажимаем “Выполнить” до тех пор, пока в регистре RAX не будет значение 0xD.

Почему 0xD? Потому что это и есть новый трюк протектора. Дело в том, что SYSCALL 0xD, это вызов WinAPI-функции “NtSetInformationThread” с константой, которая думаю вам всё скажет своим названием - “ThreadHideFromDebugger”(или же 0x11, значение лежит в регистре RDX):


Далее меняем 0x11, в регистре RDX на любое другое, но только не 0x11, будете получать результат выполнения функции в регистре RAX с ошибкой – не обращайте внимание на нее, всё хорошо ?

УДАЛЯЕМ ВСЕ ТОЧКИ ОСТАНОВА, и только после этого нажимаем “Выполнить”

Вуаля, что мы видим? Наши заветные NOP-исключения:


Секция с кодом программы расшифрована. Далее просто ставим аппаратный бряк на ваше OEP, как его искать, думаю вы знаете) Ну или WinAPI-шные функции брякайте. GetCommandLineA - ваш друг
 

Вложения

  • interium_game_patch.zip
    5,2 МБ · Просмотры: 5
D Оффлайн

deminer

Участник
LV
0
 
13.11.2023
2
0
6
24

Репутация:

В какой программе просматривалась таблица импорта?
 
Оффлайн

wlux.net

Где волчьи уши, там волчьи зубы.
Команда форума
LV
7
 
20.06.2022
23 845
218
36
Награды
10
Пол
Муж.

Репутация:

  • Автор темы
  • Администратор
  • Модератор
  • Команда форума
  • #3

Поиск по форуму

Данный сайт использует cookie. Вы должны принять их для продолжения использования. Узнать больше....