Как стать автором
Обновить

Комментарии 20

Поправочка на счет EasyAntiCheat.
Это клиент-серверное приложение. На сервер установлено приложение, модуль которого внедрен в процесс сервера игры, и которое проверяет соединилась ли программа с этого клиента (который зашел на сервер), и, если да, то оставляет клиента. Если нет — выкидывает средствами игры (kick, ban и т.д.).
Remark: EasyAntiCheat Client — программа, которая запускается параллельно игре и занимается проверкой процесса игры на внедрение, проверяет эвристикой запущенные процессы у пользователя, а так же с рандомным интервалом (но не реже раза в минуту) отсылает на сервер скриншот экрана пользователя.

Читы которые работают с EasyAntiCheat (а таких, с которым EAC еще не может совладать по сути всего один) работают на компьютере в качестве и файрволла тоже. Он дает соединится с сервером, а потом блокирует его работу в интернет, поскольку античит позволяет терять коннект на срок от 30 секунд до 1 минуты, опять же рандомно (я так понимаю, что это связанно с особенностями UDP, чтобы не было проблем при нестабильном канале). Более того, он читает момент снятия скриншота с экрана и подсовывает его античиту. Подробностей, к сожалению, не знаю, поскольку я нахожусь со стороны античита, а не тех, кто создает читы.
srsly? Вот так просто скриншот экрана? А если я в это время порс банковскими данными работаю, а игрушка на фоне свёрнута?
Раньше иногда бывали всякие инсинуации. Но уже более двух лет EAC определяет развернутость fullscreen приложения (раз) и приложение в фокусе (два) и не отсылает скриншоты вне указанных ситуаций. Ну, и конечно, любой, кто скачивает и использует ПО EAC конечно же согласен с лицензионным соглашением, где явно написано на восьми (сейчас может уже больше) языках, в том числе и русском, о том, что во время работы могут быть отосланы скриншоты экрана и это является прямым функционалом программы.
В народе это называется «анальный зонд».
Совершенно верно, клиент-серверное, я и не утверждал чего-то иного, так как знаю это
namespace EasyAntiCheat.Game.Launcher
{
    internal static class Program
    {
        private static void CopyOldOutputLog()
        {
            if (!File.Exists("AwesomeGame_Data/output_log.txt"))
            {
                return;
            }
            if (File.Exists("AwesomeGame_Data/output_log.last"))
            {
                File.Delete("AwesomeGame_Data/output_log.last");
            }
            File.Copy("AwesomeGame_Data/output_log.txt", "AwesomeGame_Data/output_log.last");
        }

        private static void Main(string[] args)
        {
            Program.CopyOldOutputLog();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Loader loader = new Loader(12, "AwesomeGame.exe", null);
            loader.Options.Installer.Allow = true;
            loader.Options.Arguments = string.Join(" ", args);
            loader.Progress += new EventHandler<LoadProgressEventArgs>(Program.OnLaunchProgress);
            loader.Completed += new EventHandler<LoadCompletedEventArgs>(Program.OnLaunchCompleted);
            loader.BeginLoad();
            while (!loader.HasCompleted())
            {
                Thread.Sleep(100);
            }
        }

        private static void OnLaunchCompleted(object sender, LoadCompletedEventArgs eventArgs)
        {
            if (eventArgs.Status == LoadExitCode.Success)
            {
                return;
            }
            MessageBox.Show(string.Format("AwesomeGame Launcher Error: {0} - {1}", eventArgs.Status, eventArgs.Message));
        }

        private static void OnLaunchProgress(object sender, LoadProgressEventArgs eventArgs)
        {
        }
    }
}


Но ее сервис, на стороне клиента, который висит в процессах и не дает просто так читать память из Ring3 немного раздражает… Вот в чем вопрос.
Судя по серии статей, автор уже давно реализовал рабочую версию бота для WoW, и хотелось бы немножко спойлера: в итоге то, работает или нет? )))
Могу предположить, что бот для 5.4 не будет работать в 6.*, технически много чего изменилось
Хинт: можно захостить в процессе игры CLR и в него из памяти прогрузить свою сборку. Античиты будут видеть только системные библиотеки с подписью MS.
И чит-аналитики из близзарда сидят, такие, смотрят снапшоты окружения, ха, подумаешь, mscoree с нами, это же MS, можно доверять. На самом деле, идея крутая, во многих случаях может дать профит.
CLR в процессе может очень многими разными путями оказаться на самом деле. Особенно если игра по каким-то причинам решила где-то использовать движок от IE.
Странная у вас обфускация, разбавление константного кода константным же мусором ИМХО ничего не даст, как только разработчики античитов прознают о вашем приложении ничто им не помешает натаскать сканер конкретно на ваш мусор, он-то неизменен.
Как по мне, нужен генератор мусора(и не только мусора), который при каждом запуске будет выдавать разный код, сделать хотя бы замену команд по некоторому набору правил, например:

ADD EAX, 3

можно превратить в
SUB EAX,-2
INC EAX

или
PUSH EAX
XOR EAX,EAX
MOV EAX,2
INC EAX
ADD EAX,DWORD PTR SS:[ESP]
ADD ESP,4

или ещё можно сделать так

полезный код
jmp lb
мусорные инструкции, рандомный набор, всё равно не выполняются
lb:
полезный код

И так далее

Хотя вас всё равно можно отследить по безусловному переходу в начале функции который указывает за пределы модуля в котором эта функция расположена.
Совершенно верно, я просто показал идею, а что туда вставлять, это уже ограничит только ваша фантазия.
Хотя вас всё равно можно отследить по безусловному переходу в начале функции который указывает за пределы модуля в котором эта функция расположена.

