eXeLab
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Русский / Russian English / Английский

Сейчас на форуме: (+2 невидимых)
 · Начало · Статистика · Регистрация · Поиск · ПРАВИЛА ФОРУМА · Язык · RSS · SVN ·

 eXeL@B —› Основной форум —› как бы это пропатчить? (флэш)
Посл.ответ Сообщение


Ранг: 140.5 (ветеран)
Статус: Участник

Создано: 20 декабря 2015 11:41 New!
Цитата · Личное сообщение · #1

Доброго времени суток!
Ковыряю игрушку Exmortis 3
Используется свой плеер и дополнительные флэшевые "обёртки", причём всё это намертво интегрировано с самой игрой - разделить вряд ли получится.
Реверснул алгоритм шифрования флэшки (чтобы можно было реплейсить флэшку в плеере), вытащил, разбираю активацию.

Код кнопки активации выглядит так
Code:
  1. // com.fizzy.controllers.MainController::clickHandler
  2. this.applicationData.addEventListener(Event.CHANGE,this.activateResultHandler); // будет ожидаться Event.CHANGE, запомним это
  3. this.applicationData.activate(_loc4_.email,_loc4_.password,_loc4_.activation); // вызывается процедура активации
  4. this.contentController.openDialogue("MsgVerificationWait"); // и вешается окно "Verifying Activation Details"


За запросы на активацию отвечают вызовы следующего вида:
Code:
  1. // com.fizzy.data.ApplicationData::activate
  2. this.remoteService = new FizzyServices();
  3. this.remoteService.addEventListener(Event.COMPLETE,this.checkActivationResult); // обработчик один, проверяется код события
  4. this.remoteService.addEventListener(ErrorEvent.ERROR,this.checkActivationResult);
  5. this.remoteService.checkActivation(_loc4_);

и
Code:
  1. // com.fizzy.data.ApplicationData::verifyCurrentActivation
  2. this.remoteService = new FizzyServices();
  3. this.remoteService.addEventListener(Event.COMPLETE,this.checkRefundResult);
  4. this.remoteService.addEventListener(ErrorEvent.ERROR,this.checkRefundResult);
  5. this.remoteService.checkRefund(_loc2_);



Code:
  1. // обработчик событий от запроса на активацию
  2. private function checkActivationResult(param1:Event) : void {
  3.   var _loc2_:* = this.remoteService.result;
  4.   this.remoteService.removeEventListener(Event.COMPLETE,this.checkActivationResult);
  5.   this.remoteService.removeEventListener(ErrorEvent.ERROR,this.checkActivationResult);
  6.   this.remoteService.close();
  7.   this.remoteService = null;
  8.   if(param1.type == ErrorEvent.ERROR) {
  9.     this._activated = false;
  10.   } else {
  11.     this._activated = Boolean(_loc2_);
  12.   }
  13.   this.generateDemoCodes();
  14.   log("Activated: " + this._activated);
  15.  
  16.   if(this._activated) {
  17.     this.saveActivation();
  18.   }
  19.   this.dispatchEvent(new Event(Event.CHANGE)); // вот пока этот вызов не сработает, "MsgVerificationWait" продолжит висеть
  20. }



Чтобы много не парить мозги, я пошёл в com.fizzy.net.remoting.FizzyServices
и в функциях checkActivation и checkRefund вместо запросов вставил код
this.dispatcher.dispatchEvent(new Event(Event.COMPLETE));
По идее, это должно вызвать обработчик с нужным кодом сообщения, и все будут счастливы.

Но это почему-то не работает... При попытке активировать любым кодом игра просто висит с сообщением "MsgVerificationWait".
Где я ошибся?


исследуемый файл (сам по себе не запускается)


Ранг: 747.9 (! !)
Статус: Участник
bytecode!

Создано: 20 декабря 2015 16:33 · Поправил: 20 декабря 2015 16:34 4kusNick New!
Цитата · Личное сообщение · #2

Если оно в итоге через Flash Player проигрывается, я бы поставил \ подсунул отладочную версию и смотрел в логи трейсов - не падает ли оно где-то из-за патча.

Затем я бы в методе checkActivationResult оставил бы код

Code:
  1. this._activated = true;
  2. this.generateDemoCodes(); // это надо бы ещё проверить что там внутри, надо ли оно вообще или нет
  3. log("Activated: " + this._activated);
  4. this.saveActivation();
  5. this.dispatchEvent(new Event(Event.CHANGE));
  6. log("Event sent"); // либо trace("Event sent")


