Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Исходник All Points Bulletin — Актуальный GObjects/GNames дампер

Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
347
Реакции
7
Народ, решил скинуть актуальный дампер под последние билды APB. Старые методы отвалились, сигнатуры у многих поплыли, так что пришлось набросать свою реализацию. Внимание: для работы нужен свой драйвер для чтения памяти (в коде я его вырезал, подставьте свой интерфейс).

Этот код позволяет выгрузить актуальные GNames, GObjects и список пакетов в логи. Полезно, если собираете актуальный SDK или ищете оффсеты для своего external-проекта.

  1. Метод GetObjectName: берет индекс из памяти и вытягивает имя через GNames.
  2. DumpGNames: итерирует по массиву имен, учитывая флаг 0x4000.
  3. DumpGObjects: выгружает индексы, указатели и полные имена объектов в лог.
  4. DumpPackages: использует unordered_set для уникализации списка пакетов.

Код:
Expand Collapse Copy
#pragma once
#include <windows.h>
#include <string>
#include <fstream>
#include <sstream>
#include <unordered_set>
#include <stdexcept>
#include <driver/Memory.hpp>
#include <iostream>
#include <filesystem>
#include "utils/offsets.h"
 
class ApbTools {
private:
 
public:
    uint64_t GetClass(uint64_t objectPtr) {
        return driver->read<uint64_t>(objectPtr + 0x18);
    }
 
    uint64_t GetOuter(uint64_t objectPtr) {
        return driver->read<uint64_t>(objectPtr + 0x2C);
    }
 
    std::string GetObjectName(uint64_t objectPtr) {
        if (objectPtr == 0) {
            return "invalid object";
        }
        int32_t fNameIndex = driver->read<int32_t>(objectPtr + 0x24);
        return GetNameByIdx(fNameIndex);
    }
 
    uint64_t GetPackageObject(uint64_t objectPtr) {
        uint64_t outerPtr = GetOuter(objectPtr);
        uint64_t lastValidPtr = outerPtr;
 
        while (outerPtr != 0) {
            outerPtr = GetOuter(outerPtr);
            if (outerPtr != 0) {
                lastValidPtr = outerPtr;
            }
        }
 
        return lastValidPtr;
    }
 
    std::string GetObjectFullName(uint64_t objectPtr) {
        uint64_t classPtr = GetClass(objectPtr);
        uint64_t outerPtr = GetOuter(objectPtr);
        if (classPtr == 0 || outerPtr == 0) {
            return "(null)";
        }
 
        std::stringstream sb;
        sb << GetObjectName(classPtr) << " ";
 
        std::string name = GetObjectName(objectPtr);
        sb << name;
 
        while (outerPtr != 0) {
            name = GetObjectName(outerPtr);
            sb.seekp(0);
            sb << name << "." << sb.str();
            outerPtr = GetOuter(outerPtr);
        }
 
        return sb.str();
    }
 
    ApbTools() {}
 
    ~ApbTools() {
        // Destructor handles cleanup (equivalent to Dispose)
    }
 
    void DumpGNames() {
        int32_t num = driver->read<int32_t>(driver->image_base + cached.Offset_GNames.load() + 8);
        int32_t max = driver->read<int32_t>(driver->image_base + cached.Offset_GNames.load() + 12);
        std::cout << "num " << num << " max " << max << std::endl;
 
        std::ofstream sw("D:\\APB_Names.log");
        if (!sw.is_open()) {
            printf("%s\n", "Failed to open APB_Names.log");
            return;
        }
 
        for (uint64_t i = 0; i < static_cast<uint64_t>(num); ++i) {
            uint64_t namePtr = driver->read<uint64_t>(driver->read<uint64_t>(driver->image_base + cached.Offset_GNames.load()) + i * 8);
            if (namePtr == 0) {
                continue;
            }
            int32_t flag = driver->read<int32_t>(namePtr);
            uint64_t strPtr = (flag == 0x4000) ? driver->read<uint64_t>(namePtr + 0x30) : namePtr + 0x18;
            std::vector<char> buffer(1024);
            if (!driver->read(strPtr, buffer.data(), 1024)) {
                printf("%s\n", ("Failed to read string at address: " + std::to_string(strPtr)).c_str());
                continue;
            }
            // Find null terminator
            size_t len = 0;
            while (len < 1024 && buffer[len] != '\0') {
                ++len;
            }
            std::string str = std::string(buffer.data(), len);
 
 
            sw << "idx: " << std::setw(5) << std::setfill('0') << i << " name: " << str << "\n";
        }
        sw.close();
    }
 
