На самом деле VMProtect не такой уж и крутой протектор, его фишкой является возможность обфускации кода или интерпритация на собственных виртуальных машинах, такое сложно исследовать и патчить, так как условный переход может быть размазан на десяток ветвлений и т.п.
А разве boost.mpi билдится с intel'евской либой? Как то пробывал собрать буст с Microsoft MPI, пришлось пилить напильником скрипты инсталяции буста, т.к. он не саппортил последние версии msmpi
Ну вы уже задели филосовский вопрос. Я нигде не обещал что защита будет полной, всё это в некоторый степени эвристика. К таму же пока операционные системы не предоставляют средств защиты кода приложений, хороших подходов к юзермодным защитам быть не может.
100+ версий DirectX под разные платформы, будете составлять базу, сверять по ней и перепатчивать ее?
Зачем составлять базу, вы думаете контрольные суммы собираются заранее?) Контрольная сумма снимается во время старта процесса из памяти либо из исполняемого файла на диске который был загружен игрой. Тут нет разницы какая версия библиотеки используется, зная её виртуальный интерфейс бинарная реализация нас не интересует.
На все остальные вопросы ответ будет следующим: «За последние 4 года на battle.net сервере, я ни разу не получил бан или предупреждение».
Первоначально вы спросили как бы я это обнаружил, я вам ответил, речь не идёт про какие-то реализации защит.
Почему вы решили что защита знать не должна каким может быть метод EndScene? И если вы получили указатель на него почему защита не может сделать также? Я уже объяснил выше как определить наличие патча кода, будь то виртуальный метод или экспорт, разница лишь в способе получения адреса.
Другой вопрос это определение модификаций в виртуальной таблице методов, там нельзя однозначно определить является перегрузка законной или нет.
А какое отношение версия библиотеки имеет к нашей контрольной сумме? Мы же знаем имя или ординал импортируемой функции, поэтому берём и парсим структуры экспорта в критической библиотеке, находим там rva нужной функции и плюсуем его к базе модуля. Обычно меняется внутренняя реализация библиотеки, интерфейс же статичен. Контрольная сумма снимается согласно данным из текущего загруженного модуля в простом случае, либо из его файла на диске (с учётом релоков и т.п. конечно) в продвинутом случае.
Если мы защита и например мы натыкаемся на нарушенную контрольную сумму (к примеру jmp на функцие EndScene), то мы можем сказать что это детект чита, либо мы можем промолчать и восстановить оригинальное содержимое функции, тем самым выпнув стороннюю логику.
UPD: Все контрольные суммы снимаются из процесса игры, они не предопределены
Если Вы не заметили, то только инъекции написаны на ассемблере, а все остальное на C#. И кстати о бизнес логике хочу сказать, что на C# проще контролировать потоки чем в С++.
Не понял о чем вы, но это ваше субьективное мнение не стану спорить.
Детектили патч в памяти 3-rd party библиотеки? Каким образом? Написали бы к игре еще и дизасемблер с отладчиком? Повторюсь. Я предпочитаю конструктивную критику. Расскажите пожалуйста.
Да ради бога :) С точки зрения защиты игры есть ряд библиотек поведение которых может повлиять на игровую логику, это системные библиотеки Kernel32, KernelBase, User32, Ntdll и т.п., графические библиотеки относящиеся к OpenGL, DirectX и возможно какие-то собственные библиотеки, распостраняющиеся с игрой. Имена этих библиотек нам за ранее извесны, будем их называть критическими (поведение остального кода в процессе нас не интересует). Так вот как детектится изменение в критических библиотеках. Анализируется импорт модулей игры и собирается список импортируемых функций из критических библиотек, снимается контрольная сумма с первых байт импортируемых функций, снимается контрольная сумма с таблицы экспорта критических библиотек. После чего защита должна переодически проверять эти контрольные суммы. Но это очень упращенный вариант реализации, тут есть подводные камни.
Складывается ощущение, что у людей при слове ассемблер начинается паническая атака, закладывает уши и отключается мозг. Не нужно его боятся на столько, он не так страшен. Ведь что может быть проще, чем попросить саму программу выполнить свою же функцию и результат поместить по указателю который вы знаете? Не нужно изобретать велосипед, я использую, то что есть
Предположим мы пишем чит (или бот как вам удобнее). Мы умеем перехватывать управление, но помимо этого у нас присутствует бизнес-логика самого чита и чем больше его функциональность, тем больше бизнес логики. Вот я хочу к примеру добавить в свой чит возможность его включения и отключения на кнопку F8, сколько строк кода это займёт на ассемблере и насколько легко будет такой код писать и сопровождать?
Потом какова цель мутации кода? Я знаю что античит может сканировать память загруженого модуля, но врятли он будет сканировать простые секции. Если бы передо мной стояла задача детекта вашего чита, я бы детектил патч в памяти но никак не код чита. Я уже писал что поиск по памяти это неэффективный костыль, сигнатура скорее всего вещается на статический оффсет, такое обходится и без ассемблера
Просто попробуйте сами, прочитать из памяти не убивая Windows-сервис.
Очевидно сервис использует какие-то дополнительные трюки, вроде инжекта или драйвер.
Что вы имеете ввиду под «внутренними функциями»? Вот что вы писали в своей первый статье:
Определенно нам необходимо внедрить код в процесс игры, который и будет ей управлять. Для это можно модифицировать сам исполняемый файл (это очень легко сделать, но и легко определить и получить бан) или внедрить DLL (это тоже определяется очень просто), но это все не для нас. Наш подход — это внедрение кода, в главный поток процесса, получающего управление и возвращающего его обратно.
если я правильно понял, тут идёт речь о коде чита, а не только о перехватчике управления.
К таму же не совсем понятно почему именно используется трюк с перехватом управления из EndScene(), реализация требует регулярного перехвата управления?
4. Защита игровой памяти от чтения/записи
Данным функционалом обладает набирающая популярность в Steam защита Easy Anti Cheat. В Windows запускается сервис EasyAntiCheat, который защищает память игры от чтения и записи. Если же сервис не запущен, то игра отказывается соединяться с сервером и хотелось бы услышать размышления хабрасообщества на этот счет.
Интересно как оно может защитать память через сервис? Тут на сколько я понимаю либо драйвер, либо это глупость (либо я чего-то не знаю)
Вообще с точки зрения защиты, нет необходимости сканировать процессы и модули на наличие запрещённого кода, как показывает опыт антивирусных компаний эта игра в кошки мышки заранее проиграна. ИМХО для защиты игр необходимо анализировать дефекты окружения, например перехваты системных функций, модификацию кода игровых модулей и т.п., всё остальные «эвристики» которые разрабы пихают в защиты порой представляют из себя такое варворство, что не хочется ставить игру с такой защитой ибо это не безопасно.
Что косается статьи, мне кажется писать чит на ассемблере крайне сложно, особенно если логики много. Лично я бы лучше написал его на С\С++ в качестве библиотеки и спроецировал бы чит собственным загрузчиком, без внесения модуля в список LDR_MODULE, для маскировки можно затереть PE заголовок и т.д.
Никто не гарантирует что пролог будет во всех бинарниках одинаковым и будет начинатся именно с конкретной инструкции, это нигде не документировано и не факт что вы не нарвётесь на уже установленный хук. Конечно оно может работать и так, но это всёравно будет не корректная реализация(см. реализацию движков перехватчиков). Что касается готового дизассемблера длин, то на ASM\С\С++ с этим проблем нету, как на дела обстаят на .net я не в курсе.
Для таких целей используют дизассемблер длин, иначе нет никакой горантии что пролог функции не будет повреждён. Вы ведь не имеете 100% представления сколько инструкций будут перезаписаны
Первоначально вы спросили как бы я это обнаружил, я вам ответил, речь не идёт про какие-то реализации защит.
Другой вопрос это определение модификаций в виртуальной таблице методов, там нельзя однозначно определить является перегрузка законной или нет.
Если мы защита и например мы натыкаемся на нарушенную контрольную сумму (к примеру jmp на функцие EndScene), то мы можем сказать что это детект чита, либо мы можем промолчать и восстановить оригинальное содержимое функции, тем самым выпнув стороннюю логику.
UPD: Все контрольные суммы снимаются из процесса игры, они не предопределены
Да ради бога :) С точки зрения защиты игры есть ряд библиотек поведение которых может повлиять на игровую логику, это системные библиотеки Kernel32, KernelBase, User32, Ntdll и т.п., графические библиотеки относящиеся к OpenGL, DirectX и возможно какие-то собственные библиотеки, распостраняющиеся с игрой. Имена этих библиотек нам за ранее извесны, будем их называть критическими (поведение остального кода в процессе нас не интересует). Так вот как детектится изменение в критических библиотеках. Анализируется импорт модулей игры и собирается список импортируемых функций из критических библиотек, снимается контрольная сумма с первых байт импортируемых функций, снимается контрольная сумма с таблицы экспорта критических библиотек. После чего защита должна переодически проверять эти контрольные суммы. Но это очень упращенный вариант реализации, тут есть подводные камни.
Потом какова цель мутации кода? Я знаю что античит может сканировать память загруженого модуля, но врятли он будет сканировать простые секции. Если бы передо мной стояла задача детекта вашего чита, я бы детектил патч в памяти но никак не код чита. Я уже писал что поиск по памяти это неэффективный костыль, сигнатура скорее всего вещается на статический оффсет, такое обходится и без ассемблера
Что вы имеете ввиду под «внутренними функциями»? Вот что вы писали в своей первый статье:
если я правильно понял, тут идёт речь о коде чита, а не только о перехватчике управления.
К таму же не совсем понятно почему именно используется трюк с перехватом управления из EndScene(), реализация требует регулярного перехвата управления?
Интересно как оно может защитать память через сервис? Тут на сколько я понимаю либо драйвер, либо это глупость (либо я чего-то не знаю)
Вообще с точки зрения защиты, нет необходимости сканировать процессы и модули на наличие запрещённого кода, как показывает опыт антивирусных компаний эта игра в кошки мышки заранее проиграна. ИМХО для защиты игр необходимо анализировать дефекты окружения, например перехваты системных функций, модификацию кода игровых модулей и т.п., всё остальные «эвристики» которые разрабы пихают в защиты порой представляют из себя такое варворство, что не хочется ставить игру с такой защитой ибо это не безопасно.
Что косается статьи, мне кажется писать чит на ассемблере крайне сложно, особенно если логики много. Лично я бы лучше написал его на С\С++ в качестве библиотеки и спроецировал бы чит собственным загрузчиком, без внесения модуля в список LDR_MODULE, для маскировки можно затереть PE заголовок и т.д.