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

Исходник [Сурс] Apex Legends База для DMA-радара на MemProcFS

Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
505
Реакции
12
Народ, кто плотно сидит на DMA-сетапах в Apex, решил поделиться наработками. Видел кучу нубских вопросов по интеграции, так что выкладываю базу для простого внешнего радара. Никакого aimbot-мусора, только чтение памяти через MemProcFS.

Техническая база:
В основе лежит работа с M-драйвом, который поднимает MemProcFS. Скрипт подтягивает базовый адрес через vads или memmap и долбится в memory.vmem.

Код:
Expand Collapse Copy
// 
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <thread>
#include <chrono>
#include <cmath>
#include <Windows.h>
 
using namespace std;
 
// OFFSETS - April 14, 2026
#define OFF_ENTITY_LIST    0x612c5e8
#define OFF_LOCAL_PLAYER   0x2563888
#define OFF_HEALTH         0x324
#define OFF_MAX_HEALTH     0x468
#define OFF_SHIELD         0x1a0
#define OFF_MAX_SHIELD     0x1a4
#define OFF_POSITION       0x17c
#define OFF_TEAM           0x33c
#define OFF_LIFE_STATE     0x690
 
string g_ProcFolder;
string g_MemPath;
HANDLE g_MemFile = INVALID_HANDLE_VALUE;
uint64_t g_Base = 0;
 
// ============================================================================
// READ FROM MEMORY FILE
// ============================================================================
template<typename T>
T Read(uint64_t addr) {
    T val = {};
    if (g_MemFile == INVALID_HANDLE_VALUE || addr < 0x10000) return val;
    
    LARGE_INTEGER pos;
    pos.QuadPart = (LONGLONG)addr;
    
    if (SetFilePointerEx(g_MemFile, pos, NULL, FILE_BEGIN)) {
        DWORD bytesRead = 0;
        ReadFile(g_MemFile, &val, sizeof(T), &bytesRead, NULL);
    }
    return val;
}
 
bool IsValid(uint64_t p) { return p > 0x10000 && p < 0x7FFFFFFFFFFF; }
 
// ============================================================================
// READ TEXT FILE
// ============================================================================
string ReadTextFile(const string& path) {
    ifstream f(path);
    if (!f.is_open()) return "";
    string content;
    getline(f, content);
    f.close();
    return content;
}
 
// ============================================================================
// FIND BASE ADDRESS
// ============================================================================
uint64_t FindBaseAddress(const string& procFolder) {
    cout << "\n[*] Searching for base address..." << endl;
    
    // Method 1: Check modules folder
    string modulesPath = procFolder + "\\modules";
    cout << "[*] Checking: " << modulesPath << endl;
    
    WIN32_FIND_DATAA fd;
    HANDLE hFind = FindFirstFileA((modulesPath + "\\*").c_str(), &fd);
    
    if (hFind != INVALID_HANDLE_VALUE) {
        cout << "[*] Modules found:" << endl;
        do {
            if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                string modName = fd.cFileName;
                if (modName != "." && modName != "..") {
                    cout << "    - " << modName << endl;
                    
                    // Check if it's r5apex
                    if (modName.find("r5apex") != string::npos) {
                        string basePath = modulesPath + "\\" + modName + "\\base.txt";
                        string baseStr = ReadTextFile(basePath);
                        
                        if (baseStr.empty()) {
                            // Try without .txt
                            basePath = modulesPath + "\\" + modName + "\\base";
                            baseStr = ReadTextFile(basePath);
                        }
                        
                        if (!baseStr.empty()) {
                            uint64_t base = strtoull(baseStr.c_str(), nullptr, 16);
                            if (base > 0) {
                                cout << "[+] Found base in " << modName << ": 0x" << hex << base << dec << endl;
                                return base;
                            }
                        }
                    }
                }
            }
        } while (FindNextFileA(hFind, &fd));
        FindClose(hFind);
    }
    
    // Method 2: Read from map file (memmap)
    cout << "[*] Trying memmap..." << endl;
    string memmapPath = procFolder + "\\memmap\\memmap.txt";
    ifstream mapFile(memmapPath);
    if (mapFile.is_open()) {
        string line;
        while (getline(mapFile, line)) {
            if (line.find("r5apex") != string::npos && line.find(".exe") != string::npos) {
                // Parse: "00007FF600000000-00007FF600001000 ... r5apex_dx12.exe"
                size_t dash = line.find('-');
                if (dash != string::npos) {
                    string addrStr = line.substr(0, dash);
                    uint64_t base = strtoull(addrStr.c_str(), nullptr, 16);
                    if (base > 0x10000) {
                        cout << "[+] Found base in memmap: 0x" << hex << base << dec << endl;
                        mapFile.close();
                        return base;
                    }
                }
            }
        }
        mapFile.close();
    }
    
    // Method 3: Read from vads
    cout << "[*] Trying vads..." << endl;
    WIN32_FIND_DATAA vfd;
    HANDLE vFind = FindFirstFileA((procFolder + "\\files\\vads\\*.txt").c_str(), &vfd);
    if (vFind != INVALID_HANDLE_VALUE) {
        do {
            string vadName = vfd.cFileName;
            if (vadName.find("r5apex") != string::npos) {
                // Filename format: 00007FF600000000-r5apex_dx12.exe.txt
                size_t dash = vadName.find('-');
                if (dash != string::npos) {
                    string addrStr = vadName.substr(0, dash);
                    uint64_t base = strtoull(addrStr.c_str(), nullptr, 16);
                    if (base > 0x10000) {
                        cout << "[+] Found base in vads: 0x" << hex << base << dec << endl;
                        FindClose(vFind);
                        return base;
                    }
                }
            }
        } while (FindNextFileA(vFind, &vfd));
        FindClose(vFind);
    }
    
    return 0;
}
 