    std::string GetNameByIdx(int32_t idx) {
        int32_t num = driver->read<int32_t>(driver->image_base + cached.Offset_GNames.load() + 8);
        if (idx < 0 || idx >= num) {
            return "invalid index";
        }
        uint64_t namePtr = driver->read<uint64_t>(driver->read<uint64_t>(driver->image_base + cached.Offset_GNames.load()) + static_cast<uint64_t>(idx) * 8);
        if (namePtr == 0) {
            return "invalid name";
        }
        int32_t flag = driver->read<int32_t>(namePtr);
        uint64_t strPtr = (flag == 0x4000) ? driver->read<uint64_t>(namePtr + 0x30) : namePtr + 0x18;
 
        std::vector<char> buffer(1024);
        if (!driver->read(strPtr, buffer.data(), 1024)) {
            printf("%s\n", ("Failed to read string at address: " + std::to_string(strPtr)).c_str());
            return "error:GetNameByIdx";
        }
        // Find null terminator
        size_t len = 0;
        while (len < 1024 && buffer[len] != '\0') {
            ++len;
        }
        std::string str = std::string(buffer.data(), len);
        return str;
    }
    void DumpSDK(){
        std::ofstream sw("D:\\APB_sdk.h");
        //apb_sdk::UObject::Class
        int32_t num = driver->read<int32_t>(driver->image_base + cached.Offset_GObjects.load() + 8);
        int32_t max = driver->read<int32_t>(driver->image_base + cached.Offset_GObjects.load() + 12);
        std::cout << "num " << num << " max " << max << std::endl;
        for (uint64_t i = 0; i < static_cast<uint64_t>(num); ++i) {
            uint64_t objectPtr = driver->read<uint64_t>(driver->read<uint64_t>(driver->image_base + cached.Offset_GObjects.load()) + i * 8);
            if (objectPtr == 0) {
                continue;
            }
            //uintptr_t _class = driver->read<uintptr_t>(objectPtr + apb_sdk::UObject::Class);
            //while (_class) {
            //    int id = driver->read<int>(objectPtr + apb_sdk::UObject::Name);
            //    std::string name = GetNameByIdx(id);
            //    if (id == 0 || name.empty()) {
            //        break;
            //    }
            //    std::string fullName = GetObjectFullName(objectPtr);
            //    sw << "Class " << std::left << std::setw(25) << fullName << "\n";
 
            //    sw << std::dec; // Reset to decimal
            //}
 
        }
 
        return;
    }
    void DumpGObjects() {
        int32_t num = driver->read<int32_t>(driver->image_base + cached.Offset_GObjects.load() + 8);
        int32_t max = driver->read<int32_t>(driver->image_base + cached.Offset_GObjects.load() + 12);
        std::cout << "num " << num << " max " << max << std::endl;
 
        std::ofstream sw("D:\\APB_Objects.log");
        if (!sw.is_open()) {
            printf("%s\n", "Failed to open APB_Objects.log");
            return;
        }
 
        for (uint64_t i = 0; i < static_cast<uint64_t>(num); ++i) {
            uint64_t objectPtr = driver->read<uint64_t>(driver->read<uint64_t>(driver->image_base + cached.Offset_GObjects.load()) + i * 8);
            if (objectPtr == 0) {
                continue;
            }
            std::string name = GetObjectName(objectPtr);
            std::string fullName = GetObjectFullName(objectPtr);
            sw << "idx " << std::setw(10) << std::setfill('0') << i
                << " ptr: " << std::hex << std::setw(16) << std::setfill('0') << objectPtr
                << " name: " << std::left << std::setw(40) << std::setfill(' ') << name
                << " fullName: " << std::setw(40) << fullName << "\n";
            sw << std::dec; // Reset to decimal
        }
        sw.close();
    }
    void DumpPackages() {
        std::unordered_set<std::string> packagesSet;
        int32_t num = driver->read<int32_t>(driver->image_base + cached.Offset_GObjects.load() + 8);
 
        std::ofstream sw("D:\\APB_Packages.log");
        if (!sw.is_open()) {
            printf("%s\n", "Failed to open APB_Packages.log");
            return;
        }
 
        for (uint64_t i = 0; i < static_cast<uint64_t>(num); ++i) {
            uint64_t objectPtr = driver->read<uint64_t>(driver->read<uint64_t>(driver->image_base + cached.Offset_GObjects.load()) + i * 8);
            if (objectPtr == 0) {
                continue;
            }
 
            uint64_t package = GetPackageObject(objectPtr);
            if (package == 0) {
                continue;
            }
 
            std::string packageName = GetObjectName(package);
            if (packagesSet.insert(packageName).second) {
                sw << packageName << "\n";
            }
        }
        sw.close();
    }
};

Работать будет до тех пор, пока не поменяют структуру UObject, так что если после патча крашит — первым делом смотрите оффсеты в utils/offsets.h.

Кто уже пробовал прокинуть это под последние апдейты, отпишитесь, не отлетели ли сигнатуры?
 
Назад
Сверху Снизу