Комментарии 20
Поправочка на счет EasyAntiCheat.
Это клиент-серверное приложение. На сервер установлено приложение, модуль которого внедрен в процесс сервера игры, и которое проверяет соединилась ли программа с этого клиента (который зашел на сервер), и, если да, то оставляет клиента. Если нет — выкидывает средствами игры (kick, ban и т.д.).
Remark: EasyAntiCheat Client — программа, которая запускается параллельно игре и занимается проверкой процесса игры на внедрение, проверяет эвристикой запущенные процессы у пользователя, а так же с рандомным интервалом (но не реже раза в минуту) отсылает на сервер скриншот экрана пользователя.
Читы которые работают с EasyAntiCheat (а таких, с которым EAC еще не может совладать по сути всего один) работают на компьютере в качестве и файрволла тоже. Он дает соединится с сервером, а потом блокирует его работу в интернет, поскольку античит позволяет терять коннект на срок от 30 секунд до 1 минуты, опять же рандомно (я так понимаю, что это связанно с особенностями UDP, чтобы не было проблем при нестабильном канале). Более того, он читает момент снятия скриншота с экрана и подсовывает его античиту. Подробностей, к сожалению, не знаю, поскольку я нахожусь со стороны античита, а не тех, кто создает читы.
Это клиент-серверное приложение. На сервер установлено приложение, модуль которого внедрен в процесс сервера игры, и которое проверяет соединилась ли программа с этого клиента (который зашел на сервер), и, если да, то оставляет клиента. Если нет — выкидывает средствами игры (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, и хотелось бы немножко спойлера: в итоге то, работает или нет? )))
Хинт: можно захостить в процессе игры CLR и в него из памяти прогрузить свою сборку. Античиты будут видеть только системные библиотеки с подписью MS.
И чит-аналитики из близзарда сидят, такие, смотрят снапшоты окружения, ха, подумаешь, mscoree с нами, это же MS, можно доверять. На самом деле, идея крутая, во многих случаях может дать профит.
Странная у вас обфускация, разбавление константного кода константным же мусором ИМХО ничего не даст, как только разработчики античитов прознают о вашем приложении ничто им не помешает натаскать сканер конкретно на ваш мусор, он-то неизменен.
Как по мне, нужен генератор мусора(и не только мусора), который при каждом запуске будет выдавать разный код, сделать хотя бы замену команд по некоторому набору правил, например:
можно превратить в
или
или ещё можно сделать так
И так далее
Хотя вас всё равно можно отследить по безусловному переходу в начале функции который указывает за пределы модуля в котором эта функция расположена.
Как по мне, нужен генератор мусора(и не только мусора), который при каждом запуске будет выдавать разный код, сделать хотя бы замену команд по некоторому набору правил, например:
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 для игры, который рисует в вашем окне?
Хотя вас всё равно можно отследить по безусловному переходу в начале функции который указывает за пределы модуля в котором эта функция расположена.
Согласен, но вот, что делает программа по безусловному переходу? Вдруг это fraps или еще какой overlay для игры, который рисует в вашем окне?
4. Защита игровой памяти от чтения/записи
Данным функционалом обладает набирающая популярность в Steam защита Easy Anti Cheat. В Windows запускается сервис EasyAntiCheat, который защищает память игры от чтения и записи. Если же сервис не запущен, то игра отказывается соединяться с сервером и хотелось бы услышать размышления хабрасообщества на этот счет.
Интересно как оно может защитать память через сервис? Тут на сколько я понимаю либо драйвер, либо это глупость (либо я чего-то не знаю)
Вообще с точки зрения защиты, нет необходимости сканировать процессы и модули на наличие запрещённого кода, как показывает опыт антивирусных компаний эта игра в кошки мышки заранее проиграна. ИМХО для защиты игр необходимо анализировать дефекты окружения, например перехваты системных функций, модификацию кода игровых модулей и т.п., всё остальные «эвристики» которые разрабы пихают в защиты порой представляют из себя такое варворство, что не хочется ставить игру с такой защитой ибо это не безопасно.
Что косается статьи, мне кажется писать чит на ассемблере крайне сложно, особенно если логики много. Лично я бы лучше написал его на С\С++ в качестве библиотеки и спроецировал бы чит собственным загрузчиком, без внесения модуля в список LDR_MODULE, для маскировки можно затереть PE заголовок и т.д.
Поддерживаю, а если совсем уж не хочется вставлять в процесс свою длл то можно написать на том-же с/с++ базонезависимые функции и тупо налету копировать их из своего процесса в целевой. Таким образом получаются легко модифицируемые куски, а не readonly ассемблер.
Единственное что в таком способе будет сложнее так это сделать мутацию кода налету, хоть и не невозможно. Хотя лично я сомневаюсь в целесообразности вообще каких либо мутаций проще мимикрировать под легальную длл, например взять и собрать свою длл-прокси d3d9.dll и положить в папку с игрой. Тогда не будет всякой магии с джампами из начала функции сразу за пределы модуля(модуль то свой), не придётся ничего патчить(за исключением разве что игровых методов).
Серьёзно в любой программе присутствует куча посторонних модулей напрямую к программе не относящихся, вот например что обнаружилось в обычном np++
Единственное что в таком способе будет сложнее так это сделать мутацию кода налету, хоть и не невозможно. Хотя лично я сомневаюсь в целесообразности вообще каких либо мутаций проще мимикрировать под легальную длл, например взять и собрать свою длл-прокси 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) потоконебезопасны — будучи вызванными из других потоков, они либо просто не сработают, либо приведут к крэшу всей игры.Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Пишем бота для MMORPG с ассемблером и дренейками. Часть 2