[C++] Hook Scanner

Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Привет форумчане.

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

По тому предоставляю самописный аналог:
Вариант еще очень сырой, однако будет дорабатываться. Тем, кто не знает зачем это нужно: просто пройдите мимо темы. Собрано из подручных средств вчера вечером, класс воялся на скорую руку.
cUtilit.h:
Код:
#pragma once
typedef std::vector<unsigned char>                      vByte;

#define INRANGE(x,a,b)        (x >= a && x <= b)
#define getBits( x )        (INRANGE(x,'0','9') ? (x - '0') : ((x&(~0x20)) - 'A' + 0xa))
#define getByte( x )        (getBits(x[0]) << 4 | getBits(x[1]))

#define LAST_STATUS_OFS (0x598 + 0x197 * (sizeof(void*)))
#define STATUS_SUCCESS                   ((NTSTATUS)0x00000000L)
inline NTSTATUS LastNtStatus()
{
    return *(NTSTATUS*)((unsigned char*)NtCurrentTeb() + LAST_STATUS_OFS);
}
class cUtilit
{
public:
    static NTSTATUS  Priviledge(const std::basic_string<TCHAR>& name = SE_DEBUG_NAME)
    {
        TOKEN_PRIVILEGES Priv, PrivOld;
        DWORD cbPriv = sizeof(PrivOld);
        HANDLE hToken;

        if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, FALSE, &hToken))
        {
            if (GetLastError() != ERROR_NO_TOKEN)
                return LastNtStatus();

            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
                return LastNtStatus();
        }

        Priv.PrivilegeCount = 1;
        Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        LookupPrivilegeValue(NULL, name.c_str(), &Priv.Privileges[0].Luid);

        if (!AdjustTokenPrivileges(hToken, FALSE, &Priv, sizeof(Priv), &PrivOld, &cbPriv))
        {
            CloseHandle(hToken);
            return LastNtStatus();
        }

        if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
        {
            CloseHandle(hToken);
            return LastNtStatus();
        }

        return STATUS_SUCCESS;
    }
};
Класс cProcess: (урезаная версия класса Крайслер , что первое под руку попало)
cProcess.h:
Код:
#pragma once
#include <windows.h>
#include <vector>
#include <tlhelp32.h>
#include <dwmapi.h>
#include <psapi.h>
#pragma comment(lib, "dwmapi.lib")
#include "cModule.h"
#include "cUtilit.h"

class cProcess
{
public:
    cProcess();
    ~cProcess();
    bool                        Attach(HANDLE hProcess);
    void                        Detach();
    cModule*                    GetModule(const std::string&);
    HANDLE                        GetHandle() const;
    std::vector<cModule*>       GetModuleList() const;
    bool                        IsValidHandle() const;
    bool                        valid();
    DWORD                       GetProcessIdByName(const std::string&);
private:
    bool                        DumpModList();
    int                         SizeOfArray(char *);
private:
    HANDLE                        m_hProcess = NULL;
    std::vector<cModule*>        m_pModList;
};
cProcess.cpp:
Код:
#include "cProcess.h"

cProcess::cProcess()
{
    cUtilit::Priviledge();
}
bool cProcess::Attach(HANDLE hProcess)
{
    Detach();

    m_hProcess = hProcess;

    if (!m_hProcess)
        return false;

    return DumpModList();
}
void cProcess::Detach()
{
    if (m_hProcess)
        CloseHandle(m_hProcess);

    m_hProcess = NULL;

    if (!m_pModList.empty())
    {
        for (auto& slot : m_pModList)
        {
            delete slot;
            slot = nullptr;
        }
    }
}

bool cProcess::DumpModList()
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetProcessId(this->m_hProcess));

    if (hSnapshot == INVALID_HANDLE_VALUE)
        return false;


    MODULEENTRY32 Entry = { NULL };

    Entry.dwSize = sizeof(MODULEENTRY32);

    if (!Module32First(hSnapshot, &Entry))
    {
        CloseHandle(hSnapshot);
        return false;
    }

    cModule* pMod = nullptr;

    do {
        char szPath[MAX_PATH] = { NULL };

        GetModuleFileNameEx(m_hProcess, Entry.hModule, szPath, MAX_PATH);

        pMod = new cModule((DWORD_PTR)Entry.hModule, (DWORD_PTR)Entry.modBaseSize, Entry.szModule, szPath);
        m_pModList.push_back(pMod);

    } while (Module32Next(hSnapshot, &Entry));
    CloseHandle(hSnapshot);
    return !m_pModList.empty();
}
DWORD cProcess::GetProcessIdByName(const std::string& szNameExe)
{
    HANDLE hSnap;
    DWORD pId = 0;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);

    try {
        hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (!hSnap) {
            throw std::exception("Could not create process snapshot");
        }

        if (!Process32First(hSnap, &pe32)) {
            throw std::exception("Enumerating processes failed");
        }

        do {
            if (std::string(pe32.szExeFile) == szNameExe) {
                pId = pe32.th32ProcessID;
                break;
            }
        } while (Process32Next(hSnap, &pe32));

        CloseHandle(hSnap);
        return pId;
    }
    catch (std::exception e) {
        CloseHandle(hSnap);
        throw;
    }
}

cModule* cProcess::GetModule(const std::string& ImageName)
{
    if (m_pModList.empty())
        return nullptr;

    for (auto& pMod : m_pModList)
    {
        if (ImageName.compare(pMod->GetName()) == 0)
        {
            return pMod;
        }
    }
    return nullptr;
}
HANDLE cProcess::GetHandle() const
{
    return m_hProcess;
}
bool cProcess::IsValidHandle() const
{
    return m_hProcess != INVALID_HANDLE_VALUE;
}
bool cProcess::valid()
{
    DWORD dwExitCode = 0;

    if (!m_hProcess || !GetExitCodeProcess(m_hProcess, &dwExitCode))
        return false;

    return (dwExitCode == STILL_ACTIVE);
}
std::vector<cModule*>  cProcess::GetModuleList() const
{
    return m_pModList;
}

int  cProcess::SizeOfArray(char *chArray)
{
    for (int iLength = 1; iLength < MAX_PATH; iLength++)
        if (chArray[iLength] == '\0')
            return iLength;


    return 0;
}

cProcess::~cProcess()
{
}
Класс cModule:
cModule.h:
Код:
#pragma once
#include <windows.h>
#include <string>

class cModule
{
public:
    cModule(DWORD_PTR, DWORD_PTR, const std::string&, const std::string&);
    ~cModule();
    DWORD_PTR            GetImage() const;
    DWORD_PTR            GetSize() const;
    const std::string&    GetName() const;
    const std::string&    GetPath() const;
    
private:
    DWORD_PTR            m_ImageBase;
    DWORD_PTR            m_ImageSize;
    std::string            m_ImageName;
    std::string            m_ImagePath;
};
cModule.cpp:
Код:
#include "cModule.h"