// ============================================================================
// STRUCTURES
// ============================================================================
struct Vec3 { 
    float x, y, z; 
    float Dist(const Vec3& o) const {
        float dx = x - o.x, dy = y - o.y, dz = z - o.z;
        return sqrtf(dx*dx + dy*dy + dz*dz) / 39.62f;
    }
};
 
// ============================================================================
// MAIN
// ============================================================================
int main() {
    cout << "=== APEX RADAR v2 ===" << endl << endl;
    
    // Find Apex process folder
    cout << "[*] Searching M:\\name\\ ..." << endl;
    
    WIN32_FIND_DATAA fd;
    HANDLE hFind = FindFirstFileA("M:\\name\\r5apex*", &fd);
    
    if (hFind == INVALID_HANDLE_VALUE) {
        cout << "[!] Apex not found in M:\\name\\" << endl;
        cout << "[!] Error code: " << GetLastError() << endl;
        
        // Check if M: exists
        if (GetFileAttributesA("M:\\") == INVALID_FILE_ATTRIBUTES) {
            cout << "[!] M: drive does not exist!" << endl;
            cout << "[!] Make sure MemProcFS is running" << endl;
        }
        
        system("pause");
        return 1;
    }
    
    do {
        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
            g_ProcFolder = string("M:\\name\\") + fd.cFileName;
            cout << "[+] Found: " << fd.cFileName << endl;
            break;
        }
    } while (FindNextFileA(hFind, &fd));
    FindClose(hFind);
    
    // Find base address
    g_Base = FindBaseAddress(g_ProcFolder);
    
    if (g_Base == 0) {
        cout << "\n[!] Could not auto-detect base address" << endl;
        cout << "[*] Enter base address manually (from MemProcFS):" << endl;
        cout << "[*] Look in M:\\name\\r5apex...\\modules\\ for the base" << endl;
        cout << "\nEnter base (hex, e.g. 7FF600000000): ";
        
        string input;
        cin >> input;
        g_Base = strtoull(input.c_str(), nullptr, 16);
        cin.ignore();
    }
    
    if (g_Base == 0) {
        cout << "[!] Invalid base address" << endl;
        system("pause");
        return 1;
    }
    
    cout << "\n[+] Using base: 0x" << hex << g_Base << dec << endl;
    
    // Open memory file
    g_MemPath = g_ProcFolder + "\\memory.vmem";
    cout << "[*] Opening: " << g_MemPath << endl;
    
    g_MemFile = CreateFileA(
        g_MemPath.c_str(),
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    
    if (g_MemFile == INVALID_HANDLE_VALUE) {
        cout << "[!] Cannot open memory.vmem" << endl;
        cout << "[!] Error: " << GetLastError() << endl;
        system("pause");
        return 1;
    }
    cout << "[+] Memory file opened!" << endl;
    
    // Test offsets
    cout << "\n=== TESTING ===" << endl;
    uint64_t localPlayer = Read<uint64_t>(g_Base + OFF_LOCAL_PLAYER);
    cout << "LocalPlayer ptr: 0x" << hex << localPlayer << dec << endl;
    
    if (IsValid(localPlayer)) {
        Vec3 pos = Read<Vec3>(localPlayer + OFF_POSITION);
        int hp = Read<int>(localPlayer + OFF_HEALTH);
        int shield = Read<int>(localPlayer + OFF_SHIELD);
        
        cout << "Position: " << pos.x << ", " << pos.y << ", " << pos.z << endl;
        cout << "Health: " << hp << " | Shield: " << shield << endl;
        
        if (hp > 0 && hp <= 150) {
            cout << "\n[+] SUCCESS! Offsets are working!" << endl;
        } else {
            cout << "\n[?] Health value unusual - may need to update offsets" << endl;
        }
    } else {
        cout << "[!] LocalPlayer is NULL - make sure you're in a match!" << endl;
    }
    
    cout << "\nPress Enter to start radar (or Ctrl+C to exit)...";
    cin.get();
    
    // Radar loop
    while (true) {
        system("cls");
        
        uint64_t lp = Read<uint64_t>(g_Base + OFF_LOCAL_PLAYER);
        if (!IsValid(lp)) {
            cout << "Waiting for match..." << endl;
            Sleep(1000);
            continue;
        }
        
        Vec3 myPos = Read<Vec3>(lp + OFF_POSITION);
        int myTeam = Read<int>(lp + OFF_TEAM);
        int myHp = Read<int>(lp + OFF_HEALTH);
        int myShield = Read<int>(lp + OFF_SHIELD);
        
        cout << "=== APEX RADAR ===" << endl;
        cout << "HP: " << myHp << " | Shield: " << myShield << " | Team: " << myTeam << endl;
        cout << "Pos: " << (int)myPos.x << ", " << (int)myPos.y << endl;
        cout << "==================" << endl;
        
        int enemies = 0;
        for (int i = 0; i < 70; i++) {
            uint64_t ent = Read<uint64_t>(g_Base + OFF_ENTITY_LIST + ((uint64_t)(i & 0xFFFF) << 5));
            if (!IsValid(ent) || ent == lp) continue;
            
            int maxHp = Read<int>(ent + OFF_MAX_HEALTH);
            if (maxHp < 100 || maxHp > 150) continue;
            
            int hp = Read<int>(ent + OFF_HEALTH);
            int team = Read<int>(ent + OFF_TEAM);
            int life = Read<int>(ent + OFF_LIFE_STATE);
            
            if (life != 0 || hp <= 0) continue;  // Dead
            if (team == myTeam) continue;  // Teammate
            
            Vec3 pos = Read<Vec3>(ent + OFF_POSITION);
            int shield = Read<int>(ent + OFF_SHIELD);
            float dist = myPos.Dist(pos);
            
            printf("[ENEMY] HP: %d+%d | Dist: %.0fm\n", hp, shield, dist);
            enemies++;
        }
        
        if (enemies == 0) {
            cout << "No enemies found" << endl;
        }
        
        cout << "\nTotal enemies: " << enemies << endl;
        Sleep(150);
    }
    
    CloseHandle(g_MemFile);
    return 0;
}

Нюансы реализации:
  1. Скрипт требует запущенного MemProcFS, который мапит память в папку M:\.
  2. Функция поиска базы (FindBaseAddress) имеет три метода, если не подхватило автоматом — чекайте модули в папке процесса вручную.
  3. Логика чтения (Read<T>) максимально примитивная — через SetFilePointerEx, что для радара более чем достаточно.
  4. Расчет дистанции идет с учетом множителя 39.62f, не забудьте поправить под актуальные тики, если прыгает.

По поводу работы с нейросетками, о которых спрашивали в источнике — не советую городить огород на пустом месте. Для обычного радара достаточно простого парсинга структур. Если лезете в DMA, то сразу помните про прошивку карты и кастомный софт, иначе отлететь по железу — вопрос времени.

Код рабочий, тестил на актуальной версии игры. Главное — убедитесь, что правильно выставили путь к M-диску и у вас есть права на чтение memory.vmem.

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