Чтобы выполнились все действия как при обычной активации.
И в конце добавил бы log или trace чтобы удостовериться что код выполнился до конца без ошибок.
Если они используют для проигрывания не Flash Player а что-то своё и там нет трейсов - то я бы посмотрел куда сбрасывает данные их log() и при необходимости включил бы его, если он отключен, чтобы можно было оставлять для себя логи.

| Сообщение посчитали полезным: -=AkaBOSS=-


Ранг: 105.6 (ветеран)
Статус: Участник

Создано: 21 декабря 2015 00:24 · Поправил: 21 декабря 2015 00:49 JohnyDoe New!
Цитата · Личное сообщение · #3

Мне кажется не надо париться с активациями. Достаточно будет _activated проинициализировать и в соответствии с логикой потереть код, который отвечает за всяческие проверки. Там обфускации нет - все не так уж и сложно должно быть.

Вариант от 4kusNick вполне годится, если не охота тереть лишний код. Можно еще весь этот код перенести прямо в метод activate и не запускать активацию вообще.


Ранг: 140.5 (ветеран)
Статус: Участник

Создано: 21 декабря 2015 01:32 New!
Цитата · Личное сообщение · #4

Ну я понимаю, что проще поменять код везде где только можно, но хочется красивого и аккуратного решения.

Основной вопрос был не сколько о том, как именно её взломать, а больше о том, почему я не наблюдаю ожидаемого эффекта. С этой ошибкой я уже разобрался - глупо, но я абсолютно не обратил внимание на проверку this.remoteService.result в обработчиках событий. Выяснить удалось только после того как функцию log перенаправил на wrapperLog - сброс лога в отдельный файл.

Таким образом, финальный патч для com.fizzy.net.remoting.FizzyServices::checkActivation и checkRefund стал таким:
Code:
  1. this._result = true;
  2. this.dispatchEvent(new Event(Event.COMPLETE));


В результате активация проходит, но в процессе до сих пор нарушается очередь событий.
Судя по всему, обработчик Event.COMPLETE вызывается раньше, чем происходит возврат из вызова applicationData.activate (нет задержки интернет-соединения). Из-за этого, экран с сообщением об удачной регистрации оказывается перекрыт всё тем же окном
"MsgVerificationWait". Плюнул и перенёс вызов, вешающий окно, на одну строчку выше
Code:
  1.     // com.fizzy.controllers.MainController::clickHandler
  2.     this.applicationData.addEventListener(Event.CHANGE,this.activateResultHandler);
  3.     this.contentController.openDialogue("MsgVerificationWait");
  4.     this.applicationData.activate(_loc4_.email,_loc4_.password,_loc4_.activation);


Вроде бы всё получилось, тестирую...

Ранг: 105.6 (ветеран)
Статус: Участник

Создано: 21 декабря 2015 12:15 New!
Цитата · Личное сообщение · #5

С логами всегда проще. Если не идет процесс, то надо искать как бы посмотреть лог.

Окно "MsgVerificationWait" выводит в конце какой-то результат или просто закрывается? А то его можно было бы вообще не выводить. С другой стороны, будет не понятно произошло ли что-то вообще после нажатия на кнопку активации.


Ранг: 140.5 (ветеран)
Статус: Участник

Создано: 21 декабря 2015 13:25 New!
Цитата · Личное сообщение · #6

JohnyDoe пишет:
Окно "MsgVerificationWait" выводит в конце какой-то результат или просто закрывается

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

Добавил еще строки с серийником и номером активации в инициализацию ApplicationData - большше не нужно ничего вводить, игра изначально считает себя зарегистрированной.
Кажется, всё...

Ранг: 105.6 (ветеран)
Статус: Участник

Создано: 21 декабря 2015 14:07 New!
Цитата · Личное сообщение · #7

Возможно будет интересно. Самый простой путь из всех - взять флешку с сайта(та что демо), изменить basepath, положить файлы из инсталлятора рядом в директорию assets и поиграться с методом isDemo. В итоге получаем полную версию игры с возможностью запуска через стандартный flash player. Теперь можно считать, что вопрос рассмотрен всесторонне

| Сообщение посчитали полезным: -=AkaBOSS=-



Ранг: 140.5 (ветеран)
Статус: Участник

Создано: 21 декабря 2015 14:59 · Поправил: 21 декабря 2015 15:17 -=AkaBOSS=- New!
Цитата · Личное сообщение · #8

С эксмортисом вопрос можно считать решённым.. Полную флэш версию возможно рассмотрю чуть позднее, пока и так работает)


Возился недавно еще с одной игрой - simian.interface, но так до конца и не довёл.
Цель исследования - сделать полную оффлайновую версию. Игра в процессе выполнения подгружает семь музыкальных треков и одно изображение - я пытаюсь их вшить внутрь, чтобы ничего лишнего не болталось.