cModule::cModule(DWORD_PTR ImageBase, DWORD_PTR ImageSize, const std::string& ImageName, const std::string& ImagePath)
    : m_ImageBase(ImageBase),
      m_ImageSize(ImageSize),
      m_ImageName(ImageName),
      m_ImagePath(ImagePath)
{
}
DWORD_PTR cModule::GetImage() const
{
    return m_ImageBase;
}

DWORD_PTR cModule::GetSize() const
{
    return m_ImageSize;
}

const std::string& cModule::GetName() const
{
    return m_ImageName;
}

const std::string& cModule::GetPath() const
{
    return m_ImagePath;
}

cModule::~cModule()
{
}
И собственно сам класс сканирования:
Scaner.h:
Код:
#include <Windows.h>

#include <string>
#include <vector>

using namespace std;

#include "cProcess.h"

typedef struct hHookData
{
    DWORD api_address;
    DWORD api_size;

    void* api_buffer_get;
    void* api_buffer_set;

    hHookData(DWORD _address, DWORD _size, void* _buffer_get, void* _buffer_set) : api_address(_address), api_size(_size), api_buffer_get(_buffer_get), api_buffer_set(_buffer_set)
    {

    }
};

typedef struct _export_data
{
    FARPROC api_call;
    char* api_name;

    _export_data(FARPROC _call, char* _name) : api_call(_call), api_name(_name)
    {

    }
};

#define S_SUCCRESS(a) a != NULL

class Scanner
{
public:
    Scanner();
    Scanner(cProcess* g_pProcess);
    ~Scanner();

    hHookData* GetExternalData(std::string NameOfModule, std::string NameOfFunction, DWORD size);
    vector<hHookData*> ScanExternalModule(std::string NameOfModule, DWORD size);

private:
    FARPROC find_function(HMODULE Mod, const char* fName);
    vector<_export_data*> query_function_list(HMODULE Mod);
private:
    cProcess* vProcess;
};
Scanner.cpp:
Код:
#include "Scanner.h"
Scanner::Scanner()
{
    this->vProcess = nullptr;
}
Scanner::Scanner(cProcess* g_pProcess)
{
    this->vProcess = g_pProcess;
}

Scanner::~Scanner()
{
}

FARPROC Scanner::find_function(HMODULE Mod, const char* fName)
{
    ULONG  uReturn = 0;
    USHORT strTMP = 0;
    USHORT tmpINDEX;
    char * tmpName;
    ULONG Adress;

    if ((ULONG)fName <= 0xFFFF)
        strTMP = (USHORT)fName;

    if (Mod)
    {
        ULONG Portable_Executable = *(ULONG*)((ULONG)Mod + 0x3C) + (ULONG)Mod;
        PIMAGE_EXPORT_DIRECTORY EXPORT_DIRECTORY = (PIMAGE_EXPORT_DIRECTORY)(*(ULONG*)((ULONG)Portable_Executable + 0x78) + (ULONG)Mod);
        PULONG RVAPointer = (ULONG*)(EXPORT_DIRECTORY->AddressOfNames + (ULONG)Mod);
        PUSHORT oTb_RVA = (USHORT*)(EXPORT_DIRECTORY->AddressOfNameOrdinals + (ULONG)Mod);
        PULONG dwTbRVA = (ULONG*)(EXPORT_DIRECTORY->AddressOfFunctions + (ULONG)Mod);

        ULONG size_CNT = (EXPORT_DIRECTORY->NumberOfNames > EXPORT_DIRECTORY->NumberOfFunctions) ? EXPORT_DIRECTORY->NumberOfNames : EXPORT_DIRECTORY->NumberOfFunctions;

        for (USHORT i = 0; i < size_CNT; i++)
        {
            if (i < EXPORT_DIRECTORY->NumberOfFunctions)
            {
                tmpName = (char*)(RVAPointer[i] + (ULONG)Mod);
                tmpINDEX = oTb_RVA[i];
            }
            else
            {
                tmpName = 0;
                tmpINDEX = i;
            }
            Adress = dwTbRVA[tmpINDEX] + (ULONG)Mod;
            if ((strTMP == tmpINDEX + EXPORT_DIRECTORY->Base) || (tmpName && !strcmp(tmpName, fName))) // wcscmp
            {
                uReturn = Adress;
                break;
            }
        }
    }
    return reinterpret_cast<FARPROC>(uReturn);
}

vector<_export_data*> Scanner::query_function_list(HMODULE Mod)
{
    vector<_export_data*> t3Vector;

    ULONG  uReturn = 0;
    USHORT strTMP = 0;
    USHORT tmpINDEX;
    char * tmpName;
    ULONG Adress;

    if (Mod)
    {
        ULONG Portable_Executable = *(ULONG*)((ULONG)Mod + 0x3C) + (ULONG)Mod;
        PIMAGE_EXPORT_DIRECTORY EXPORT_DIRECTORY = (PIMAGE_EXPORT_DIRECTORY)(*(ULONG*)((ULONG)Portable_Executable + 0x78) + (ULONG)Mod);
        PULONG RVAPointer = (ULONG*)(EXPORT_DIRECTORY->AddressOfNames + (ULONG)Mod);
        PUSHORT oTb_RVA = (USHORT*)(EXPORT_DIRECTORY->AddressOfNameOrdinals + (ULONG)Mod);
        PULONG dwTbRVA = (ULONG*)(EXPORT_DIRECTORY->AddressOfFunctions + (ULONG)Mod);

        ULONG size_CNT = (EXPORT_DIRECTORY->NumberOfNames > EXPORT_DIRECTORY->NumberOfFunctions) ? EXPORT_DIRECTORY->NumberOfNames : EXPORT_DIRECTORY->NumberOfFunctions;

        for (USHORT i = 0; i < size_CNT; i++)
        {
            if (i < EXPORT_DIRECTORY->NumberOfFunctions)
            {
                tmpName = (char*)(RVAPointer[i] + (ULONG)Mod);
                tmpINDEX = oTb_RVA[i];
            }
            else
            {
                tmpName = 0;
                tmpINDEX = i;
            }
            Adress = dwTbRVA[tmpINDEX] + (ULONG)Mod;
            t3Vector.push_back(new _export_data(reinterpret_cast<FARPROC>(Adress), tmpName));
        }
    }
    return t3Vector;
}

