Исследование новой защиты игр от Alawar
Исследование новой защиты игр от Alawar
Компания Alawar в особом представлении не нуждается, уже много лет это крупнейший дистрибьютор игр различных жанров. Но популярность имеет и обратную сторону, поэтому специалистами было создано немало различных инструментов для сброса триального времени, генерации серийных номеров, или вообще для удаления навесной защиты. Недавно "противостояние брони и снаряда" перешло на очередной виток, был полностью переделан игровой wrapper, соответственно, все существующие инструменты для обхода защиты стали бесполезными.
Для исследования я возьму одну из новых игр - "Пиратские загадки. Угадай картинку". В процессе установки я обратил внимание, что кроме файлов игры и привычных уже ресурсов враппера ставятся библиотеки Qt. К игре они не относятся, но зато они нужны для работы нового враппера. Я посчитал объем всего ненужного хлама, который ставится вместе с игрой. Получилось, что более 70 мегабайт (!) всякого говна нужно только для того, чтобы нарисовать окно с картинкой и отправить запрос в интернет для загрузки страницы справки и регистрации. "Программисты" (в кавычках), вы там не охуели? Думать над кодом стало уже не модно, куда лучше программировать мышкой? Ламеры поганые.
Окно враппера
Враппер запускается, при этом всеми силами стараясь выбраться в интернет, но вот запустить с его помощью игру на своей машине мне так и не удалось. Для очистки совести проверил еще на нескольких играх с этим же враппером, результат одинаковый - запустить игру даже в пробном варианте невозможно. Я не удивлен, при такой квалификации "программистов", которые писали эту защиту, было бы странно ожидать чего-то еще. Запустить игру удалось только после танцев с бубнами на виртуальной машине.
Небольшое отступление. Прошлые версии врапперов Alawar работали примерно по одной схеме. В защищаемом файле портились некоторые данные, например, код на точке входа или где-нибудь еще. Оригинальные данные из испорченных участков были сохранены во враппере. При старте защищенной игры враппер восстанавливал исполняемый файл игры в памяти. Для отвязки игры от враппера было достаточно снять дамп секции кода из запущенной игры и восстановить испорченные участки в исходном защищенном файле.
После запуска игры я снял дамп процесса и сравнил секцию кода дампа с исходным кодом в защищенном файле. Никаких различий не нашлось. Значит новый враппер работает по какой-то другой схеме. Посмотрим на защищенный файл поближе.
Секции защищенного файла
Как видно на скриншоте, к файлу дописана новая секция с именем "x123y", и точка входа указывает на нее. Обозначим эту секцию, как защитную. Если посмотреть на нее в редакторе, то можно увидеть кучу всего интересного. А именно: работа с сетевыми функциями, адрес локального хоста 127.0.0.1, какой-то пароль. Сама секция дописана по "вирусному" принципу, определяет адрес библиотеки kernel32.dll из окружения процесса, получает адрес функции GetProcAddress, загружает библиотеку wsock32.dll и ее функции для работы с сетью.
Защитная секция
Как я понял, враппер при запуске поднимает локальный сервер, к которому коннектится защитная секция и получает из него какие-то данные. Лютая жесть, другого определения происходящему у меня нет. Ковыряться во всем этом говне у меня нет никакого желания. Поэтому надо поискать какой-нибудь другой вариант решения проблемы. Как мы помним, основная секция кода в защищенном файле не модифицирована, значит для отвязки от враппера нам надо сделать так, чтобы при старте управление сразу получала именно она, а не защитная секция. Короче говоря, надо изменить адрес точки входа на оригинальный, который был у файла до того, как к нему была дописана новая секция.
Как же определить оригинальную точку входа? Практически все игры от Alawar написаны на С/С++, значит они должны иметь как минимум похожие участки кода, присущие этому компилятору. Давайте посмотрим на исполняемые файлы каких-нибудь других игр, не защищенных новым враппером. Они все имеют похожую точку входа. Что-типа такого:
Code (Assembler) : Убрать нумерацию
- .text:0074394F $LN33 proc near
- .text:0074394F call sub_75A5A5
- .text:00743954 jmp sub_7437D1
- .text:00743954 $LN33 endp
Code (Assembler) : Убрать нумерацию
- .text:0075A5A5 sub_75A5A5 proc near
- .text:0075A5A5 mov edi, edi
- .text:0075A5A7 push ebp
- .text:0075A5A8 mov ebp, esp
- .text:0075A5AA sub esp, 10h
- .text:0075A5AD mov eax, dword_842FF4
- .text:0075A5B2 and dword ptr [ebp-8], 0
- .text:0075A5B6 and dword ptr [ebp-4], 0
- .text:0075A5BA push ebx
- .text:0075A5BB push edi
- .text:0075A5BC mov edi, 0BB40E64Eh
- .text:0075A5C1 mov ebx, 0FFFF0000h
- .text:0075A5C6 cmp eax, edi
- .text:0075A5C8 jz short loc_75A5D7
- .text:0075A5CA test ebx, eax
- .text:0075A5CC jz short loc_75A5D7
- .text:0075A5CE not eax
- .text:0075A5D0 mov dword_842FF8, eax
- .text:0075A5D5 jmp short loc_75A637
- .text:0075A5D7 ; ------------------------------------------------
- .text:0075A5D7 loc_75A5D7:
- .text:0075A5D7 push esi
- .text:0075A5D8 lea eax, [ebp-8]
- .text:0075A5DB push eax
- .text:0075A5DC call ds:GetSystemTimeAsFileTime
- .text:0075A5E2 mov esi, [ebp-4]
- .text:0075A5E5 xor esi, [ebp-8]
- .text:0075A5E8 call ds:__imp_GetCurrentProcessId
- .text:0075A5EE xor esi, eax
- .text:0075A5F0 call ds:GetCurrentThreadId
- .text:0075A5F6 xor esi, eax
- .text:0075A5F8 call ds:GetTickCount
- .text:0075A5FE xor esi, eax
- .text:0075A600 lea eax, [ebp-10h]
- .text:0075A603 push eax
- .text:0075A604 call ds:QueryPerformanceCounter
Code (Assembler) : Убрать нумерацию
- .text:00472661 push ebp
- .text:00472662 mov ebp, esp
- .text:00472664 sub esp, 14h
- .text:00472667 mov eax, dword_492800
- .text:0047266C and [ebp+SystemTimeAsFileTime.dwLowDateTime], 0
- .text:00472670 and [ebp+SystemTimeAsFileTime.dwHighDateTime], 0
- .text:00472674 push esi
- .text:00472675 push edi
- .text:00472676 mov edi, 0BB40E64Eh
- .text:0047267B mov esi, 0FFFF0000h
- .text:00472680 cmp eax, edi
- .text:00472682 jz short loc_472691
- .text:00472684 test esi, eax
- .text:00472686 jz short loc_472691
- .text:00472688 not eax
- .text:0047268A mov dword_492804, eax
- .text:0047268F jmp short loc_4726F7
- .text:00472691 ; ------------------------------------------
- .text:00472691 loc_472691:
- .text:00472691 lea eax, [ebp+SystemTimeAsFileTime]
- .text:00472694 push eax ; lpSystemTimeAsFileTime
- .text:00472695 call ds:GetSystemTimeAsFileTime
- .text:0047269B mov eax, [ebp+SystemTimeAsFileTime.dwHighDateTime]
- .text:0047269E xor eax, [ebp+SystemTimeAsFileTime.dwLowDateTime]
- .text:004726A1 mov [ebp+var_4], eax
- .text:004726A4 call ds:GetCurrentThreadId
- .text:004726AA xor [ebp+var_4], eax
- .text:004726AD call ds:GetCurrentProcessId
- .text:004726B3 xor [ebp+var_4], eax
- .text:004726B6 lea eax, [ebp+PerformanceCount]
- .text:004726B9 push eax ; lpPerformanceCount
- .text:004726BA call ds:QueryPerformanceCounter
Code (Assembler) : Убрать нумерацию
- ; Оригинальная точка входа
- .text:00471F6D call sub_472661
- .text:00471F72 jmp loc_471E08
Определение Image Base
Дальше немного математики. Точка входа = VA OEP - Image Base. То есть 00471F6D - 00400000 = 00071F6D. Осталось вписать это значение в заголовок файла:
Исправляем Entry Point
Сохраняем изменения, запускаем исправленный файл Fill and Cross. Pirate Riddles.wrp.exe. Все отлично, игра без проблем запускается и работает.
Игра успешно отвязана от враппера
Вот так игры Alawar отвязываются от нового враппера. Все происходит в статике, для этого даже не надо запускать игру. Не исключено, что в дальнейшем враппер будет вновь доработан на предмет порчи и восстановления файла, как было в ранних версиях. В этом случае при отвязке добавится еще один шаг с восстановлением секции кода из дампа.
Срамота!
Напоследок процитирую Лермонтова: "Забил заряд я в пушку туго. И думал: угощу я друга! Постой-ка, брат мусью!" и посоветую Alawar как можно скорее уволить своих криворуких "программистов".
Просмотров: 12386 | Комментариев: 31
Метки: исследование защиты, игры
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(06.03.2015 в 22:01):
Можно поискать по GetModuleHandleA, процедура с этой функцией вызывается самой первой рядом с OEP. Статистику не собирал, насколько это будет универсальным решением.
R U B O A R D M A N
(06.03.2015 в 21:45):
ManHunter, подскажите есть ли способ аналогичный описанному в статье поиска точки входа, но только для Дельфей? Иногда после снятия протекторов вроде Армадилы бывает полезно.
вася
(22.09.2014 в 11:07):
согласен гандоны.бесплатные игры всегда платные.Развод.Да еще и установи яндекс,бар и .т.д.Вообще охели
Isaev
(02.09.2014 в 19:12):
"ставятся библиотеки Qt. К игре они не относятся, но зато они нужны для работы нового враппера."
ужс :D
Откуда ж они берутся, эти горе-программисты!
ужс :D
Откуда ж они берутся, эти горе-программисты!
ManHunter
(18.06.2014 в 11:59):
В данном конкретном случае описан не универсальный метод поиска OEP для всего на свете, а исключительно для игр от Alawar, которые идут под новым враппером. И этот метод в данном конкретном случае прекрасно работает.
Shlak
(18.06.2014 в 11:47):
С большим удовольствием читал ваши статьи. Только после этого я осознал, что для хорошего взлома нужно знать ассемблер. Так что благодарю за то, что смогли вбить в меня эту истину.
Но в данном конкретном случае я не согласен с вами в методе поиска Entry Point. Такой метод подходит в большинстве случаев, но далеко не всегда. Пример функции которая является Entry Point, в игре которою недавно я разбирал: rghost.ru/56443140/image.png
(Защита навесная - шифрование секции text и смещение Entry Point в секцию расшифровки. На скриншоте разумеется уже расшифрованный вариант. Написан на Microsoft Visual C++ 8)
Я предпочитаю идти поиском по маске "C3 E8 ?? ?? ?? ?? E9 ?? ?? ?? ??" от окончания секции в сторону начала файла. Первая или вторая точка почти наверняка и есть искомая Entry Point.
Но в данном конкретном случае я не согласен с вами в методе поиска Entry Point. Такой метод подходит в большинстве случаев, но далеко не всегда. Пример функции которая является Entry Point, в игре которою недавно я разбирал: rghost.ru/56443140/image.png
(Защита навесная - шифрование секции text и смещение Entry Point в секцию расшифровки. На скриншоте разумеется уже расшифрованный вариант. Написан на Microsoft Visual C++ 8)
Я предпочитаю идти поиском по маске "C3 E8 ?? ?? ?? ?? E9 ?? ?? ?? ??" от окончания секции в сторону начала файла. Первая или вторая точка почти наверняка и есть искомая Entry Point.
Voffka
(16.06.2014 в 15:41):
Кажись сделал "декриптор" который из "KEY"(что во wrapper.log)расшифровывает оеп. Но походу в DRM и вправду косяк, в одной игре этот "KEY" у меня кривой и игра не запускается никак.
"декриптор" не выкладываю, это вроде как запрещено...
"декриптор" не выкладываю, это вроде как запрещено...
ManHunter
(16.06.2014 в 11:01):
У меня игры с новым враппером вообще не стартуют, сразу валятся с ошибкой. Поэтому все эти запуски в отладчике, точки останова на секции, патчи врапперов ничем не помогут.
Voffka
(16.06.2014 в 10:45):
Кстати там осталась(и даже упростилась) фича с патчем DllGetRegInfo в wrapper.dll, только на всякий случай лучше удалить F2PUpdater.exe, а то в первый раз после патча почему-то обновилась wrapper.dll
ufo
(15.06.2014 в 20:52):
Я так к другим играм ОЕП так и не нашел.
>>По единственной перекрестной ссылке переходим на код, который вызывает эту функцию. Он абсолютно идентичен коду на точке входа других файлов.<<
Можно поподробней?
P/S
Voffka, замути видео что ли...
>>По единственной перекрестной ссылке переходим на код, который вызывает эту функцию. Он абсолютно идентичен коду на точке входа других файлов.<<
Можно поподробней?
P/S
Voffka, замути видео что ли...
Voffka
(15.06.2014 в 19:00):
Мои кавычки, куда хочу туда и ставлю :)
А вообще кавычки там не нужны, нужно еще пару тройку игр на других языках, тогда кавычки сами расставятся.
А вообще кавычки там не нужны, нужно еще пару тройку игр на других языках, тогда кавычки сами расставятся.
ManHunter
(15.06.2014 в 18:51):
Voffka, ты кавычки не там расставил. Надо
Voffka
(15.06.2014 в 18:42):
"Универсальный" и более простой способ поиска ОЕП:
1. Запускаем игру, выходим из игры, последний наг не закрываем
2. Открываем в отладчике .wrp
3. тут 2 варианта выйти на оеп:
а. ставим бряк на секцию кода(Set memory breakpoint on access) и запускаем, первый бряк = ОЕР
б. Ищем PUSH 1F4 Ниже будет такой код:
PUSH 01F4h
CALL DWORD PTR SS:[EBP-0Ch]
MOV ECX,DWORD PTR SS:[EBP-094h]
MOV EDX,DWORD PTR SS:[EBP-4]
MOV EAX,DWORD PTR DS:[ECX]
SUB EAX,DWORD PTR DS:[EDX]
MOV DWORD PTR SS:[EBP-0ACh],EAX
CALL DWORD PTR SS:[EBP-0ACh] ; CALL TO OEP
Собственно и все...
1. Запускаем игру, выходим из игры, последний наг не закрываем
2. Открываем в отладчике .wrp
3. тут 2 варианта выйти на оеп:
а. ставим бряк на секцию кода(Set memory breakpoint on access) и запускаем, первый бряк = ОЕР
б. Ищем PUSH 1F4 Ниже будет такой код:
PUSH 01F4h
CALL DWORD PTR SS:[EBP-0Ch]
MOV ECX,DWORD PTR SS:[EBP-094h]
MOV EDX,DWORD PTR SS:[EBP-4]
MOV EAX,DWORD PTR DS:[ECX]
SUB EAX,DWORD PTR DS:[EDX]
MOV DWORD PTR SS:[EBP-0ACh],EAX
CALL DWORD PTR SS:[EBP-0ACh] ; CALL TO OEP
Собственно и все...
ManHunter
(15.06.2014 в 16:42):
Угу. Это С/С++ и есть, вредно совмещать шашлыки и реверс :) Поправил в статье, спасибо.
А для цитат есть цитаты.
А для цитат есть цитаты.
SReg
(15.06.2014 в 16:03):
>> Практически все игры от Alawar написаны на Дельфи
Да ну? :) может всетаки С/С++?
Никогда алавар не пилили на дельфи игры. И наврятли будут.
Да ну? :) может всетаки С/С++?
Никогда алавар не пилили на дельфи игры. И наврятли будут.
DimitarSerg
(15.06.2014 в 15:50):
Отличная статья!
p.s. За N лет я так и не понял, зачем они аспр вешают :D
>Практически все игры от Alawar написаны на Дельфи
Хм, разве ? Вроде ж MSовская студия такое компилит (сужу по ОЕП) :)
p.s. За N лет я так и не понял, зачем они аспр вешают :D
>Практически все игры от Alawar написаны на Дельфи
Хм, разве ? Вроде ж MSовская студия такое компилит (сужу по ОЕП) :)
ManHunter
(15.06.2014 в 11:03):
Если страна, то тогда как объяснить
am13.mirror.alawar.com/testsec/RoyalDefenseAncientMenaceRus_8.exe ? :))
Главное, что на оба варианта защиты есть решения. Остальное все фигня.
am13.mirror.alawar.com/testsec/RoyalDefenseAncientMenaceRus_8.exe ? :))
Главное, что на оба варианта защиты есть решения. Остальное все фигня.
Vnv
(15.06.2014 в 10:53):
Видимо, от страны проживания.
ua - понятно, а вот lat - при чем тут Москва?
ManHunter
(15.06.2014 в 10:41):
Гм.. Чудеса ч.2. Скачал lat.mirror.alawar.com/testsec/FillAndCrossPirateRiddlesRus_9.exe
MD5 1755EBD24A6BB05E53F4DAAB19E0B1B4 *FillAndCrossPirateRiddlesRus_9.exe
То есть файл идентичен _8.exe
Ну дык, там и размер в половину меньше. И враппер старый. Видимо это специальная спрятанная ссылка для пользователей, у которых это чудо программерской мысли тоже не запускается :) Типа, юзер->саппорт: "аааа, ничо не работает!!!", саппорт->юзер: "тогда скачайте отсюда".
MD5 1755EBD24A6BB05E53F4DAAB19E0B1B4 *FillAndCrossPirateRiddlesRus_9.exe
То есть файл идентичен _8.exe
Ну дык, там и размер в половину меньше. И враппер старый. Видимо это специальная спрятанная ссылка для пользователей, у которых это чудо программерской мысли тоже не запускается :) Типа, юзер->саппорт: "аааа, ничо не работает!!!", саппорт->юзер: "тогда скачайте отсюда".
Vnv
(15.06.2014 в 10:33):
ManHunter
(15.06.2014 в 10:23):
Кстати, сейчас проверил дистрибутив на предмет обновления, никаких изменений нет. Сервер возвращает Last-Modified: Mon, 09 Jun 2014 14:34:07 GMT. Ссылка на дистрибутив lat.mirror.alawar.com/testsec/FillAndCrossPirateRiddlesRus_8.exe
MD5: 1755EBD24A6BB05E53F4DAAB19E0B1B4 *FillAndCrossPirateRiddlesRus_8.exe
Получается, что у них на разных зеркалах лежат разные дистрибутивы?
MD5: 1755EBD24A6BB05E53F4DAAB19E0B1B4 *FillAndCrossPirateRiddlesRus_8.exe
Получается, что у них на разных зеркалах лежат разные дистрибутивы?
Vnv
(15.06.2014 в 10:19):
Видать после твоей статьи вернули старый враппер.
Vnv
(15.06.2014 в 10:01):
ManHunter, на сайте уже выложен вариант со спертым OEP (MD5 инсталлятора = D5C729F70794AC689435ADC66B2D08AF) и работает со старым добрым UnWrapper Helper.
ManHunter
(15.06.2014 в 08:58):
Vladimir, файл игры - .wrp.exe, а на враппере у них всегда аспр висел.
Vladimir
(15.06.2014 в 04:16):
Судя по всему защиту уже сменили. Защитная секция убрана, а на файле игры висит ASprotect 1.4 build 02.26 Beta, если верить ASPrINFO.
Maksovich
(14.06.2014 в 01:09):
Да, скорее всего Невософт. Подзабыл уже.
Я когда игрался в Невософтовские игрушки помню еще реестр было ковырял, ключи на время переделывал.
А за статью спасибо. Полезно.
ManHunter
(13.06.2014 в 22:07):
Сделай, я не возражаю.
Жека
(13.06.2014 в 22:03):
ченить типа унипатча возможно?
ManHunter
(13.06.2014 в 21:24):
Maksovich, речь, скорее всего, идет про Невософт, у них была такая защита. У Алавара уже лет 10 как полноценный враппер.
Maksovich
(13.06.2014 в 21:12):
Я вспоминаю как одно время у них была такая "крутая" защита что до слез можно было смеяться. Значит игра запускалась с EXE-шника и рядом с ним в папке появлялся оригинальный не тронутый EXE. Только он был скрытым и если не ошибаясь системным. Потом после закрытия игры он удалялся. Ну охренеть какая защита! :) Запустил игру, свернул, скопировал не тронутый EXE-шник куда нибудь, закрыл игру, вставил скопированный EXE-шник в папку и игрой и играй спокойно с него. Я когда первый раз это увидел, правда, смешно стало. Защита от дурака называется.
Кодер
(13.06.2014 в 18:39):
Шикарно! Респект.
Добавить комментарий
Заполните форму для добавления комментария