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 scanningcode 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, взять модуль и прочитать его экспорты.
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}");
Этот пример хорош тем, что в нём уже есть вся базовая модель: процесс, модуль и работа не с "магическим адресом", а с нормальным окном на память модуля.
Базовый маршрут
Обычно работа выглядит так:
- открыть процесс
- выбрать нужный модуль
- ограничить память через
MemoryOfModule(...) - найти опорную точку через export, import или сигнатуру
- уже потом читать структуры и указатели
Если хотите лучше понять, почему так надёжнее, чем просто хранить один жёсткий адрес, очень помогают 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(...)выделяет память и возвращаетIMemoryRegionIMemoryRegionхранитAddressиSizeProtectMemory(...)меняет protection и возвращает предыдущее значениеFreeMemory(...)явно освобождает ранее выделенный регион
Это удобно в сценариях, где нужно:
- подготовить буфер внутри процесса
- временно открыть страницу под patching или shellcode
- потом вернуть protection назад
- в конце корректно освободить память
Простейший маршрут выглядит так:
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.