hHookData* Scanner::GetExternalData(std::string NameOfModule, std::string NameOfFunction, DWORD size)
{
    hHookData* Data = nullptr;

    HMODULE m_pModule = GetModuleHandleA(NameOfModule.c_str());
    cModule* g_pModule = this->vProcess->GetModule(NameOfModule);

    if (S_SUCCRESS(m_pModule) && S_SUCCRESS(g_pModule))
    {
        FARPROC m_pFunction = this->find_function(m_pModule, NameOfFunction.c_str());

        if (S_SUCCRESS(m_pFunction))
        {
            void* hLocalBuffer = malloc(size);
            void* hExternalBuffer = malloc(size);

            if (S_SUCCRESS(hLocalBuffer) && S_SUCCRESS(hExternalBuffer))
            {
                DWORD dwOldProtect = 0;

                VirtualProtectEx(GetCurrentProcess(), m_pFunction, size, PAGE_EXECUTE_READ, &dwOldProtect);
                ReadProcessMemory(GetCurrentProcess(), m_pFunction, hLocalBuffer, size, 0);
                VirtualProtectEx(GetCurrentProcess(), m_pFunction, size, dwOldProtect, &dwOldProtect);

                VirtualProtectEx(this->vProcess->GetHandle(), m_pFunction, size, PAGE_EXECUTE_READ, &dwOldProtect);
                ReadProcessMemory(this->vProcess->GetHandle(), m_pFunction, hExternalBuffer, size, 0);
                VirtualProtectEx(this->vProcess->GetHandle(), m_pFunction, size, dwOldProtect, &dwOldProtect);

                if (memcmp(hLocalBuffer, hExternalBuffer, size) == 0)
                {
                    free(hLocalBuffer);
                    free(hExternalBuffer);
                }
                else
                {
                    Data = new hHookData(reinterpret_cast<DWORD>(m_pFunction), size, hLocalBuffer, hExternalBuffer);
                }
            }
        }
    }

    return Data;
}

vector<hHookData*> Scanner::ScanExternalModule(std::string NameOfModule, DWORD size)
{
    vector<hHookData*> Data;

    HMODULE m_pModule = GetModuleHandleA(NameOfModule.c_str());
    cModule* g_pModule = this->vProcess->GetModule(NameOfModule);

    if (S_SUCCRESS(m_pModule) && S_SUCCRESS(g_pModule))
    {
        vector<_export_data*> m_pFunctionList = this->query_function_list(m_pModule);

        if (S_SUCCRESS(m_pFunctionList.size()))
        {
            for (_export_data* data : m_pFunctionList)
            {
                if (S_SUCCRESS(data->api_call) && S_SUCCRESS(data->api_name))
                {
                    void* hLocalBuffer = malloc(size);
                    void* hExternalBuffer = malloc(size);

                    if (S_SUCCRESS(hLocalBuffer) && S_SUCCRESS(hExternalBuffer))
                    {
                        DWORD dwOldProtect = 0;

                        VirtualProtectEx(GetCurrentProcess(), data->api_call, size, PAGE_EXECUTE_READ, &dwOldProtect);
                        ReadProcessMemory(GetCurrentProcess(), data->api_call, hLocalBuffer, size, 0);
                        VirtualProtectEx(GetCurrentProcess(), data->api_call, size, dwOldProtect, &dwOldProtect);

                        VirtualProtectEx(this->vProcess->GetHandle(), data->api_call, size, PAGE_EXECUTE_READ, &dwOldProtect);
                        ReadProcessMemory(this->vProcess->GetHandle(), data->api_call, hExternalBuffer, size, 0);
                        VirtualProtectEx(this->vProcess->GetHandle(), data->api_call, size, dwOldProtect, &dwOldProtect);

                        if (memcmp(hLocalBuffer, hExternalBuffer, size) == 0)
                        {
                            free(hLocalBuffer);
                            free(hExternalBuffer);
                        }
                        else
                        {
                            Data.push_back(new hHookData(reinterpret_cast<DWORD>(data->api_call), size, hLocalBuffer, hExternalBuffer));
                        }
                    }
                }
            }
        }
    }

    return Data;
}
Пример использования:
Код:
int main()
{

    cProcess* g_pProcess = new cProcess;
    
    DWORD PID = g_pProcess->GetProcessIdByName("process.exe");

    if (PID > 0)
    {
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);

        if (hProcess)
        {
            g_pProcess->Attach(hProcess);

            Scanner g_pScanner = Scanner(g_pProcess);

            hHookData* getData = g_pScanner.GetExternalData("kernel32.dll", "LoadLibraryA", 5);
            if (getData != nullptr)
            {
                //стоит хук
            }
            else
            {
                //Хука нет.
            }

            vector<hHookData*> Hooks = g_pScanner.ScanExternalModule("kernel32.dll", 5);
            //выведет все хуки найденные в kernel32.dll если они есть.
            //размеры естественно указывать руками, минимум 5 для тамполайна x32 и минимум 12 для x64
            for (hHookData* Data : Hooks)
            {
                printf("find hook: 0x%X size: %d\n", Data->api_address, Data->api_size);
            }

            printf("Hooks Len: %d\n", Hooks.size());

            system("pause");
        }
    }

    g_pProcess->Detach();
    delete g_pProcess;

    return 0;
}
 
Разработчик
Статус
Оффлайн
Регистрация
23 Авг 2017
Сообщения
171
Реакции[?]
474
Поинты[?]
1K
Ну такое, пойдёт только для каких нибудь юзеллес античтов, которые только и делают что хукают тот же LoadLibrary (с которым инжектят в 2018 только пастеры или люди с отклонением в развитии).
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Ну такое, пойдёт только для каких нибудь юзеллес античтов, которые только и делают что хукают тот же LoadLibrary (с которым инжектят в 2018 только пастеры или люди с отклонением в развитии).
Ты может удивишься, но многие до сих пор хукают LdrLoadDll, RtlUserThreadStart и прочее из nt плюх... Тот же FaceIt/BattlEye/Многие версии xTrap/GameGuard от части. Еще хукают CreateProcess чтобы дескриптор создаваемого процесса не перехватили на старте и не модифицировали, очень много античитов еще юзают хуки))) просто никто не это не смотрит практически и большинство на iat/eat переехало.
 
Разработчик
Статус
Оффлайн
Регистрация
23 Авг 2017
Сообщения
171
Реакции[?]
474
Поинты[?]
1K
Ты может удивишься, но многие до сих пор хукают LdrLoadDll, RtlUserThreadStart и прочее из nt плюх... Тот же FaceIt/BattlEye/Многие версии xTrap/GameGuard от части. Еще хукают CreateProcess чтобы дескриптор создаваемого процесса не перехватили на старте и не модифицировали, очень много античитов еще юзают хуки))) просто никто не это не смотрит практически и большинство на iat/eat переехало.
Я понимаю, что юзают, но помимо этого юзают и другие технологии для обнаружения. Я о том что это чудо (которое почему то по ебанутому написано, зачем к примеру юзать VirtualProtectEx и ReadProcessMemory в своём же процессе, ну да ладно, это мелочи) - может отключить лишь часть защиты, и то незначительную, и только если правильно воспользоваться сие модулем. Я в плане толку от того, что ты узнаешь, стоят ли хуки?
Но в целом модуль полезный, главное правильно его использовать, ибо он подойдёт только для изучения работы античита, но никак не для его обхода.

