понедельник, 3 марта 2014 г.

Anti-cheat crackme или обход MuGuard.org

И снова здравствуйте. Это уже наша 3-я статья на тему реверс инжиниринга и взлома игровых защит. В этот раз, как я и обещал мы поговорим об очередной MuOnline защите MuGuard.org. Данная защита продаётся всего за 130-160$ и популярна на иностранных серверах. Забегая вперёд хочу сказать что сегодняшняя статья будет немного не обычной, в ней мы осуществим сразу две разные атаки на античит.


Этап 0×00. Разведка и подготовка

Исследовать защиту будем на 2х серверах http://muonline.com.ph и http://www.infinitymu.net. И начнём с Mu Philipines.

Античит состоит из 2х модулей muph.exe и main.dll, зашифрованного конфигурационного файла Mcfg.mac, оба модуля не упакованы что упрощает процесс взлома на 90%. Поскольку на сервер установлена версия игры MuEx700, сам клиент упакован. Дело в том, что азиаты (в частности это относится к Корейцам) проявили свою обдолбанность и без того тормазнутый движек MuOnline напихали статическими библиотеками и накрыли не менее тормознутым протектором. В итоге из вроде бы мелкой игры, получился монстр, который грузит ПК так, как будто запущено не MuOnline, а клиент Aion. Но к чему я веду, факт наличия протектора говорит о том, что внедрить библиотеку античита классическим путём (см. как это сделано в NS Engine Bypass) не получится. Следовательно для внедрения используется либо техника dll hijacking либо инжект в процесс. В нашем случае используется второй метод, поэтому игра запускается через muph.exe:



Когда библиотека античита загружена в main.exe, она выполняет расшифровку конфигурационного файла и помещает его в %TEMP%, c произвольным именем имеющим префикс M1. Расшифрованный конфигурационный файл имеет следующий вид:

[COMMON]
dllver = 1.2.1.6
muip = connect.infinitymu.net
musn = a0a1b6a2a3a0b4a6c9d4a1b214b3a3d2
csky = a2a5a4a7a3a6a8a8
mumv = :68:>
mupt = 44405
mucs = 129
muml = 0
muss = Photo
lname = mu.exe
muname = InfinityMU
nof11 = 1
mainver = 104j
mainlimit = 0
stamp = 1267022349
[PLUGIN]
llcs = Aeu7863jh90kja76
llsc = Aeu7863jh90kja76
ll3d = Aeu7863jh90kja76
[SECURITY]
llky = a763hfja87adh3HF
csm = main.exe
mctr = 2
checkagi = 1
checkbot = 0
multiclient = 0
notimechange = 0
mulr = 1
mugg = 0
csplugin = 1
scan1 = 1
scan2 = 1
scan3 = 1
scan5 = 1
scan8 = 1
scanht = 1hK135430h0Jz073
scanmod = 0
ctick = 1
ticklvl = 2
winxp = 0
vista = 0
win7 = 0
web = www.infinitymu.net/warning
sync = dll.infinitymu.net/sync
hmu = 0
[SUBIP]
count = 5
0 = 216.245.211.194
1 = 78.46.71.162
2 = 72.8.189.45
3 = connect.infinitymu.net
4 = 192.169.80.178
[BANKEYS]
f1 = 0
f2 = 0
f3 = 0
f4 = 0
f5 = 1
f6 = 1
f7 = 1
f8 = 0
f9 = 0
f10 = 0
f11 = 0
f12 = 0
[CLEARDIR]
xdir =
[CRCVALUE]
count = 16
0 = b687bf08
1 = 9238b264
2 = 16f1d9aa
3 = 1ad72866
4 = d0d9a81d
5 = 8c73e3ee
6 = 5339965e
7 = 88c417dd
8 = 7cc0297c
9 = ac7d77ca
10 = 42aa92d3
11 = 2290fc1a
12 = 36d22547
13 = 89d51f6c
14 = 8b2dba87
15 = 5b13a974
[CRCPATH]
0 = extra.dll
1 = glow_104j.dll
2 = llsc.exe
3 = mu.exe
4 = data\local\skill.bmd
5 = data\player\player.bmd
6 = data\world1\encterrain1.att
7 = data\world1\terrain1.att
8 = data\world4\encterrain4.att
9 = data\world4\terrain4.att
10 = muguard\llah.dll
11 = data\local\itemaddoption.bmd
12 = data\local\item.bmd
13 = vcorp.dll
14 = main.exe
15 = muguard\lldb.dat
[CLEARFILE]
count = 0
[eof]


