WELCOME TO INFOCHEATS.NET

INFOCHEATS is a community-driven platform focused on free game cheats, cheat development, and verified commercial software for a wide range of popular games. We provide a large collection of free cheats shared by the community. All public releases are checked for malicious code to reduce the risk of viruses, malware, or unwanted software before users interact with them.

Alongside free content, INFOCHEATS hosts an active marketplace with many independent sellers offering commercial cheats. Each product is discussed openly, with user feedback, reviews, and real usage experience available to help you make informed decisions before purchasing.

Whether you are looking for free cheats, exploring paid solutions, comparing sellers, or studying how cheats are developed and tested, INFOCHEATS brings everything together in one place — transparently and community-driven.

byte_corvus

Newbie
Newbie

byte_corvus

Newbie
Newbie
Status
Offline
Joined
Mar 3, 2026
Messages
297
Reaction score
7
Anyone currently poking at APB?

Had to dust off the old projects because the existing dumpers for the latest build were either dead or broken. If you're tired of manual memory analysis, here's an updated implementation for dumping GNames and GObjects. It uses a clean external approach, though you'll need to plug in your own memory driver headers.

Technical Breakdown:
  1. GNames: Iterates through the name pool, handles both standard and flag-based string retrieval (0x4000 flag check included).
  2. GObjects: Parses the object array to generate logs for your SDK research.
  3. Object Traversal: Logic for recursive Outer pointer tracing to resolve full object paths.

The Implementation:
Code:
#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();
    }
};

Notes & Troubleshooting:
  1. Offsets: Ensure your Offset_GNames and Offset_GObjects are correctly updated in your local config; otherwise, you'll just be dumping garbage memory.
  2. Driver: This assumes you have a standard read function exported via your driver wrapper. If you're getting access violations, verify your process handle/EPROCESS status.
  3. Stability: This will work until the devs decide to shift the UObject structure, which happens more often than we'd like.

Q: Why is my log file empty?
A: Check your base address and verify the offsets. If your driver isn't reading the process memory correctly, you'll never find the count/max variables.

Q: Does this work for main?
A: Never run debug tools on your main account. This is strictly for RE and SDK generation. Use a burner if you're testing live.

Anyone else successfully dumping the latest build, or are you running into structural changes?
 
Top