P.S. Уже есть тулзы которые палят все хуки в процессе, так что не знаю зачем этот велосипед, но за сорс готового решения спасибо.
 
Последнее редактирование:
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Я понимаю, что юзают, но помимо этого юзают и другие технологии для обнаружения. Я о том что это чудо (которое почему то по ебанутому написано, зачем к примеру юзать VirtualProtectEx и ReadProcessMemory в своём же процессе, ну да ладно, это мелочи
по схожему принципу можно написать чтение iat/eat/hardware, VirtualProtectEx и ReadProcessMemory в своём же процессе - так надо.
может отключить лишь часть защиты, и то незначительную, и только если правильно воспользоваться сие модулем.
нужно обходить только детектирование узких частей которые отрезают тебе возможности инжекта/мапа модуля/создания потока, всю защиту отключать и не нужно.
Я Я в плане толку от того, что ты узнаешь, стоят ли хуки?
я узнаю в какие рамки античит пытается загнать мои действия и как из этих рамок выйти.
 
Премиум
Статус
Оффлайн
Регистрация
25 Авг 2017
Сообщения
557
Реакции[?]
220
Поинты[?]
0
Ты может удивишься, но многие до сих пор хукают LdrLoadDll, RtlUserThreadStart и прочее из nt плюх... Тот же FaceIt/BattlEye/Многие версии xTrap/GameGuard от части. Еще хукают CreateProcess чтобы дескриптор создаваемого процесса не перехватили на старте и не модифицировали, очень много античитов еще юзают хуки))) просто никто не это не смотрит практически и большинство на iat/eat переехало.
xTrap хукает LdrLoadDll? Серьезно?
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
xTrap хукает LdrLoadDll? Серьезно?
я видел версии которые это делали на латиноамериканском клиенте пб (кайбо), у них там на клиенте больше 100 хуков в r3 весело от модуля xTrap в сборке 2к15, потом античит сменили на XignCode 2к16 из бюджетных соображений. А знатока мне загонять не надо, я в глаза не долбился и прекрасно знаю что пишу.
 
Разработчик
Статус
Оффлайн
Регистрация
23 Авг 2017
Сообщения
171
Реакции[?]
474
Поинты[?]
1K
по схожему принципу можно написать чтение iat/eat/hardware, VirtualProtectEx и ReadProcessMemory в своём же процессе - так надо.
Ну можно было хотя бы VirtualProtect заюзать, и то я не думаю что в таких местах нет прав на чтение, ты ведь просто сравниваешь память в своём процессе, с чужим, ну да ладно, это мой перфекционизм уже доёбывается, главное что бы код работал. (Или я чего то не понимаю и так реально надо? Просто интересно)

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

Ну а вообще, как по мне, лучший метод обхода - это подмена информации в пакетах :kappa:
 
Забаненный
Статус
Оффлайн
Регистрация
12 Май 2017
Сообщения
375
Реакции[?]
11
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Привет форумчане.

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

По тому предоставляю самописный аналог:
cUtilit.h:
Код:
#pragma once
typedef std::vector<unsigned char>                      vByte;

#define INRANGE(x,a,b)        (x >= a && x <= b)
#define getBits( x )        (INRANGE(x,'0','9') ? (x - '0') : ((x&(~0x20)) - 'A' + 0xa))
#define getByte( x )        (getBits(x[0]) << 4 | getBits(x[1]))

#define LAST_STATUS_OFS (0x598 + 0x197 * (sizeof(void*)))
#define STATUS_SUCCESS                   ((NTSTATUS)0x00000000L)
inline NTSTATUS LastNtStatus()
{
    return *(NTSTATUS*)((unsigned char*)NtCurrentTeb() + LAST_STATUS_OFS);
}
class cUtilit
{
public:
    static NTSTATUS  Priviledge(const std::basic_string<TCHAR>& name = SE_DEBUG_NAME)
    {
        TOKEN_PRIVILEGES Priv, PrivOld;
        DWORD cbPriv = sizeof(PrivOld);
        HANDLE hToken;

        if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, FALSE, &hToken))
        {
            if (GetLastError() != ERROR_NO_TOKEN)
                return LastNtStatus();

            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
                return LastNtStatus();
        }

        Priv.PrivilegeCount = 1;
        Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        LookupPrivilegeValue(NULL, name.c_str(), &Priv.Privileges[0].Luid);

        if (!AdjustTokenPrivileges(hToken, FALSE, &Priv, sizeof(Priv), &PrivOld, &cbPriv))
        {
            CloseHandle(hToken);
            return LastNtStatus();
        }

        if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
        {
            CloseHandle(hToken);
            return LastNtStatus();
        }

        return STATUS_SUCCESS;
    }
};
Класс cProcess: (урезаная версия класса Крайслер , что первое под руку попало)
cProcess.h:
Код:
#pragma once
#include <windows.h>
#include <vector>
#include <tlhelp32.h>
#include <dwmapi.h>
#include <psapi.h>
#pragma comment(lib, "dwmapi.lib")
#include "cModule.h"
#include "cUtilit.h"

class cProcess
{
public:
    cProcess();
    ~cProcess();
    bool                        Attach(HANDLE hProcess);
    void                        Detach();
    cModule*                    GetModule(const std::string&);
    HANDLE                        GetHandle() const;
    std::vector<cModule*>       GetModuleList() const;
    bool                        IsValidHandle() const;
    bool                        valid();
    DWORD                       GetProcessIdByName(const std::string&);
private:
    bool                        DumpModList();
    int                         SizeOfArray(char *);
private:
    HANDLE                        m_hProcess = NULL;
    std::vector<cModule*>        m_pModList;
};
cProcess.cpp:
Код:
#include "cProcess.h"

cProcess::cProcess()
{
    cUtilit::Priviledge();
}
bool cProcess::Attach(HANDLE hProcess)
{
    Detach();

    m_hProcess = hProcess;

    if (!m_hProcess)
        return false;

    return DumpModList();
}
void cProcess::Detach()
{
    if (m_hProcess)
        CloseHandle(m_hProcess);

    m_hProcess = NULL;

    if (!m_pModList.empty())
    {
        for (auto& slot : m_pModList)
        {
            delete slot;
            slot = nullptr;
        }
    }
}