Сама библиотека антчита содержит в ресурсах 4 исполняемых модуля. Один из которых .exe остальные три это разные версии одного и того же 32-битного драйвера. Как оказалось, на сервере Mu Philipines, античит не полностью включен и его комплектация отличается от той что идёт для сервера Infinity Mu:

llsc.exe — модуль для какой-то синхронизации
MuGuard\hvll.dll — библиотека античита
MuGuard\llck.sys — 32-битный драйвер
MuGuard\main.dat — конфигурационный файл
и т.д.

Причём в этой комплектации все файлы упакованы PECompact’ом. Несмотря на наличие драйвера, он не является основной частью защиты и на 64-битных системах его загрузка вообще не возможна. Вероятно он используется для детектирования HideTools, которая так же не работает на 64-битных системах.

Согласно данным из конфигурационных файлов, обе защиты имеют практически одинаковую версию библиотеки античита (1.2.1.7 и 1.2.1.6), поэтому распаковывать вторую библиотеку мы не будем и изучим алгоритмы работы используя не упакованную версию от Mu Philipines.

Теперь давайте взглянем на внутренности клиентской библиотеки античита. Как говорилось ранее, сперва библиотека выполняет расшифровку файла конфигураций. Далее происходит установка перехватчиков на некоторые WinAPI:



Перехватчики GetSturtupInfoA, GetCommandLineA используются для выполнения второй части инициализации в упакованных main.exe. Перехват ExitProcess используется для корректной выгрузки античита, а из CreateFileA перехватываются данные из каких-то bmd файлов. Winsock фукции используются в механизме авторизации с сервером.

Затем создается несколько рабочих потоков:



Так же в коде собирается информация о MAC адресе клиента:



это может говорить о наличии системы блокировки по MAC адресу, что конечно легко обходится.

Из описания продукта известно что для привязки к серверу используется так называемая система ConnectServer auth. Т.е. протокол ConnectServer’a инкапсулирует авторизацию античита, препятствуя отключению защиты в клиенте. Взглянем на дамп протокола:

send :: c1:06:a9:20:9c:2f
recv :: c1:04:00:01:b2:b0:a1
send :: c1:04:f4:06:74:52:67:67
recv :: c2:00:27:f4:06:00:08:00:00:30:00:01:00:32:00:02:00:63:00:03:00:3f:00:04:00:02:00:14:00:38:00:15:00:34:00:16:00:40:00

Не трудно заметить что в 2х пакетах присутствует инородный стаб (выделен красным). Получив какие-то данные античит на их основе генерирует ответ, который в последствии проверяется на серверной стороне.

Этап 0×01. Атака подменой конфигурации

Нам известно что часть функционала античита настраивается из конфигурационного файла. Если мы научимся создавать свои собственные конфигурационный файлы, то есть вероятность что таким образом получится отключить часть защиты. Давайте попробуем реализовать данную атаку.

Первоначально обратим внимание на то, что конфигурационный файл является ini-файлом, предварительно защифрованным. Это играет нам на руку, хотя бы по той причине, что исследовать его содержимое гораздо проще чем если бы это был бинарный файл. Всё что нам остаётся, это узичить алгоритм шифрования и написать свой распаковщик и упаковщик.

Подключив отладчик в процессу игры достаточно быстро на глаза попался алгоритм расшифровки конфигураций:



Как видно на рисунке процедура имеет множество логических операций, из неё вызываются не менее сложные логические подпроцедуры. Очевидно, что таким сложным самодельный алгоритм шифрования быть не может. Я пошел на хитрость и загуглил сообщения об ошибках, которые видны на рисунке выше и как оказалось не без результатно. Алгоритмом шифрования оказался blowfish, его код находится здесь:

http://commitmonitor.googlecode.com/svn/trunk/ext/BlowFish/BlowFish.cpp

