Инженерный кейс
Автоматизация игрового клиента
Связка из панели, агента и клиентского модуля: выполняет игровые действия без человека и скрывает от клиента признаки того, что машина ему уже знакома.
- части и общий слой
- 3
- бита обязательно
- 32
- описание протокола
- 1
Три части: панель, агент-загрузчик на машине и модуль внутри игрового процесса с наложенным интерфейсом. Модуль выполняет игровые действия без человека; идентификаторы оборудования при этом подменяются на уровне системных запросов — без этого клиент узнаёт машину.
Три части, одно описание протокола
Панель, агент и клиентский модуль — разные исполняемые файлы с разным жизненным циклом. Всё общее вынесено в отдельный слой заголовков: протокол запуска, работа с окружением, журнал, обработчик падений.
Так описание живёт в одном месте на три части. Три собственные реализации разъехались бы на первом же изменённом поле — и разъезд обнаружился бы не при сборке, а во время работы, когда одна часть уже не понимает другую.
Запуск — это рукопожатие, а не ожидание вслепую
Пути, каталог журналов, адрес прокси и признаки подмены передаются модулю через переменные окружения, а готовность сторон — через именованные события: агент говорит «я готов», клиентский модуль — «я загрузился».
Очевидный путь — подождать секунду и продолжить — ломается на медленной машине и на быстрой: в первом случае рано, во втором зря потеряно время. Событие снимает вопрос: ждём ровно до готовности.
Сборка принудительно 32-битная, и об этом предупреждает сама сборка
Игровой клиент 32-битный, значит и модуль обязан быть таким же. В настройках сборки стоит проверка: если выбрана другая разрядность, выдаётся предупреждение прямо при конфигурации.
Иначе ошибка всплывает поздно и выглядит непонятно — сборка проходит, а модуль просто не грузится в чужой процесс. Час на поиск против одной строки предупреждения.
Свой обработчик падений
Падение внутри чужого процесса не оставляет пригодного отчёта: игра просто закрывается. Поэтому в общий слой добавлен собственный обработчик — снимок памяти через системную библиотеку отладки, перехват необработанных исключений, ошибок выделения памяти и сигналов, и свой журнал рядом.
Без него единственным свидетельством сбоя было бы «у меня всё закрылось».
Интерфейс живёт внутри игры
Наложенный интерфейс собран на Dear ImGui и рисуется прямо в окне игры, а перехват точек входа сделан через MinHook. Обе библиотеки подтягиваются сборкой по фиксированной версии — не «последняя из сети», а конкретный тег.
Для проекта, который живёт годами и собирается редко, это разница между «собралось как тогда» и «собралось неизвестно из чего».
Трафик каждой копии идёт своим маршрутом
В общем слое есть клиент прокси, SOCKS5 и запуск туннеля: каждая копия выходит в сеть своим путём. Это часть той же задачи — машины должны выглядеть независимыми, а не одной.
Что сделано на скорую руку
Имена переменных окружения для подмены продублированы в двух заголовках, чтобы разорвать циклическое включение, и синхронизируются руками. В коде на это стоит прямая пометка — но проверки, что они не разъехались, нет.
C++20 · CMake · MSVC · Dear ImGui · MinHook · Windows API