bool cProcess::DumpModList()
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetProcessId(this->m_hProcess));

    if (hSnapshot == INVALID_HANDLE_VALUE)
        return false;


    MODULEENTRY32 Entry = { NULL };

    Entry.dwSize = sizeof(MODULEENTRY32);

    if (!Module32First(hSnapshot, &Entry))
    {
        CloseHandle(hSnapshot);
        return false;
    }

    cModule* pMod = nullptr;

    do {
        char szPath[MAX_PATH] = { NULL };

        GetModuleFileNameEx(m_hProcess, Entry.hModule, szPath, MAX_PATH);

        pMod = new cModule((DWORD_PTR)Entry.hModule, (DWORD_PTR)Entry.modBaseSize, Entry.szModule, szPath);
        m_pModList.push_back(pMod);

    } while (Module32Next(hSnapshot, &Entry));
    CloseHandle(hSnapshot);
    return !m_pModList.empty();
}
DWORD cProcess::GetProcessIdByName(const std::string& szNameExe)
{
    HANDLE hSnap;
    DWORD pId = 0;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);

    try {
        hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (!hSnap) {
            throw std::exception("Could not create process snapshot");
        }

        if (!Process32First(hSnap, &pe32)) {
            throw std::exception("Enumerating processes failed");
        }

        do {
            if (std::string(pe32.szExeFile) == szNameExe) {
                pId = pe32.th32ProcessID;
                break;
            }
        } while (Process32Next(hSnap, &pe32));

        CloseHandle(hSnap);
        return pId;
    }
    catch (std::exception e) {
        CloseHandle(hSnap);
        throw;
    }
}

cModule* cProcess::GetModule(const std::string& ImageName)
{
    if (m_pModList.empty())
        return nullptr;

    for (auto& pMod : m_pModList)
    {
        if (ImageName.compare(pMod->GetName()) == 0)
        {
            return pMod;
        }
    }
    return nullptr;
}
HANDLE cProcess::GetHandle() const
{
    return m_hProcess;
}
bool cProcess::IsValidHandle() const
{
    return m_hProcess != INVALID_HANDLE_VALUE;
}
bool cProcess::valid()
{
    DWORD dwExitCode = 0;

    if (!m_hProcess || !GetExitCodeProcess(m_hProcess, &dwExitCode))
        return false;

    return (dwExitCode == STILL_ACTIVE);
}
std::vector<cModule*>  cProcess::GetModuleList() const
{
    return m_pModList;
}

int  cProcess::SizeOfArray(char *chArray)
{
    for (int iLength = 1; iLength < MAX_PATH; iLength++)
        if (chArray[iLength] == '\0')
            return iLength;


    return 0;
}

cProcess::~cProcess()
{
}
Класс cModule:
cModule.h:
Код:
#pragma once
#include <windows.h>
#include <string>

class cModule
{
public:
    cModule(DWORD_PTR, DWORD_PTR, const std::string&, const std::string&);
    ~cModule();
    DWORD_PTR            GetImage() const;
    DWORD_PTR            GetSize() const;
    const std::string&    GetName() const;
    const std::string&    GetPath() const;
   
private:
    DWORD_PTR            m_ImageBase;
    DWORD_PTR            m_ImageSize;
    std::string            m_ImageName;
    std::string            m_ImagePath;
};
cModule.cpp:
Код:
#include "cModule.h"



cModule::cModule(DWORD_PTR ImageBase, DWORD_PTR ImageSize, const std::string& ImageName, const std::string& ImagePath)
    : m_ImageBase(ImageBase),
      m_ImageSize(ImageSize),
      m_ImageName(ImageName),
      m_ImagePath(ImagePath)
{
}
DWORD_PTR cModule::GetImage() const
{
    return m_ImageBase;
}

DWORD_PTR cModule::GetSize() const
{
    return m_ImageSize;
}

const std::string& cModule::GetName() const
{
    return m_ImageName;
}

const std::string& cModule::GetPath() const
{
    return m_ImagePath;
}

cModule::~cModule()
{
}
И собственно сам класс сканирования:
Scaner.h:
Код:
#include <Windows.h>

#include <string>
#include <vector>

using namespace std;

#include "cProcess.h"

typedef struct hHookData
{
    DWORD api_address;
    DWORD api_size;

    void* api_buffer_get;
    void* api_buffer_set;

    hHookData(DWORD _address, DWORD _size, void* _buffer_get, void* _buffer_set) : api_address(_address), api_size(_size), api_buffer_get(_buffer_get), api_buffer_set(_buffer_set)
    {

    }
};

typedef struct _export_data
{
    FARPROC api_call;
    char* api_name;

    _export_data(FARPROC _call, char* _name) : api_call(_call), api_name(_name)
    {

    }
};

#define S_SUCCRESS(a) a != NULL

class Scanner
{
public:
    Scanner();
    Scanner(cProcess* g_pProcess);
    ~Scanner();

    hHookData* GetExternalData(std::string NameOfModule, std::string NameOfFunction, DWORD size);
    vector<hHookData*> ScanExternalModule(std::string NameOfModule, DWORD size);

private:
    FARPROC find_function(HMODULE Mod, const char* fName);
    vector<_export_data*> query_function_list(HMODULE Mod);
private:
    cProcess* vProcess;
};
Scanner.cpp:
Код:
#include "Scanner.h"
Scanner::Scanner()
{
    this->vProcess = nullptr;
}
Scanner::Scanner(cProcess* g_pProcess)
{
    this->vProcess = g_pProcess;
}

Scanner::~Scanner()
{
}

FARPROC Scanner::find_function(HMODULE Mod, const char* fName)
{
    ULONG  uReturn = 0;
    USHORT strTMP = 0;
    USHORT tmpINDEX;
    char * tmpName;
    ULONG Adress;

    if ((ULONG)fName <= 0xFFFF)
        strTMP = (USHORT)fName;

    if (Mod)
    {
        ULONG Portable_Executable = *(ULONG*)((ULONG)Mod + 0x3C) + (ULONG)Mod;
        PIMAGE_EXPORT_DIRECTORY EXPORT_DIRECTORY = (PIMAGE_EXPORT_DIRECTORY)(*(ULONG*)((ULONG)Portable_Executable + 0x78) + (ULONG)Mod);
        PULONG RVAPointer = (ULONG*)(EXPORT_DIRECTORY->AddressOfNames + (ULONG)Mod);
        PUSHORT oTb_RVA = (USHORT*)(EXPORT_DIRECTORY->AddressOfNameOrdinals + (ULONG)Mod);
        PULONG dwTbRVA = (ULONG*)(EXPORT_DIRECTORY->AddressOfFunctions + (ULONG)Mod);

        ULONG size_CNT = (EXPORT_DIRECTORY->NumberOfNames > EXPORT_DIRECTORY->NumberOfFunctions) ? EXPORT_DIRECTORY->NumberOfNames : EXPORT_DIRECTORY->NumberOfFunctions;

        for (USHORT i = 0; i < size_CNT; i++)
        {
            if (i < EXPORT_DIRECTORY->NumberOfFunctions)
            {
                tmpName = (char*)(RVAPointer[i] + (ULONG)Mod);
                tmpINDEX = oTb_RVA[i];
            }
            else
            {
                tmpName = 0;
                tmpINDEX = i;
            }
            Adress = dwTbRVA[tmpINDEX] + (ULONG)Mod;
            if ((strTMP == tmpINDEX + EXPORT_DIRECTORY->Base) || (tmpName && !strcmp(tmpName, fName))) // wcscmp
            {
                uReturn = Adress;
                break;
            }
        }
    }
    return reinterpret_cast<FARPROC>(uReturn);
}