Согласен, но вот, что делает программа по безусловному переходу? Вдруг это fraps или еще какой overlay для игры, который рисует в вашем окне?
4. Защита игровой памяти от чтения/записи
Данным функционалом обладает набирающая популярность в Steam защита Easy Anti Cheat. В Windows запускается сервис EasyAntiCheat, который защищает память игры от чтения и записи. Если же сервис не запущен, то игра отказывается соединяться с сервером и хотелось бы услышать размышления хабрасообщества на этот счет.

Интересно как оно может защитать память через сервис? Тут на сколько я понимаю либо драйвер, либо это глупость (либо я чего-то не знаю)

Вообще с точки зрения защиты, нет необходимости сканировать процессы и модули на наличие запрещённого кода, как показывает опыт антивирусных компаний эта игра в кошки мышки заранее проиграна. ИМХО для защиты игр необходимо анализировать дефекты окружения, например перехваты системных функций, модификацию кода игровых модулей и т.п., всё остальные «эвристики» которые разрабы пихают в защиты порой представляют из себя такое варворство, что не хочется ставить игру с такой защитой ибо это не безопасно.

Что косается статьи, мне кажется писать чит на ассемблере крайне сложно, особенно если логики много. Лично я бы лучше написал его на С\С++ в качестве библиотеки и спроецировал бы чит собственным загрузчиком, без внесения модуля в список LDR_MODULE, для маскировки можно затереть PE заголовок и т.д.
Поддерживаю, а если совсем уж не хочется вставлять в процесс свою длл то можно написать на том-же с/с++ базонезависимые функции и тупо налету копировать их из своего процесса в целевой. Таким образом получаются легко модифицируемые куски, а не readonly ассемблер.
Единственное что в таком способе будет сложнее так это сделать мутацию кода налету, хоть и не невозможно. Хотя лично я сомневаюсь в целесообразности вообще каких либо мутаций проще мимикрировать под легальную длл, например взять и собрать свою длл-прокси d3d9.dll и положить в папку с игрой. Тогда не будет всякой магии с джампами из начала функции сразу за пределы модуля(модуль то свой), не придётся ничего патчить(за исключением разве что игровых методов).
Серьёзно в любой программе присутствует куча посторонних модулей напрямую к программе не относящихся, вот например что обнаружилось в обычном np++
левые модули
RocketDo         D:\Programs\RocketDock\RocketDock.dll
libgit23             C:\Program Files\TortoiseGit\bin\libgit232.dll
zlib132             C:\Program Files\TortoiseGit\bin\zlib132.dll
gitdll32             C:\Program Files\TortoiseGit\bin\gitdll32.dll
Tortoi_1           C:\Program Files\TortoiseGit\bin\TortoiseGit32.dll
Tortoise           C:\Program Files (x86)\Common Files\TortoiseOverlays\TortoiseOverlays.dll

Просто попробуйте сами, прочитать из памяти не убивая Windows-сервис.
А что касается чита на ассемблере, то во-первых — это не чит, во-вторых, ассемблер нужен лишь для вызова внутренних функций и что сложно, а что просто решает каждый сам для себя:
"call " + GetAnyGameObjectFunctionPointer,
"push " + argument3Pointer,
"push " + argument2Pointer,
"push " + argument1Pointer,
"push " + argument0Pointer,
"mov ecx, eax",
"call " + DoAnythingFunctionPointer,
"retn"

Это разве сложно?
Непереносимо. В x64 аргументы передаются иным способом. Да, я помню,
x64 очень легко получить из x86, пару бессонных ночей и готово
но этих бессонных ночей можно избежать, как говорится, in the first place. ;)
у меня занудодетектор сейчас зашкаливает!
Просто попробуйте сами, прочитать из памяти не убивая Windows-сервис.
Очевидно сервис использует какие-то дополнительные трюки, вроде инжекта или драйвер.

Что вы имеете ввиду под «внутренними функциями»? Вот что вы писали в своей первый статье:
Определенно нам необходимо внедрить код в процесс игры, который и будет ей управлять. Для это можно модифицировать сам исполняемый файл (это очень легко сделать, но и легко определить и получить бан) или внедрить DLL (это тоже определяется очень просто), но это все не для нас. Наш подход — это внедрение кода, в главный поток процесса, получающего управление и возвращающего его обратно.
если я правильно понял, тут идёт речь о коде чита, а не только о перехватчике управления.

К таму же не совсем понятно почему именно используется трюк с перехватом управления из EndScene(), реализация требует регулярного перехвата управления?

Очевидно сервис использует какие-то дополнительные трюки, вроде инжекта или драйвер.

Не имеет значения, есть сервис — чтение невозможно из Ring3, нет сервиса — чтение есть, но играть нельзя. Вот и вся суть.
если я правильно понял, тут идёт речь о коде чита, а не только о перехватчике управления.

Вы совершенно не правильно поняли.
К таму же не совсем понятно почему именно используется трюк с перехватом управления из EndScene(), реализация требует регулярного перехвата управления?

FrameLock, знаете что такое?
К таму же не совсем понятно почему именно используется трюк с перехватом управления из EndScene()
Конкретно в WoW основная причина того, почему требуется перехват EndScene, связана не с пересчётом мира, а в том, что EndScene вызывается из «основного» потока игры. А все или большинство функций, представляющих интерес (передвижение, каст фаерболов, Lua) потоконебезопасны — будучи вызванными из других потоков, они либо просто не сработают, либо приведут к крэшу всей игры.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории