Pull to refresh

В поиске бесплатных билетов, исследование игры Аэрофлота

Information Security *Reverse engineering *
Началось все с того, что я получил ссылку на промо-сайт компании Аэрофлот. Акция заключается в прохождении небольшой flash игры и получении бонусных миль. Главный приз в 150 000 миль получает игрок, занявший первую строчку в рейтинге. Собственно, принцип формирования рейтинга и вызвал мой интерес к этой акции.



Как всем хорошо известно, код flash приложений выполняется на стороне клиента, поэтому защита от нечестной игры представляет весьма сложную задачу. По сути, единственным верным решением является перенос всей игровой механики на сторону сервера, а flash приложение выполняет роль клиента к API.

Посмотрим, как с этой задачей справляются в Аэрофлот.

Для начала запускаем игру с открытой консолью разработчика в Google Chrome. И… видимо, все будет скучно. Как оказалось, запрос на сервер отправляется всего один раз в конце игры.



Данные в запросе подозрительно похожи на base64, но преобразование из этой кодировки приводит лишь к набору бинарных данных. Значит, запрос шифруется где-то в глубине клиента. К сожалению, или к счастью, swf файлы никогда не являлись стойкими к декомпиляции.

Буквально через 10 секунд после просмотра ActionScript кода обнаруживается вот такой фрагмент:

public static function prepareForSend(param1:Object, param2:String) : String {
    return Xor64.encode(JSON.stringify(param1), "aef-game" + param2);
}


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

// main.as
this._token = stage.loaderInfo.parameters["token"];

// http://aeroflotbonus15.ru/media/js/aef.js
start : function( token, authState, connector, autoStart ){
    . . .
    this._token = token;
    . . .
},
. . . 
AEF.flashController.buildFlash({ token: this._token, connector: this._connector }, this._lang );
. . . 

// http://aeroflotbonus15.ru/
AEF.start('c958c089505d321994578a12fabbe73d', true, "http://aeroflotbonus15.ru/api/", false, 'ru');


То есть полный ключ – aef-gamec958c089505d321994578a12fabbe73d почти весь лежит у всех на виду, прямо в коде страницы.
Кстати, судя по всему, разработчики даже поленились самостоятельно реализовывать алгоритм шифрования и воспользовались готовым решением.

Результат дешифровки с озвученным ключом:

{  
   "result":{  
      "cities":11,
      "miles":749.9018522566122,
      "time":58356,
      "bonuses":2,
      "wins":6
   },
   "version":0.98,
   "bytes":7205605,
   "system":{  
      "cpuArchitecture":"x86",
      "screenDPI":72,
      "playerType":"PlugIn",
      "isDebugger":false,
      "version":"MAC 15,0,0,152",
      "manufacturer":"Google Pepper"
   },
   "url":"http://aeroflotbonus15.ru/media/swf/game.swf?68"
}


Форматирование добавлено для удобства чтения.

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

P.S.



У меня нет карточки «Аэрофлот Бонус», поэтому результаты никак не повлияют на общий рейтинг.
Tags:
Hubs:
Total votes 179: ↑173 and ↓6 +167
Views 90K
Comments 71
Comments Comments 71