Ertheia GetSendPacketAddress

LifeGame32

Прославленный
Местный
Сообщения
265
Розыгрыши
0
Решения
5
Репутация
339
Реакции
206
Баллы
1 438
ft-guard, GameGuard, rGuard и тп...
Клиент: Ertheia 610.
не работает "typedef void (__cdecl *_SendPacket) (unsigned int This, char *Format, ...)" - отправка клиент пакетов на сервер.
как я понял нужно изменить метод "unsigned int GetSendPacketAddress(void)"
C++:
unsigned int GetSendPacketAddress(void)
{
    HMODULE hEngine = LoadLibraryA("engine.dll");

    unsigned int startVMT = (unsigned int)hEngine + 0x51F658;
    unsigned int AddNetworkQueue = (unsigned int) GetProcAddress(hEngine, "?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPacket@@@Z");
    unsigned int currVMT = startVMT;

    if (AddNetworkQueue == 0)
    {
        return 0;
    }

    while (true)
    {
        if (*(unsigned int*) currVMT == AddNetworkQueue)
        {
            return *(unsigned int*) (currVMT - 0xA4);
        }

        currVMT++;
        if (currVMT - startVMT > 10000)
        {
            return 0;
        }
    }
    return 0;
}
unsigned int startVMT = (unsigned int)hEngine + 0x51F658; для hf 268
каким образом найти для артеи?
 

Вложения

  • EngineUNP.zip
    3 МБ · Просмотры: 11
  • Engine.zip
    4,8 МБ · Просмотры: 10

ft-guard, GameGuard, rGuard и тп...
Клиент: Ertheia 610.
не работает "typedef void (__cdecl *_SendPacket) (unsigned int This, char *Format, ...)" - отправка клиент пакетов на сервер.
как я понял нужно изменить метод "unsigned int GetSendPacketAddress(void)"
C++:
unsigned int GetSendPacketAddress(void)
{
    HMODULE hEngine = LoadLibraryA("engine.dll");

    unsigned int startVMT = (unsigned int)hEngine + 0x51F658;
    unsigned int AddNetworkQueue = (unsigned int) GetProcAddress(hEngine, "?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPacket@@@Z");
    unsigned int currVMT = startVMT;

    if (AddNetworkQueue == 0)
    {
        return 0;
    }

    while (true)
    {
        if (*(unsigned int*) currVMT == AddNetworkQueue)
        {
            return *(unsigned int*) (currVMT - 0xA4);
        }

        currVMT++;
        if (currVMT - startVMT > 10000)
        {
            return 0;
        }
    }
    return 0;
}
unsigned int startVMT = (unsigned int)hEngine + 0x51F658; для hf 268
каким образом найти для артеи?
Очевидно что нужно найти адрес и собственно саму функцию в Engine.dll от HighFive 268 ( изучить хоть немного ее сигнатуру) , после чего найти места откуда эту функция вызывается и а дальше по косвенными признакам, байтовой последовательности, либо по значению строк, найти такие же места в клиенте Erthei и после чего найти ту самую нужную функцию и высчитать нужные смешения.
 
Сигнатура для поиска SendPacket: B8 00 80 00 00 E8 ?? ?? ?? ?? 56
Если все-таки хотите отталкиваться от смещения, то заатачтесь x64Dbg (32-битной версией, естественно) с предварительно установленным плагином типа Baymax Tools который позволит искать по сигнатуре - найдите им адрес и вычтете BaseAddress engine.dll из него - получите нужное смещение.
 
убогий в этом деле. пусто. или что то не так сделал.
 

Вложения

  • 2024-06-18_21-55-42.png
    2024-06-18_21-55-42.png
    105 КБ · Просмотры: 80
Видимо сигнатура отличается. Попробуй по-очереди убирать по байту с конца из сигнатуры.
Я бы посмотрел наживую, но клиента чистого на 610 проткол найти не смог.
 
Да, видимо в Ertheia знатно поменяли сетевой код.
Попробуйте сигнатуру 55 8B EC 83 E4 F8 B8 04 80 00 00 E8 ?? ?? ?? ?? A1 ?? ?? ?? ?? 83 38 00
Смещение вроде как 4C3170 1718761392724.png
 
Последнее редактирование:
Очевидно что нужно найти адрес и собственно саму функцию в Engine.dll от HighFive 268 ( изучить хоть немного ее сигнатуру) , после чего найти места откуда эту функция вызывается и а дальше по косвенными признакам, байтовой последовательности, либо по значению строк, найти такие же места в клиенте Erthei и после чего найти ту самую нужную функцию и высчитать нужные смешения.
вот что в hf
C++:
unsigned int GetSendPacketAddress(void)
{
    HMODULE hEngine = LoadLibraryA("engine.dll");
    unsigned int startVMT = (unsigned int)hEngine;
    unsigned int AddNetworkQueue = (unsigned int) GetProcAddress(hEngine, "?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPacket@@@Z");
    unsigned int currVMT = startVMT;

    if (AddNetworkQueue == 0)
    {
        return 0;
    }

    while (true)
    {
        if (*(unsigned int*) currVMT == AddNetworkQueue)
        {
            return *(unsigned int*) (currVMT - 0xA4);
        }
        currVMT++;
    }
    return 0;
}
startVMT + так походу с потолка сюда пишется дабы быть ближе к адресу.
Код:
?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPacket@@@Z - 203d8380

20520a2c на 203d8380
    20520a2c 80              ??         80h                                              ?  ->  203d8380
    20520a2d 83              ??         83h
    20520a2e 3d              ??         3Dh    =
    20520a2f 20              ??         20h    

       
20520a2c - 0xA4  = 20520988
    20520988 b0              ??         B0h                                              ?  ->  203d8bb0
    20520989 8b              ??         8Bh
    2052098a 3d              ??         3Dh    =
    2052098b 20              ??         20h    

SendPacketAddress = 203d8bb0

то что происходит в unsigned int GetSendPacketAddress(void)
для артеи не выходит.
 
В Ertheia+ убрали UNetworkHandler вообще из экспортируемых функций, у вас AddNetworkQueue будет всегда nullptr. Эта функция ищет адрес SendPacket отталкиваясь от известного адреса и известного смещения относительно этого адреса. Хотя и хватало бы просто отнять известное смещение от адреса AddNetworkQueue без скана.

Поступим проще.

memory_utils.hpp

C++:
#pragma once
/**
 * @author ANZO
 */
class MemoryUtils
{
    public:
        /// Find specified pattern address in memory
        /// @param pattern hex pattern to search
        /// @param handle module handle to search
        /// @param skip_count skip count for cases when few matches found
        /// @return memory pointer
        static uint8_t* find_sig(const char* pattern, HMODULE handle = nullptr, const uint32_t skip_count = 0)
        {
            static auto pattern_to_byte = [](const char* pattern_signature)
            {
                auto bytes = std::vector<int>{};
                const auto start = const_cast<char*>(pattern_signature);
                const auto end = const_cast<char*>(pattern_signature) + std::strlen(pattern_signature);

                for (auto current = start; current < end; ++current)
                {
                    if (*current == '?')
                    {
                        ++current;
                        if (*current == '?')
                        {
                            ++current;
                        }
                        bytes.push_back(-1);
                    }
                    else
                    {
                        bytes.push_back(std::strtoul(current, &current, 16));
                    }
                }
                return bytes;
            };

            const auto dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(handle);
            const auto nt_headers =
                reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<std::uint8_t*>(handle) + dos_header->e_lfanew);

            const auto memory_size = nt_headers->OptionalHeader.SizeOfImage;
            const auto signature_bytes = pattern_to_byte(pattern);
            const auto memory_bytes = reinterpret_cast<std::uint8_t*>(handle);

            const auto signature_size = signature_bytes.size();
            const auto signature_data = signature_bytes.data();

            uint32_t found_count = 0;
            for (auto i = 0ul; i < memory_size - signature_size; ++i)
            {
                bool found = true;
                for (auto j = 0ul; j < signature_size; ++j)
                {
                    if (memory_bytes[i + j] != signature_data[j] && signature_data[j] != -1)
                    {
                        found = false;
                        break;
                    }
                }

                if (found)
                {
                    if (found_count == skip_count)
                    {
                        return &memory_bytes[i];
                    }
                    found_count++;
                }
            }
            return nullptr;
        }
  
        /// Find specified pattern address in memory
        /// @param pattern hex pattern to search
        /// @param module_name module handle name to search
        /// @param skip_count skip count for cases when few matches found
        /// @return memory pointer
        static uint8_t* find_sig(const char* pattern, LPCWSTR module_name = nullptr, const uint32_t skip_count = 0)
        {
            auto handle = ::GetModuleHandle(module_name);
            while (handle == nullptr)
            {
                handle = ::GetModuleHandle(module_name);
            }
            return find_sig(pattern, handle, skip_count);
        }

        /// Read bytes from specified process memory address
        /// @param process_handle process handle
        /// @param address memory address
        /// @param size bytes count to read
        /// @return byte array if read successfully, {@code nullptr} otherwise
        static uint8_t* read_bytes(const HANDLE process_handle, const DWORD64 address, const size_t size)
        {
            const auto address_pointer = reinterpret_cast<LPVOID>(address);
            const auto memory = new byte[size];
            memcpy(memory, address_pointer, size);
            return memory;
        }
};

Пример использования для твоего случая (не проверялось, так как у меня есть только engine.dll и в плюсах я вообще не але)
C++:
unsigned int GetSendPacketAddress(void)
{
    return reinterpret_cast<unsigned int>(
MemoryUtils::find_sig("55 8B EC 83 E4 F8 B8 04 80 00 00 E8 ?? ?? ?? ?? A1 ?? ?? ?? ?? 83 38 00", L"engine.dll", 0));
}
 
большая благодарность. заработало. по этому адресу 2024-06-20_21-25-31.png
 
  • Мне нравится
Реакции: ANZO
Назад
Сверху Снизу