vector<_export_data*> Scanner::query_function_list(HMODULE Mod)
{
    vector<_export_data*> t3Vector;

    ULONG  uReturn = 0;
    USHORT strTMP = 0;
    USHORT tmpINDEX;
    char * tmpName;
    ULONG Adress;

    if (Mod)
    {
        ULONG Portable_Executable = *(ULONG*)((ULONG)Mod + 0x3C) + (ULONG)Mod;
        PIMAGE_EXPORT_DIRECTORY EXPORT_DIRECTORY = (PIMAGE_EXPORT_DIRECTORY)(*(ULONG*)((ULONG)Portable_Executable + 0x78) + (ULONG)Mod);
        PULONG RVAPointer = (ULONG*)(EXPORT_DIRECTORY->AddressOfNames + (ULONG)Mod);
        PUSHORT oTb_RVA = (USHORT*)(EXPORT_DIRECTORY->AddressOfNameOrdinals + (ULONG)Mod);
        PULONG dwTbRVA = (ULONG*)(EXPORT_DIRECTORY->AddressOfFunctions + (ULONG)Mod);

        ULONG size_CNT = (EXPORT_DIRECTORY->NumberOfNames > EXPORT_DIRECTORY->NumberOfFunctions) ? EXPORT_DIRECTORY->NumberOfNames : EXPORT_DIRECTORY->NumberOfFunctions;

        for (USHORT i = 0; i < size_CNT; i++)
        {
            if (i < EXPORT_DIRECTORY->NumberOfFunctions)
            {
                tmpName = (char*)(RVAPointer[i] + (ULONG)Mod);
                tmpINDEX = oTb_RVA[i];
            }
            else
            {
                tmpName = 0;
                tmpINDEX = i;
            }
            Adress = dwTbRVA[tmpINDEX] + (ULONG)Mod;
            t3Vector.push_back(new _export_data(reinterpret_cast<FARPROC>(Adress), tmpName));
        }
    }
    return t3Vector;
}

hHookData* Scanner::GetExternalData(std::string NameOfModule, std::string NameOfFunction, DWORD size)
{
    hHookData* Data = nullptr;

    HMODULE m_pModule = GetModuleHandleA(NameOfModule.c_str());
    cModule* g_pModule = this->vProcess->GetModule(NameOfModule);

    if (S_SUCCRESS(m_pModule) && S_SUCCRESS(g_pModule))
    {
        FARPROC m_pFunction = this->find_function(m_pModule, NameOfFunction.c_str());

        if (S_SUCCRESS(m_pFunction))
        {
            void* hLocalBuffer = malloc(size);
            void* hExternalBuffer = malloc(size);

            if (S_SUCCRESS(hLocalBuffer) && S_SUCCRESS(hExternalBuffer))
            {
                DWORD dwOldProtect = 0;

                VirtualProtectEx(GetCurrentProcess(), m_pFunction, size, PAGE_EXECUTE_READ, &dwOldProtect);
                ReadProcessMemory(GetCurrentProcess(), m_pFunction, hLocalBuffer, size, 0);
                VirtualProtectEx(GetCurrentProcess(), m_pFunction, size, dwOldProtect, &dwOldProtect);

                VirtualProtectEx(this->vProcess->GetHandle(), m_pFunction, size, PAGE_EXECUTE_READ, &dwOldProtect);
                ReadProcessMemory(this->vProcess->GetHandle(), m_pFunction, hExternalBuffer, size, 0);
                VirtualProtectEx(this->vProcess->GetHandle(), m_pFunction, size, dwOldProtect, &dwOldProtect);

                if (memcmp(hLocalBuffer, hExternalBuffer, size) == 0)
                {
                    free(hLocalBuffer);
                    free(hExternalBuffer);
                }
                else
                {
                    Data = new hHookData(reinterpret_cast<DWORD>(m_pFunction), size, hLocalBuffer, hExternalBuffer);
                }
            }
        }
    }

    return Data;
}

