1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
  3. Данный раздел создан исключительно для релизов! Вопросы по лаунчеру или обвязке задавайте ТОЛЬКО в соответсвующей теме автора. Любые другие темы будут удалены, а авторы понесут наказание.

Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Лаунчер [C++17|Avn2]: Пишем защиту вместе! #7 Виртуализация на службе у читера

Тема в разделе "Веб-обвязки и лаунчеры", создана пользователем HoShiMin, 16 мар 2019.

  1. Автор темы
    HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    А я по тебе уже успел соскучиться!
     
  2. SaturnZero228

    SaturnZero228 Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    SaturnPvP
  3. Автор темы
    HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Ругался, ругался, а теперь просишь помощи?
    Подозреваю, что проблема в этой строчке:
    Код:
    2019-08-30 09:59:06 [SEVERE] [ForgeModLoader] FML appears to be missing any signature data. This is not a good thing
    
    Проверь свою сборку - в частности, корректность форджа.
    Не знаю, какая версия моей библиотеки там стоит, но, в любом случае, сработок нет, лог чистый.
     
    Последнее редактирование: 10 июн 2020
  4. Автор темы
    HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    #6: Защищаемся от скана памяти.

    Маленькая заметка о том, как можно было бы защититься от CheatEngine, если бы не одно но.

    Способ основан на особенностях подкачиваемой памяти и позволяет защититься от поиска по значениям и сигнатурам.

    Отдельные страницы памяти, к которым длительное время не обращался процессор, ради экономии могут быть сброшены на диск в файл подкачки, а набор страниц, размещённых в данный момент в оперативной памяти, называется "рабочим набором" процесса.

    Если страница сброшена в файл подкачки, то любое обращение к ней заставит систему загрузить страницу обратно в оперативную память. Скан памяти перебирает все страницы процесса и все сброшенные в подкачку страницы будут загружены в рабочий набор. На этом и построен детект.

    Концепция проста: с помощью VirtualAlloc выделяем страницы, за наличием которых в рабочем наборе мы будем следить. И принудительно сбрасываем эти страницы в файл подкачки функцией VirtualUnlock. Периодически проверяем наличие страниц в рабочем наборе с помощью функции QueryWorkingSetEx. Как только одна из этих страниц снова окажется в рабочем наборе (загружена в оперативную память из свопа) - значит, кто-то попытался к ней обратиться. А так как никто из нашего процесса к ней обратиться не мог - делаем вывод, что нашу память сканируют.

    Пример:
    Код:
    #include <Windows.h>
    #include <Psapi.h>
    
    class MemoryWatcher {
    private:
        PVOID m_readwrite;
        PVOID m_executable;
    public:
        MemoryWatcher()
            : m_readwrite(VirtualAlloc(NULL, USN_PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))
            , m_executable(VirtualAlloc(NULL, USN_PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE))
        {
            memset(m_readwrite, 0xAA, USN_PAGE_SIZE);
            memset(m_executable, 0xAA, USN_PAGE_SIZE);
            removeFromWorkingSet();
        }
        ~MemoryWatcher()
        {
            VirtualFree(m_readwrite, 0, MEM_RELEASE);
            VirtualFree(m_executable, 0, MEM_RELEASE);
        }
        void removeFromWorkingSet()
        {
            VirtualUnlock(m_readwrite, USN_PAGE_SIZE);
            VirtualUnlock(m_executable, USN_PAGE_SIZE);
        }
        void loadToWorkingSet()
        {
            *reinterpret_cast<ULONG*>(m_readwrite) = 0xAA;
            *reinterpret_cast<ULONG*>(m_executable) = 0xAA;
        }
        bool isAnyInWorkingSet()
        {
            PSAPI_WORKING_SET_EX_INFORMATION info[2] = {};
            info[0].VirtualAddress = m_readwrite;
            info[1].VirtualAddress = m_executable;
            BOOL status = QueryWorkingSetEx(GetCurrentProcess(), info, sizeof(info));
            if (!status) return false;
    
            for (unsigned int i = 0; i < _countof(info); ++i)
            {
                if (info[i].VirtualAttributes.Flags != 0x0D400000)
                {
                    return true;
                }
            }
    
            return false;
        }
    };
    
    ...
    
    unsigned int getSeconds()
    {
        return static_cast<unsigned int>(__rdtsc() >> 32);
    }
    
    int main()
    {
        auto time = getSeconds();
    
        MemoryWatcher watcher;
    
        while (true)
        {
            auto current = getSeconds();
            if (current - time > 1)
            {
                bool isScanned = watcher.isAnyInWorkingSet();
                if (isScanned)
                {
                    __fastfail(0);
                }
                time = current;
            }
        }
    }
    
    Однако, не всё так просто.
    Этот способ спасёт от сканирования памяти из юзермода, работающего на основе ReadProcessMemory, или от поиска сигнатур из внедрённой в процесс дллки чита. Однако, способ не будет работать на сканах памяти из ядра, т.к., в большинстве случаев, скан производится не в памяти самого процесса, а в отображении этих страниц на ядерное адресное пространство (KeStackAttachProcess -> MmProbeAndLockPages -> MmMapLockedPagesSpecifyCache) - таким образом, рабочий набор процесса не затрагивается.

    В CheatEngine режим скана из драйвера активируется в настройках (Edit -> Settings):
    upload_2020-2-28_0-39-16.png

    И, разумеется, файл подкачки может быть отключен - нужно дополнительно обрабатывать этот случай, чтобы избежать ложных срабатываний из-за того, что наши контрольные страницы всегда будут в рабочем наборе процесса.
     
    Последнее редактирование: 28 фев 2020
  5. Jok1r

    Jok1r Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Jok1r
    Спасибо за топик, очень познавательно и информативно. Будешь ли разбирать примеры защиты с помощью jni и jmvti?
     
  6. Автор темы
    HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Моя область интересов - внутреннее устройство операционок и околожелезячный уровень, а про внутреннее устройство джавы почти ничего не знаю, так что нет. По джаве пинай @NyanKa, это его вотчина.
     
  7. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Не умеет он в такое, потому его античиты блокируют всех кроме самих читаков :D.
    Себе дороже такое юзать.
     
  8. Автор темы
    HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    #7: Виртуализация на службе у читера

    upload_2020-5-31_22-32-20.png

    Развитие технологий аппаратной виртуализации (Intel VT-x и AMD-V) открывает широкие возможности по контролю выполнения кода на самом низком уровне. Привычные всем гипервизоры (Hyper-V, KVM, VMware или VirtualBox - и многие другие) позволяют запускать операционные системы в изолированном окружении: это становится возможным, благодаря способности процессоров работать в специальном режиме, в котором он может контролировать доступ к ресурсам и обрабатывать выполнение некоторых инструкций и событий.

    При наступлении заданного события процессор передаёт управление специальному обработчику - монитору виртуальных машин (VMM). Обработчик особым образом обрабатывает событие (например, эмулирует инструкцию) и отдаёт управление обратно виртуальной машине.

    Этот принцип можно использовать не только для виртуализации самостоятельных операционных систем, но и для виртуализации "живой" системы на лету, что позволит произвольным образом контролировать поведение процессора и, как следствие, обманывать механизмы защиты или, наоборот, не дать их обойти.

    Так как разработка гипервизоров - обширная тема, выходящая за рамки одной статьи, ограничимся лишь вводным экскурсом и рассмотрим виртуализацию живой системы на примере проекта Kernel-Bridge.

    Несмотря на то, что Intel VT-x (другое название VMX - Virtual Machine Extensions) и AMD-V (SVM - Secure Virtual Machine) очень сильно различаются в деталях реализации, они работают по схожему и простому принципу:
    1. В процессоре включается поддержка виртуализации.
    2. Настраивается контекст процессора (состояние регистров), с которым он выполнит первую инструкцию в виртуальном режиме (в режиме гостя).
    3. Настраивается гостевое адресное пространство (память, что будет доступна виртуальному процессору).
    4. Настраиваются события, которые требуют специальной обработки (доступ к портам, регистрам и памяти, выполнение особых инструкций и т.д.).
    5. Настраивается состояние монитора виртуальных машин (VMM), который получит управление при наступлении одного из событий, заданных в пункте 4.
    6. Процессор переводится в виртуальный режим выполнением специальной инструкции ("vmlaunch" на VT-x и "vmrun" на AMD-V) и начинает работу в настроенном гостевом окружении.

    Как только на виртуализованном процессоре происходит событие, заданное при настройке, он выходит в монитор виртуальных машин (VMM) - этот процесс называется #VMEXIT. Процессор сохраняет состояние виртуальной машины и отдаёт управление заданному обработчику. Тот обрабатывает событие (например, меняет значение регистров или содержимое памяти) и снова передаёт управление виртуальной машине.

    Основываясь на этих принципах, можно перевести все логические процессоры в виртуальный режим прозрачно для работающей системы - таким образом, что виртуальная система продолжит выполнять код хоста, находясь в общем с хостом адресном пространстве. Таким образом, это потребует минимальной настройки гипервизора:
    - Физическая память гостевого режима соотносится с физической памятью хоста один к одному (т.е., гостевой физический адрес 0x12345 будет соответствовать такому же хостовому физическому адресу 0x12345).
    - Состояние регистров гостя на момент входа в виртуальный режим задаётся равным регистрам хоста.

    С заданными начальными условиями виртуальный процессор "продолжит" выполнять за хостом его код - но уже под виртуализацией. Таким образом будет виртуализована вся операционная система.

    Детали реализации гипервизоров можно посмотреть здесь (подмена CPUID, обработка скрытия памяти).

    Пример:
    Код:
    #include <Windows.h>
    
    #include "WdkTypes.h"
    #include "CtlTypes.h"
    #include "User-Bridge.h"
    
    void* GetFuncPtr(const void* Func)
    {
        if (!Func) return nullptr;
        const auto* FuncDataPtr = reinterpret_cast<const unsigned char*>(Func);
        if (*FuncDataPtr == 0xE9)
        {
            auto Offset = *reinterpret_cast<const int*>(FuncDataPtr + 1);
            return const_cast<unsigned char*>((FuncDataPtr + 5) + Offset);
        }
        else
        {
            return const_cast<void*>(Func);
        }
    }
    
    #pragma section(".hidden", read, execute, nopage)
    __declspec(code_seg(".hidden")) unsigned int HiddenFunc()
    {
        printf("Called from the hidden func\n");
        return 0x1EE7C0DE;
    }
    
    VOID TestMemoryHiding()
    {
        using namespace Hypervisor;
        using namespace PhysicalMemory;
    
        constexpr unsigned int PageSize = 4096;
    
        // Выделяем память, на которую будем подменять нужную страницу (отдельно на чтение и запись):
        volatile PBYTE Read = reinterpret_cast<PBYTE>(VirtualAlloc(NULL, PageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE));
        volatile PBYTE Write = reinterpret_cast<PBYTE>(VirtualAlloc(NULL, PageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE));
        volatile PBYTE Execute = reinterpret_cast<PBYTE>(GetFuncPtr(HiddenFunc));
    
        // Предотвратим сброс страниц в своп:
        VirtualLock(Read, PageSize);
        VirtualLock(Write, PageSize);
        VirtualLock(Execute, PageSize);
    
        // Заполним подменные страницы данными, которые будут показываться на чтение и запись:
        memset(Read, 0xFF, PageSize);
        memset(Write, 0xEE, PageSize);
    
        // Получим физические адреса всех страниц:
        WdkTypes::PVOID64 ReadPa = 0, WritePa = 0, ExecutePa = 0;
        KbGetPhysicalAddress(NULL, reinterpret_cast<WdkTypes::PVOID>(Read), &ReadPa);
        KbGetPhysicalAddress(NULL, reinterpret_cast<WdkTypes::PVOID>(Write), &WritePa);
        KbGetPhysicalAddress(NULL, reinterpret_cast<WdkTypes::PVOID>(Execute), &ExecutePa);
     
        // Установим на чтение и запись подменные страницы, на исполнение - оригинал:
        KbVmmInterceptPage(ExecutePa, ReadPa, WritePa, ExecutePa);
        HiddenFunc(); // Проверим
        KbVmmDeinterceptPage(ExecutePa);
    
        VirtualUnlock(Execute, PageSize);
        VirtualUnlock(Write, PageSize);
        VirtualUnlock(Read, PageSize);
    
        VirtualFree(Write, 0, MEM_RELEASE);
        VirtualFree(Read, 0, MEM_RELEASE);
    }
    
    void PrintCpuid()
    {
        int regs[4] = {};
        __cpuid(regs, 0);
        char str[13] = {};
        // CPUID Vendor = RBX + RDX + RCX:
        *(int*)(str + 0) = regs[1]; // RBX
        *(int*)(str + 4) = regs[3]; // RDX
        *(int*)(str + 8) = regs[2]; // RCX
        printf("CPU: %s\r\n", str);
    }
    
    int main()
    {
        if (KbLoader::KbLoadAsFilter(
            L"C:\\Temp\\Kernel-Bridge\\Kernel-Bridge.sys",
            L"260000" // Altitude of minifilter
        )) {
            if (Hypervisor::KbVmmEnable())
            {
                PrintCpuid();
                TestMemoryHiding();
                Hypervisor::KbVmmDisable();
            }
            KbLoader::KbUnload();
        }
    
        return 0;
    }
    
    Vmm.gif

    Что в итоге?
    С помощью виртуализации можно скрывать перехваты (программа будет видеть одно, а исполнять - другое) и целые модули (например, для потоков защиты память будет невидима), подменять CPUID, заставлять процесс выполнять недоверенный код. Можно обойти PatchGuard (система проверки целостности кода ядра Windows) и перехватывать функции в ядре. Можно придумывать собственные машинные инструкции и реализовывать их произвольное поведение. Возможности ограничены лишь фантазией.

    А что с защитой? Те же самые средства можно направить и на защиту: например, сделать всю память процесса недоступной для процессов извне. Таким образом, процесс будет работать в изолированном анклаве, доступ к которому извне (например, с помощью CheatEngine) получить будет невозможно. Или, обрабатывая отладочные прерывания, сделать невозможной отладку.

    Time to choose.
     
  9. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    vmprotect так работает.
     
  10. Автор темы
    HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Принцип похожий, разница лишь в том, что он софтверный (визор без приставки "гипер") и защищает только от реверсинга, и больше ни от чего.
     
  11. yawik74082

    yawik74082 Ньюби

    Баллы:
    1
    А как поставить эту длл и где её скачать
     
  12. Xedosyatko

    Xedosyatko Новичок

    Баллы:
    6
    С чего такой вывод? Он защищает от всех пабликовских и многих приватных JNI/JVMTI обходов, защищает от патчей в кодовых секциях модулей джавы (с чем эйвон не справляется, он в целом ни с чем не справляется, многие админы приобретали XSGuard из-за того, что эйвон ни от чего не спасал, даже от банального LoadLibrary, хоть и эйвон позиционируется как анти-инжект, который обходится в один клик).
     
  13. Автор темы
    HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Значит, я ошибся и у тебя действительно хорошая защита
     
  14. Devindel

    Devindel Участник

    Баллы:
    31
    Имя в Minecraft:
    Devindel
    Здравствуйте , нам надо сделать сайт и лаунчер (любой) , я сам пытался но получилось. Если бы вы помогли был бы очень благодарен, давайте всё обсудим в дс Dan Yer64#1720
     
  15. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Ты не по адресу пришел.
     
  16. Devindel

    Devindel Участник

    Баллы:
    31
    Имя в Minecraft:
    Devindel
    То закрытая тема .
     
  17. R.G.SL!M

    R.G.SL!M Активный участник Пользователь

    Баллы:
    88
    Имя в Minecraft:
    SlimRG
    Хочется услышать насчет обфускации с виртуализацией типа vmware thinapp + themida
     
  18. Автор темы
    HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Слишком широкий вопрос.
    Виртуализация в темиде никак не связана с аппаратной виртуализацией и с эмуляцией системных ресурсов, как в ThinApp
     
  19. Дмитрий keka_VAC

    Дмитрий keka_VAC Активный участник Пользователь

    Баллы:
    76
    Имя в Minecraft:
    Cake_progress
    Хошик сдох бадабумц..[​IMG]
     
  20. Santa

    Santa Активный участник Пользователь

    Баллы:
    76
    Имя в Minecraft:
    Jewish_Cat
    спасибо за udav лаунчер, который с ****нной защитой(без соглашения пользователя позволяет делать скриншоты, ****ить данные и прочее). 10 из 10 шакалов
     

Поделиться этой страницей