C изображением проще всего - подключил как ByteArray, а в конструкторе game.levels.GlitchmapBackground вместо loadImage
Code:
  1. this.glitchmap = new Glitchmap(); // com.soulwire.display.Glitchmap
  2. this.glitchmap.loadImage (this.myState.externalPath + "images/gradient_green.jpg");

сразу указал bytesSource
Code:
  1. this.glitchmap = new Glitchmap(); // com.soulwire.display.Glitchmap
  2. this.glitchmap.bytesSource = GlitchmapBackground_ImgGradientGreen as ByteArray;

Вопрос первый - это будет работать, если GlitchmapBackground_ImgGradientGreen объявлен как ByteArrayAsset?


далее - музыка.. С ней всё посложнее.
Треки грузятся в
Code:
  1. // game.PlayState::loadMusic
  2. var _loc6_:String = this.externalPath + "music/" + param1;
  3. FlxG.playMusic (null,_loc6_,param2,0);
  4.  
  5.  
  6. // org.flixel.FlxG::playMusic
  7. if(param1 != null) {
  8.   music[param4].loadEmbedded(param1,true);
  9. else {
  10.   music[param4].loadStream(param2,true);
  11. }

Правильно ли я понимаю, это означает, что в playMusic первым параметром можно передать SoundAsset as Sound и это будет работать?

Ранг: 105.6 (ветеран)
Статус: Участник

Создано: 21 декабря 2015 16:49 · Поправил: 21 декабря 2015 16:50 JohnyDoe New!
Цитата · Личное сообщение · #9

GlitchmapBackground_ImgGradientGreen это какой-то класс? Если да, то как-то так должно быть.

this.glitchmap.bytesSource = new GlitchmapBackground_ImgGradientGreen() as ByteArray;

Со звуком не приходилось иметь дело. В любом случае надо пробовать.


Ранг: 140.5 (ветеран)
Статус: Участник

Создано: 21 декабря 2015 17:28 · Поправил: 22 декабря 2015 03:13 -=AkaBOSS=- New!
Цитата · Личное сообщение · #10

Переделал функцию loadMusic - теперь в качестве первого аргумента она принимает Class, и передаёт его первым же аргументом в playMusic. Ну и соответствующим образом изменил вызовы - вместо строк с названиями передаются классы SoundAsset. Всё отлично, но поначалу не играло из-за выключенного звука в опциях.


JohnyDoe пишет:
GlitchmapBackground_ImgGradientGreen это какой-то класс?

ну я посмотрел как в других местах сделано, пошаманил с rabcdasmом и получилось такое:

Code:
  1. package game.levels {
  2.   import mx.core.ByteArrayAsset;
  3.   
  4.   public class GlitchmapBackground_ImgGradientGreen extends ByteArrayAsset {
  5.      
  6.     public function GlitchmapBackground_ImgGradientGreen() {
  7.       super();
  8.     }
  9.   }
  10. }


Плюс внёс соответствующие изменения в SymbolClass и ExportAssets, и добавил нужное изображение как binaryData.

создаю объект так:

Code:
  1. this.glitchmap.bytesSource = new GlitchmapBackground_ImgGradientGreen() as ByteArray;
  2.  
  3. // версия от RABCDAsm
  4. getlocal0
  5. getproperty         QName(PrivateNamespace(null,"30"),"glitchmap")
  6. findpropstrict      QName(PackageNamespace("game.levels"),"GlitchmapBackground_ImgGradientGreen")
  7. constructprop       QName(PackageNamespace("game.levels"),"GlitchmapBackground_ImgGradientGreen"), 0
  8. getlex              QName(PackageNamespace("flash.utils"),"ByteArray")
  9. astypelate
  10. initproperty        QName(PackageNamespace(""),"bytesSource")


в момент использования (после 6го уровня) отладочный плеер выдаёт ошибку:
ReferenceError: Error #1069: Property ::glitchmap not found on game.levels.GlitchmapBackground and there is no default value.
at game.levels::GlitchmapBackground()



Последний глюк оказался вызван тем, что rabcdasm не очень хорошо понимает неймспейсы, скопированные из ffdec.
Вместо строчки
getproperty QName(PrivateNamespace(null,"30"),"glitchmap")
вставил
getproperty QName(PrivateNamespace(null, "game.levels:GlitchmapBackground/instance"), "glitchmap")

теперь всё работает)
если кому-то интересно глянуть на результат - залил
 eXeL@B —› Основной форум —› как бы это пропатчить? (флэш)
Эта тема закрыта. Ответы больше не принимаются.

Оригинальный DVD-ROM: eXeL@B DVD !

Вы находитесь на форуме сайта EXELAB.RU
Проект ReactOS