vector<hHookData*> Scanner::ScanExternalModule(std::string NameOfModule, DWORD size)
{
    vector<hHookData*> Data;

    HMODULE m_pModule = GetModuleHandleA(NameOfModule.c_str());
    cModule* g_pModule = this->vProcess->GetModule(NameOfModule);

    if (S_SUCCRESS(m_pModule) && S_SUCCRESS(g_pModule))
    {
        vector<_export_data*> m_pFunctionList = this->query_function_list(m_pModule);

        if (S_SUCCRESS(m_pFunctionList.size()))
        {
            for (_export_data* data : m_pFunctionList)
            {
                if (S_SUCCRESS(data->api_call) && S_SUCCRESS(data->api_name))
                {
                    void* hLocalBuffer = malloc(size);
                    void* hExternalBuffer = malloc(size);

                    if (S_SUCCRESS(hLocalBuffer) && S_SUCCRESS(hExternalBuffer))
                    {
                        DWORD dwOldProtect = 0;

                        VirtualProtectEx(GetCurrentProcess(), data->api_call, size, PAGE_EXECUTE_READ, &dwOldProtect);
                        ReadProcessMemory(GetCurrentProcess(), data->api_call, hLocalBuffer, size, 0);
                        VirtualProtectEx(GetCurrentProcess(), data->api_call, size, dwOldProtect, &dwOldProtect);

                        VirtualProtectEx(this->vProcess->GetHandle(), data->api_call, size, PAGE_EXECUTE_READ, &dwOldProtect);
                        ReadProcessMemory(this->vProcess->GetHandle(), data->api_call, hExternalBuffer, size, 0);
                        VirtualProtectEx(this->vProcess->GetHandle(), data->api_call, size, dwOldProtect, &dwOldProtect);

                        if (memcmp(hLocalBuffer, hExternalBuffer, size) == 0)
                        {
                            free(hLocalBuffer);
                            free(hExternalBuffer);
                        }
                        else
                        {
                            Data.push_back(new hHookData(reinterpret_cast<DWORD>(data->api_call), size, hLocalBuffer, hExternalBuffer));
                        }
                    }
                }
            }
        }
    }

    return Data;
}
Пример использования:
Код:
int main()
{

    cProcess* g_pProcess = new cProcess;
   
    DWORD PID = g_pProcess->GetProcessIdByName("process.exe");

    if (PID > 0)
    {
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);

        if (hProcess)
        {
            g_pProcess->Attach(hProcess);

            Scanner g_pScanner = Scanner(g_pProcess);

            hHookData* getData = g_pScanner.GetExternalData("kernel32.dll", "LoadLibraryA", 5);
            if (getData != nullptr)
            {
                //стоит хук
            }
            else
            {
                //Хука нет.
            }

            vector<hHookData*> Hooks = g_pScanner.ScanExternalModule("kernel32.dll", 5);
            //выведет все хуки найденные в kernel32.dll если они есть.
            //размеры естественно указывать руками, минимум 5 для тамполайна x32 и минимум 12 для x64
            for (hHookData* Data : Hooks)
            {
                printf("find hook: 0x%X size: %d\n", Data->api_address, Data->api_size);
            }

            printf("Hooks Len: %d\n", Hooks.size());

            system("pause");
        }
    }

    g_pProcess->Detach();
    delete g_pProcess;

    return 0;
}
А можно гайд по части памяти?А то плохие люди плюсую лишнее, а потом возращают обратно старое :(

#ifdef USE32
auto assemblyLoadHookRefAddr = exportData->procAddress + 6;
m_AssemblyLoadPtr = m_InnerProcess.memory().Read<int>(assemblyLoadHookRefAddr).result();
#else
auto assemblyLoadHookRefAddr = exportData->procAddress + 13;
int assemblyLoadHookOffset = m_InnerProcess.memory().Read<int>(assemblyLoadHookRefAddr).result();
m_AssemblyLoadPtr = (exportData->procAddress + 17) + assemblyLoadHookOffset;
#endif
[TBODY] [/TBODY]
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Тут я имел в виду что уже есть рабочие сканнеры
я это в самом начале написал,
как правило, большинство античитов не дают сделать снимок хуков сторонним приложениям, ибо те тулзы, которые для этого существуют, зачастую детектят.​
на пример PCHunter, но в месте с любой игрой на EasyAntiCheat ты его не запустишь. EAC не установится просто и пошлет нафиг. Эти тулзы детектят как самые ссаные, а опенсорса на них найти крайне трудно.
 
Разработчик
Статус
Оффлайн
Регистрация
23 Авг 2017
Сообщения
171
Реакции[?]
474
Поинты[?]
1K
я это в самом начале написал,
на пример PCHunter, но в месте с любой игрой на EasyAntiCheat ты его не запустишь. EAC не установится просто и пошлет нафиг. Эти тулзы детектят как самые ссаные, а опенсорса на них найти крайне трудно.
Ждём детекта твоей :kappa:
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
А можно гайд по части памяти?А то плохие люди плюсую лишнее, а потом возращают обратно старое :(

#ifdef USE32
auto assemblyLoadHookRefAddr = exportData->procAddress + 6;
m_AssemblyLoadPtr = m_InnerProcess.memory().Read<int>(assemblyLoadHookRefAddr).result();
#else
auto assemblyLoadHookRefAddr = exportData->procAddress + 13;
int assemblyLoadHookOffset = m_InnerProcess.memory().Read<int>(assemblyLoadHookRefAddr).result();
m_AssemblyLoadPtr = (exportData->procAddress + 17) + assemblyLoadHookOffset;
#endif
[TBODY] [/TBODY]
как я понял, из твоих слов они снимают твою подписку на событие assemblyLoad, насколько я знаю моно инжекторы чаще всего запуливают шелкод для инжекта, для шелкода нужен поток, или APC вызов (асинхронное выполнение), можно детектить и то и другое, для трейдов, гугли в направлении RtlCreateUserThread/NtCreateThreadEx, для APC, гугли KiUserApcDispatcher, KiUserCallbackDispatcher, KiUserExceptionDispatcher, KiRaiseUserExceptionDispatcher / QueneUserAPC.... Еще прикольно палить DisableThreadLibraryCalls)) многие прямо в dllmain эту не нужную отписку делают даже не зная зачем она нужна. А вообще, скачай API Monitor, и с читом в игру зайди, посмотри какие они функции вызывают, из данных проаперируй фикс.
 
Забаненный
Статус
Оффлайн
Регистрация
12 Май 2017
Сообщения
375
Реакции[?]
11
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
как я понял, из твоих слов они снимают твою подписку на событие assemblyLoad, насколько я знаю моно инжекторы чаще всего запуливают шелкод для инжекта, для шелкода нужен поток, или APC вызов (асинхронное выполнение), можно детектить и то и другое, для трейдов, гугли в направлении RtlCreateUserThread/NtCreateThreadEx, для APC, гугли KiUserApcDispatcher, KiUserCallbackDispatcher, KiUserExceptionDispatcher, KiRaiseUserExceptionDispatcher / QueneUserAPC.... Еще прикольно палить DisableThreadLibraryCalls)) многие прямо в dllmain эту не нужную отписку делают даже не зная зачем она нужна. А вообще, скачай API Monitor, и с читом в игру зайди, посмотри какие они функции вызывают, из данных проаперируй фикс.
Просто добавляют 6 байтов и потом возращают все назад.Может readmemory поможет?

Код:
    bool MonoProcess::DisableAssemblyLoadCallback()
    {
        /*
        *    Ref: https://github.com/Unity-Technologies/mono/blob/unity-staging/mono/metadata/assembly.c
        *
        *    => AssemblyLoadHook *assembly_load_hook = NULL;
        *    AssemblyLoadHook is a global variable that holds all the callbacks that needs to be fired when an assembly is loaded.
        *   
        *    Plan is to get an hold of it, null the pointer and restore it after loading our injected assembly.
        */

        if (m_OriginalAssemblyLoadPtrVal == NULL)
        {
            if (m_AssemblyLoadPtr == NULL)
            {
                auto exportData = m_InnerProcess.modules().GetExport(m_MonoModule, "mono_assembly_invoke_load_hook");

            #ifdef USE32
                auto assemblyLoadHookRefAddr = exportData->procAddress + 6;
                m_AssemblyLoadPtr = m_InnerProcess.memory().Read<int>(assemblyLoadHookRefAddr).result();
            #else
                auto assemblyLoadHookRefAddr = exportData->procAddress + 13;
                int assemblyLoadHookOffset = m_InnerProcess.memory().Read<int>(assemblyLoadHookRefAddr).result();
                m_AssemblyLoadPtr = (exportData->procAddress + 17) + assemblyLoadHookOffset;
            #endif               
            }

            //Keep the original pointer value so we can restore it.
            m_OriginalAssemblyLoadPtrVal = m_InnerProcess.memory().Read<blackbone::ptr_t>(m_AssemblyLoadPtr).result();

            //Null the pointer so it doesn't points to existing callback list anymore
            m_InnerProcess.memory().Write<blackbone::ptr_t>(m_AssemblyLoadPtr, 0);

            return true;
        }

        return false;
    }

    bool MonoProcess::EnableAssemblyLoadCallback()
    {
        if (m_OriginalAssemblyLoadPtrVal != NULL)
        {
            m_InnerProcess.memory().Write<blackbone::ptr_t>(m_AssemblyLoadPtr, m_OriginalAssemblyLoadPtrVal);
            m_OriginalAssemblyLoadPtrVal = NULL;

            return true;
        }

        return false;
    }
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Просто добавляют 6 байтов и потом возращают все назад.Может readmemory поможет?