Автор защиты воспользовался публичным кодом и тем самым позволил нам с легкостью заполучить его :) В качестве ключа шифрования используется жестко вписанный ключ 1M07HjhSse90Tlj3, который одинаков на обоих серверах.

Теперь дело остаётся за малым, написать програмку которая распаковывает и упаковывает ini-конфиг. Готовый код распаковщика ищите в конце статьи.

Используя подмену конфига, мы можем отключать различные защитные модули: привязку к лаунчеру, CRC сканирование файлов, CS авторизацию что в принципе позволяет угнать библиотеку античита для другого сервера и т.д.

Этап 0×02. Обход механизма ConnectServer auth

Выполнив распаковку конфига, нам удалось ослабить защиту, но не удалось её отключить полностью, поэтому нам необходимо найти другой более надёжный способ. В своих предыдущих статьях мы эмулировали через Mu Proxy Module шифрование и патчили библиотеку античита, обе техники можно пременить и для данного семпла, однако более универсальным будет именно прокси, которое будет эмулировать механизм ConnectServer auth, это самый идеальный способ обхода. Вообще авторизация на ConnectServer’e легко обходится путём перенаправления чистого клиента на собственный фейковый ConnectServer, это работает только если нету дополнительного шифрования или авторизации на подключениях к GameServer. Мы проигнорируем этот метод обхода и воспользуемся методом прокси. Основной сложностью в нашей задаче является понять алгоритм, на основе которого клиент должен выдать ответ. Для этого займёмся уже динамическим анализом кода библиотеки античита.

Опустим подробности реверсинга, как оказалось пакеты авторизации выглядят следующим образом:
dump #1
recv :: c1:04:00:01: b2:b0:a1
send :: c1:04:f4:06: 74:52:67:67
dump #2
recv :: c1:04:00:01: b1:d1:d0
send :: c1:04:f4:06: 74:52:72:19


Глядя на стабы сразу можно уловить какую-то закономерность. Для большей ясности соберём еще несколько пар запросов-ответов:
a0:e0:d1 - 74:52:66:31
b2:b0:a1 - 74:52:67:67
b2:b0:a1 - 74:52:67:67
b0:a1:b2 - 74:52:68:75
b1:d1:d0 - 74:52:72:19


Как оказалось ответ собирается из 2х ключей, по следующему алгоритму:



Глобальный ключ(global_key) генерируется на основе каких-то данных при инициализации библиотеки, в моём случае он выглядит как число 74526311(0x04712E67). Поскольку код генерации этого ключа находится в коде чтения конфигураций, разумно предположить что ключ собирается на базе информации из конфига.

Что косается второго ключа(session_key), он создаётся используя полученную от ConnectServer информацию. Найдя алфовиты мне сразу стал понятен алгоримт генерации:



Каждый байт сессионного пакета переводится в строковое представление и разбивается на 2 части, затем декодируется согласно предопределённым алфовитам. Например пакет a0:e0:d1, первый байт A0 разбивается на 2 части A и 0, A является членом алфовита ABDE, позиция в данном алфовите определяет тип второго алфовита, вторая часть пакета 0 определяет индекс во втором алфовите 361. Таким образом нашему пакету соответствуют A0 = 3, E0 =2, D1=0, получаем число 320, это и есть session_key.

Вот и вся авторизация у нас на ладонях, осталось только дописать её поддержку в наш излюбленный Mu Bypass Proxy Module и дело в шляпе. Рабочий код ищите в конце статьи.

Этап 0×03. Заключение

Наша экспертная оценка защиты 2.3 / 5

Конечно в защите присутствует множество недочётов и ошибок: авторизация на Connect Server’e, слабая защита конфигурационных файлов, наличие незапакованных семплов, диструктивные действия в отношении подозрительного ПО(закрытие процесса) и т.д. Однако не смотря на это заметно что автор сталкивался с многими подводными камнями разработки античита и по малому понимает некоторые основные проблемы проектирования защитного ПО, так что его оценка чуть выше предыдущих.

Традиционное видео демонстрирующее результат работы нашего обхода.



Исходные коды доступны тут.

Спасибо за внимание

2 комментария:

  1. Помоги мне также сделать с маленьким фановым сервером, а то у меня чтото не получается)

    ОтветитьУдалить