Memory API - С чего начать

Первое знакомство с Memory API в скриптах EyeAuras

Memory API в скриптах EyeAuras

Memory API нужен, когда вы хотите читать не экран, а реальные данные из памяти процесса: entity list, структуры игрока, координаты, HP, target id, view matrix и похожие вещи. Если нужен быстрый игровой контекст, посмотрите Aimbot и ESP у Game Hacking Academy.

Главная идея EyeAuras не в том, что это "ещё один reader памяти". Главное здесь в том, что поверх разных способов доступа к памяти лежит один и тот же верхний слой:

  • типизированное чтение и запись
  • строки, структуры и pointer math
  • MemoryOfModule(...)
  • ReadImports() и ReadExports()
  • pattern scanning
  • code caves

То есть вы меняете backend, а большая часть инструментов остаётся прежней.

Какие backend'ы уже есть

  • LocalProcess — обычный локальный процесс через WinAPI. Это нормальная первая точка входа. С защищёнными процессами он не подходит. Подробнее: LocalProcess.
  • NativeLocalProcess — тот же локальный сценарий, но поверх handle, который вы уже получили своим способом.
  • LCProcess — backend через MemProcFS и LeechCore. Основной сценарий здесь это DMA, обычно через FPGA. Подробнее: LCProcess. По теме полезны Ulf Frisk, LeechCore, MemProcFS и PCILeech.
  • KDProcess — backend через kernel driver. Нужен там, где обычного WinAPI уже мало.

KernelDriver сейчас в закрытом бета-тесте. Если вы автор пака и вам нужен доступ, напишите мне отдельно. FPGA и DMA сценарии уже доступны всем желающим.

Если у вас свой драйвер или свой способ чтения памяти, его тоже можно встроить в Memory API. Для этого есть отдельные точки расширения: Кастомный IProcess и Кастомные memory backend.

Куда читать дальше по backend'ам и расширению

Если вам нужна не только базовая работа с LocalProcess, а более конкретный сценарий, удобнее всего идти так:

  • для обычного локального чтения и user-mode контроля: LocalProcess
  • для DMA, MemProcFS и LeechCore: LCProcess
  • если хотите подключить свой драйвер, bridge или внешний reader как полноценный процесс: Кастомный IProcess
  • если хотите оборачивать уже существующий backend в кэш, логирование, статистику или другие decorator-слои: Кастомные memory backend

Что значит IProcess

Если коротко, interface в C# здесь означает не "сложную внутренность", а просто контракт.

  • IProcess — объект, который представляет процесс
  • IProcessMemory — объект, через который вы работаете с памятью процесса

Если вы читаете эту страницу именно как автор интеграции, дальше обычно полезно смотреть две статьи:

  • Кастомный IProcess — если хотите подключить новый источник памяти как полноценный process-wrapper
  • Кастомные memory backend — если хотите добавить кэширование, логирование, статистику или другой низкоуровневый слой поверх уже существующего backend'а

Для старта достаточно помнить простую связку:

  • LocalProcess открывает процесс
  • process.Memory даёт доступ к памяти

Первый пример

Самый безопасный стартовый сценарий это открыть текущий процесс EyeAuras, взять модуль и прочитать его экспорты.

csharp
using System.Diagnostics;
using EyeAuras.Memory;
using EyeAuras.Memory.Scaffolding;

using var process = LocalProcess.ByProcessId(Process.GetCurrentProcess().Id);
using var kernel32 = process.MemoryOfModule("kernel32.dll");

Log.Info($"Process: {process.ProcessName} ({process.ProcessId})");
Log.Info($"Modules: {process.GetProcessModules().Count}");
Log.Info($"kernel32 exports: {kernel32.ReadExports().Count}");

Этот пример хорош тем, что в нём уже есть вся базовая модель: процесс, модуль и работа не с "магическим адресом", а с нормальным окном на память модуля.

Базовый маршрут

Обычно работа выглядит так:

  1. открыть процесс
  2. выбрать нужный модуль
  3. ограничить память через MemoryOfModule(...)
  4. найти опорную точку через export, import или сигнатуру
  5. уже потом читать структуры и указатели

Если хотите лучше понять, почему так надёжнее, чем просто хранить один жёсткий адрес, очень помогают Game Fundamentals, Dynamic Memory Allocation и Pattern Scanner.

Что доступно всегда, а что нет

Здесь есть простое правило:

  • чтение памяти доступно почти всегда
  • активный контроль процесса зависит от backend'а

Почти любой backend хорошо покрывает:

  • чтение памяти
  • модули, потоки и регионы
  • MemoryOfModule(...)
  • импорты, экспорты и сигнатуры

А вот вещи вроде заморозки процесса, выделения памяти, смены protection, DLL inject, APC, remote thread или manual mapping доступны не везде.

  • LocalProcess и NativeLocalProcess подходят и для чтения, и для обычного user-mode контроля процесса.
  • LCProcess в первую очередь про внешнее чтение и анализ памяти. Для активного управления процессом он обычно не используется.
  • KDProcess нужен там, где нужен более глубокий контроль и обычный WinAPI уже не справляется.

Выделение, ProtectMemory(...) и FreeMemory(...)

В свежих версиях у IProcessControlApi появились явные методы для полного цикла работы с выделенным регионом:

  • AllocateMemory(...) выделяет память и возвращает IMemoryRegion
  • IMemoryRegion хранит Address и Size
  • ProtectMemory(...) меняет protection и возвращает предыдущее значение
  • FreeMemory(...) явно освобождает ранее выделенный регион

Это удобно в сценариях, где нужно:

  • подготовить буфер внутри процесса
  • временно открыть страницу под patching или shellcode
  • потом вернуть protection назад
  • в конце корректно освободить память

Простейший маршрут выглядит так:

csharp
using System.Diagnostics;
using EyeAuras.Memory;

using var process = LocalProcess.ByProcessId(Process.GetCurrentProcess().Id);
var control = (IProcessControlApi) process;

var region = control.AllocateMemory(
    IntPtr.Zero,
    4096,
    MemoryAllocationType.Commit | MemoryAllocationType.Reserve,
    MemoryProtectionType.ReadWrite);

try
{
    var oldProtection = control.ProtectMemory(
        region.Address,
        region.Size,
        MemoryProtectionType.ExecuteRead);

    // Здесь можно писать данные, делать patching или готовить payload.

    control.ProtectMemory(region.Address, region.Size, oldProtection);
}
finally
{
    control.FreeMemory(region);
}

Важно помнить:

  • ProtectMemory(...) и FreeMemory(...) относятся к активному управлению процессом, а не просто к чтению памяти
  • обычно это имеет смысл с LocalProcess, NativeLocalProcess и KDProcess
  • не каждый backend обязан это поддерживать; если не поддерживает, можно получить NotSupportedException

Зачем нужен DLL inject

Пока вы читаете память снаружи, вы в основном наблюдаете за процессом. DLL inject нужен, когда код должен выполняться уже внутри целевой программы: вызывать её внутренние функции, ставить хуки, делать code cave, строить internal-логику. Отдельная статья с разбором вариантов, manual mapping и особенностей запуска здесь: DLL inject. Если нужен внешний фон, полезны DLL Memory Hack, DLL Injector, Code Caves & DLL's и Triggerbot.

Что читать дальше