Код:
    bool MonoProcess::DisableAssemblyLoadCallback()
    {
        /*
        *    Ref: https://github.com/Unity-Technologies/mono/blob/unity-staging/mono/metadata/assembly.c
        *
        *    => AssemblyLoadHook *assembly_load_hook = NULL;
        *    AssemblyLoadHook is a global variable that holds all the callbacks that needs to be fired when an assembly is loaded.
        * 
        *    Plan is to get an hold of it, null the pointer and restore it after loading our injected assembly.
        */

        if (m_OriginalAssemblyLoadPtrVal == NULL)
        {
            if (m_AssemblyLoadPtr == NULL)
            {
                auto exportData = m_InnerProcess.modules().GetExport(m_MonoModule, "mono_assembly_invoke_load_hook");

            #ifdef USE32
                auto assemblyLoadHookRefAddr = exportData->procAddress + 6;
                m_AssemblyLoadPtr = m_InnerProcess.memory().Read<int>(assemblyLoadHookRefAddr).result();
            #else
                auto assemblyLoadHookRefAddr = exportData->procAddress + 13;
                int assemblyLoadHookOffset = m_InnerProcess.memory().Read<int>(assemblyLoadHookRefAddr).result();
                m_AssemblyLoadPtr = (exportData->procAddress + 17) + assemblyLoadHookOffset;
            #endif             
            }

            //Keep the original pointer value so we can restore it.
            m_OriginalAssemblyLoadPtrVal = m_InnerProcess.memory().Read<blackbone::ptr_t>(m_AssemblyLoadPtr).result();

            //Null the pointer so it doesn't points to existing callback list anymore
            m_InnerProcess.memory().Write<blackbone::ptr_t>(m_AssemblyLoadPtr, 0);

            return true;
        }

        return false;
    }

    bool MonoProcess::EnableAssemblyLoadCallback()
    {
        if (m_OriginalAssemblyLoadPtrVal != NULL)
        {
            m_InnerProcess.memory().Write<blackbone::ptr_t>(m_AssemblyLoadPtr, m_OriginalAssemblyLoadPtrVal);
            m_OriginalAssemblyLoadPtrVal = NULL;

            return true;
        }

        return false;
    }
как я понял они ссылку затирают, прогугли в направлении hLeaker C#, и проверяй какие внешние процессы имеют хендлы твоего процесса, так ты узнаешь какие процессы содержат или открывают хендлы твоего процесса/твоих потоков/твоих файлов клиента и сможешь реагировать на подозрительные, на пример если у некого процесса есть хендл с правом на чтение/запись памяти vm операции, или же ALL_ACCESS, и это не системный процесс - смело можешь высылать ДЕТЕКТЕД.
 
Забаненный
Статус
Оффлайн
Регистрация
12 Май 2017
Сообщения
375
Реакции[?]
11
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
как я понял они ссылку затирают, прогугли в направлении hLeaker C#, и проверяй какие внешние процессы имеют хендлы твоего процесса, так ты узнаешь какие процессы содержат или открывают хендлы твоего процесса/твоих потоков/твоих файлов клиента и сможешь реагировать на подозрительные, на пример если у некого процесса есть хендл с правом на чтение/запись памяти vm операции, или же ALL_ACCESS, и это не системный процесс - смело можешь высылать ДЕТЕКТЕД.
Про хендлы можешь подсказать куда копать?Если буду искать что-то типо "Как найти дочерние процессы по хендлу" не думаю что найду путное что-то
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Про хендлы можешь подсказать куда копать?Если буду искать что-то типо "Как найти дочерние процессы по хендлу" не думаю что найду путное что-то
я же тебе сказал, hLeaker C#. или же FindHandles C++, это на гитхабе есть, суть в том чтобы перебрать все хендлы открытые в системе, определить какие из них принадлежат тебе, твоему процессу, твоим потокам, и в чьих руках эти хендлы.
 
Забаненный
Статус
Оффлайн
Регистрация
12 Май 2017
Сообщения
375
Реакции[?]
11
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
я же тебе сказал, hLeaker C#. или же FindHandles C++, это на гитхабе есть, суть в том чтобы перебрать все хендлы открытые в системе, определить какие из них принадлежат тебе, твоему процессу, твоим потокам, и в чьих руках эти хендлы.
Хорошо.А то мы там уже к Zero приравниваем (
 
Забаненный
Статус
Оффлайн
Регистрация
12 Май 2017
Сообщения
375
Реакции[?]
11
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
я же тебе сказал, hLeaker C#. или же FindHandles C++, это на гитхабе есть, суть в том чтобы перебрать все хендлы открытые в системе, определить какие из них принадлежат тебе, твоему процессу, твоим потокам, и в чьих руках эти хендлы.
Видать не работает от с unity - или я что-то намудрил...Поменял TargetProcess с Unturned на название своего процесса без exe и при запуске HandleLeaker он просто висит в процессах и все
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Видать не работает от с unity - или я что-то намудрил...Поменял TargetProcess с Unturned на название своего процесса без exe и при запуске HandleLeaker он просто висит в процессах и все
это похоже на цитату говно кодера, hLeaker содержит лишь метод, его нужно ПЕРЕПИСЫВАТЬ ПОД СВОИ НУЖДЫ.
 
Забаненный
Статус
Оффлайн
Регистрация
12 Май 2017
Сообщения
375
Реакции[?]
11
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
это похоже на цитату говно кодера, hLeaker содержит лишь метод, его нужно ПЕРЕПИСЫВАТЬ ПОД СВОИ НУЖДЫ.
Значит херовый кодер я.Инфы по читам дохера,а вот античит никто делать не хочет.Не 1 статьи нормальной нету по минимальной защите
 
Похожие темы
Ответы
4
Просмотры
2K
Сверху Снизу