Основи: пам'ять, процеси та інструменти
Основи: пам'ять, процеси та інструменти
🎯 Мета розділу
- Зрозуміти, що таке реверс-інжиніринг (reverse engineering) і де його застосовують.
- Знати правові та етичні межі: на чому тренуватися можна, а на чому ні.
- Побачити план курсу: від пошуку значення в пам'яті до власного чіта для AssaultCube.
- Зрозуміти, чому адреса у двох процесів може збігатися, а дані різні.
- Знати, які області пам'яті є в процесі: код, дані, купа, стек.
- Дізнатися, який системний виклик читає пам'ять іншого процесу на кожній ОС.
- Встановити сканер пам'яті, налагоджувач і компілятор на своїй ОС.
- Зібрати та запустити гру-мішень і тренер з репозиторію.
- Розуміти, який інструмент у якому уроці знадобиться.
🔑 Ключові терміни
- Реверс-інжиніринг: вивчення готової програми без вихідного коду, щоб зрозуміти, як вона працює.
- Чіт (cheat): програма, що змінює поведінку гри на користь гравця.
- Тренер (trainer): окремий процес, який читає і змінює пам'ять гри.
- Інжектор (injector): код, який завантажується всередину процесу гри.
- Адресний простір: набір віртуальних адрес, які бачить один процес.
- Сторінка (page): блок пам'яті, зазвичай 4 КБ (на Apple Silicon 16 КБ), з однаковими правами доступу.
- Купа (heap): область, звідки береться пам'ять для
newіmalloc. - PID: числовий ідентифікатор процесу.
- Сканер пам'яті: програма, що шукає у процесі всі місця із заданим значенням.
- Налагоджувач (debugger): зупиняє процес, показує регістри, пам'ять та інструкції.
- Дизасемблер: перетворює машинний код в асемблер.
Що таке реверс-інжиніринг і з чого починається практика
Програма, яку ви запускаєте, — це машинний код і дані в пам'яті. Вихідного коду в користувача немає, але гра зберігає здоров'я, набої та координати в оперативній пам'яті, а процесор виконує зрозумілі команди. Реверс-інжиніринг навчає знаходити ці дані й команди та розуміти, що вони означають.
Де це застосовують
- Аналіз шкідливого коду. Аналітик розбирає вірус, щоб написати для нього захист.
- Безпека. Пошук вразливостей у програмах, для яких нема коду.
- Сумісність. Підтримка старого ПЗ і драйверів, документація яких загубилася.
- Моддинг і навчання. Розширення ігор, дослідження того, як працюють їхні механіки.
- Розробка антічітів. Щоб захистити гру, треба знати, як її ламають.
Ігри обирають для навчання, бо результат видно одразу: змінили число в пам'яті, і здоров'я на екрані змінилося.
Правові та етичні межі
Правило курсу: усі експерименти виконуються лише над програмами, які ви запускаєте локально й дозволяєте досліджувати:
- Власна гра-мішень з цього курсу, її код ми пишемо самі.
- AssaultCube — вільна гра з відкритим кодом, створена для спільного тренування. Запускаємо її тільки в одиночному режимі або на власному сервері.
Те, що ви навчитеся робити, застосовується однаково, але проти чужих серверів курс це не використовує.
Огляд курсу
Пам'ять і процеси
Як програма зберігає дані, чому один процес не бачить пам'ять іншого і як ОС дозволяє це обійти для налагодження.
Інструменти
Cheat Engine, x64dbg, GDB, LLDB, власний сканер на C++.
Структури, зміщення, ланцюжки вказівників
Як із випадкової адреси перейти до стабільного способу знайти потрібне значення після перезапуску.
Асемблер і налагоджувач
Хто саме змінює здоров'я: знаходимо інструкцію, читаємо її, змінюємо.
Тренер і internal-чіт
Зовнішня програма, яка пише в пам'ять гри, і бібліотека, що завантажується всередину процесу (DLL, LD_PRELOAD, dylib).
AssaultCube
Усе вивчене застосовуємо до реальної гри на Windows, Linux і macOS.
Підготовка
Потрібне знання C++ на рівні вказівників і структур. Достатньо тем курсу C++ про вказівники й структури. Код лабораторних лежить у репозиторії в labs/reverse-engineering/.
gcc/clang, cmake, gdb. Для Windows — Visual Studio Build Tools або MinGW і Cheat Engine. Детальне встановлення описано в розділі «Інструменти» нижче.Процеси, віртуальна пам'ять і доступ до чужого процесу
Коли гра виконує new Player, вона отримує адресу на кшталт 0x103231a70. Це віртуальна адреса: її бачить лише цей процес, а ядро ОС відображає її на реальну фізичну пам'ять. Інший процес із такою самою адресою звертається до власних даних.

Звідси два наслідки. Тренер не може просто прочитати вказівник гри. Йому потрібен дозвіл ядра: спеціальний виклик, який каже «прочитай N байтів за адресою A у процесі з PID X».
З чого складається процес
| Область | Що там лежить | Права |
|---|---|---|
Код (.text) | машинні інструкції | читання, виконання |
Дані (.data, .bss) | глобальні й статичні змінні | читання, запис |
| Купа | об'єкти з new/malloc | читання, запис |
| Стек | локальні змінні, адреси повернення | читання, запис |
| Бібліотеки | код і дані системних та сторонніх бібліотек | залежить від секції |
Глобальні змінні гри мають стабільну адресу відносно початку програми. Об'єкти в купі (гравець, вороги) отримують нову адресу при кожному запуску. Різниця між цими двома випадками — основа розділу про ланцюжки вказівників.
Як прочитати пам'ять іншого процесу
HANDLE h = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
FALSE, pid);
int32_t hp;
ReadProcessMemory(h, (LPCVOID)addr, &hp, sizeof(hp), nullptr);
iovec local{&hp, sizeof(hp)};
iovec remote{(void*)addr, sizeof(hp)};
process_vm_readv(pid, &local, 1, &remote, 1, 0);
mach_port_t task;
task_for_pid(mach_task_self(), pid, &task);
mach_vm_size_t got;
mach_vm_read_overwrite(task, addr, sizeof(hp), (mach_vm_address_t)&hp, &got);
Схема однакова: отримати дозвіл на процес (дескриптор, pid, mach-порт), потім читати й писати байти за адресою. Різниця лише в умовах отримання дозволу.
OpenProcess працює для процесів того ж користувача, якщо їх не захищає антічіт. На Linux діє ptrace_scope: за значення 1 читати можна лише власних нащадків, тому або запускайте гру з тренера, або виконайте sudo sysctl kernel.yama.ptrace_scope=0 на навчальній машині. На macOS task_for_pid потребує sudo (root) або підписаного налагоджувача, а програми з hardened runtime та системні недоступні навіть root.Ці обмеження існують навмисно: вони не дають довільній програмі лізти в чужі процеси. У нашому курсі гра й тренер збираються локально без hardened runtime, тому достатньо sudo.
Інструменти: що встановити на Windows, Linux і macOS
Набір інструментів
| Задача | Windows | Linux | macOS |
|---|---|---|---|
| Сканер пам'яті | Cheat Engine | scanmem / GameConqueror | власний сканер (trainer scan) |
| Налагоджувач | x64dbg | GDB | LLDB |
| Дизасемблер | Ghidra, x64dbg | Ghidra, objdump | Ghidra, objdump -d |
| Компілятор | MSVC / MinGW | GCC / Clang | Apple Clang |
Cheat Engine працює лише на Windows. На Linux і macOS ту саму ідею виконують scanmem та власний сканер, який є в репозиторії. Ghidra — безкоштовний дизасемблер, однаковий на всіх ОС.
- Cheat Engine: під час встановлення відмовтеся від додаткових пропозицій.
- x64dbg.
- Visual Studio Build Tools або MinGW і
cmake.
sudo apt install build-essential cmake gdb scanmem
sudo sysctl kernel.yama.ptrace_scope=0 # лише на навчальній машині
xcode-select --install
brew install cmake
lldb входить до Xcode Command Line Tools.
Збірка гри-мішені та тренера
cd labs/reverse-engineering/target-game
cmake -S . -B build && cmake --build build
./build/target_game
cd labs/reverse-engineering/trainer
cmake -S . -B build && cmake --build build
Гра виводить свій PID і команди керування. З параметром --show-addr вона додатково друкує адреси Game* та Player*. Це підказка для самоперевірки; у перших розділах параметр не вмикайте.
task_for_pid потрібен sudo. Запускайте з підвищеними правами лише збірки, які ви зробили самі.trainer scan.Бібліотеки C++: cpp-httplib, cxxopts, CLI11, Google Test і Catch2
HTTP-сервер і клієнт на cpp-httplib з JSON API, розбір аргументів командного рядка у cxxopts та CLI11, юніт-тестування в Google Test і Catch2 v3. Підключення через vcpkg, перевірені приклади та реальні виводи.
Пошук даних у пам'яті: сканування, структури, ланцюжки вказівників
Сканування значень, зміщення полів структури та ланцюжки вказівників, що переживають перезапуск гри.