Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save artkirienko/645c2b9bb7ffec4d735a to your computer and use it in GitHub Desktop.
Save artkirienko/645c2b9bb7ffec4d735a to your computer and use it in GitHub Desktop.
Анализ приложения «Бургер Кинг»
ПРОТОКОЛ
АНАЛИЗА ПРИЛОЖЕНИЯ "BURGER KING" ОТ РАЗРАБОТЧИКА "LOYALTY PLANT" ("ФАБРИКА ЛОЯЛЬНОСТИ")
ОСНОВНЫЕ ПОЛОЖЕНИЯ:
========================================================================================================
1. Приложение разработано для мобильных платформ: Android, Windows Phone, iOS
2. Приложение разработано на основе фреймворка Xamarin, который реализует поддержку .NET-приложений в мобильной среде
3. Приложение, кроме того, состоит в целом из двух важных частей:
* .NET-ассембли, написаный, скорее всего, на C#. (Весь код, включая структуру классов, а так же декомпилированные листинги методов, можно получить с использованием .NET Reflector)
* Ассембли содержит основной функционал программы, логику работы с аппаратным обеспечением, логику для генерирования уникального идентфикатора устройства
* Ассембли содержит основную логику для работы с REST-сервисом LoyaltyPlant на основе XML-запросов
* Ассембли содержит вызовы подпрограмм для обеспечения шифрования передаваемых данных:
* Используется следующая схема:
КЛИЕНТ->СЕРВЕР: [ XML-запрос] -> [ AES-шифрование (Java-бэкенд) ] -> [ Base64-кодирование ]
СЕРВЕР->КЛИЕНТ: [ Base64-декодирование ] -> [ Дешифровка AES (Java-бэкенд) ] -> [ XML-ответ ]
* Java-бэкенд (весь существенный код, кроме биндингов к Android-среде, прошёл процедуру обфускации путём искажения реальных имён классов и их членов, а так же локальных переменных. Получить исходные коды можно через связку утилит: dex2jar -> jd-gui):
* Состоит из биндингов из Xamarin (.NET) среды к среде Android (в данном конкретном случае рассматривается только реализация для Android)
* Содержит в себе набор обфусцированных классов библиотеки BouncyCastle для обеспечения поддержки AES-шифрования
* Содержит в себе класс (с именем a.class), цель которого обеспечить связь между .NET-частью и Java-бэкендом через вызовы JNI со стороны .NET-части. Связь выражается в виде вызовов подпрограмм для шифрования/дешифрования
* Содержит класс "a.class", который в своём статическом блоке инициализации единожды генерирует постоянный 16-байтовый ключ для AES-шифрования. Кроме того, класс имеет подпрограммы вызова шифрующих/дешифрующих подпрограмм.
* Содержит в себе класс com.google.utils.Util, который, в свою очередь, содержит подпрограмму для генерации уникального идентификатора пользователя на основе данных о его модели. Содержит строковые константы с предупреждением о возможном нарушении статьи 272 УК РФ, а так же вызовы хеш-функции CRC32
4. Некоторые сведения об используемой "защите":
* Криптографическая схема в стандартных обозначениях: AES/CBC/PCKS7Padding (алгоритм: симметричный шифр AES (aka Rijndael), режим: блочный, выравнивание блоков: PCKS7)
* Хеш-функция: CRC32
* Функция обратимого кодирования малым алфавитом: Base64
* Схема передачи данных:
КЛИЕНТ->СЕРВЕР: [ XML-запрос] -> [ AES-шифрование (Java-бэкенд) ] -> [ Base64-кодирование ]
СЕРВЕР->КЛИЕНТ: [ Base64-декодирование ] -> [ Дешифровка AES (Java-бэкенд) ] -> [ XML-ответ ]
ЦЕЛЬ:
========================================================================================================
Разработать приложение, которое будет имитировать ввод промо-кода на физическом устройстве с целью получения бонусных баллов с минимумом затрат
ОБФУСЦИРОВАННЫЕ НАЗВАНИЯ КЛАССОВ Java-БЭКЕНДА И ИХ ПРЕДНАЗНАЧЕНИЕ:
========================================================================================================
* a - Main (можно назвать главным классом в крипографической схеме. Генерирует ключ шифрования, обеспечивает связь с .NET-частью в плане вызова шифрующих/дешифрующих подпрограмм)
* d - BlockCipher (BouncyCastle)
* l - CBCBlockCipher (BouncyCastle)
* t.class, r.class - кодирование BASE64
* k.class - Реализация AES (BouncyCastle)
* n.class - PaddedBufferedBlockCipher (BouncyCastle)
ПРОТОКОЛ ЛЕГАЛЬНОЙ СЕССИИ ПЕРЕДАЧИ ДАННЫХ МЕЖДУ КЛИЕНТОМ И СЕРВЕРОМ:
========================================================================================================
Общие положения:
* Передача данных ведётся по протоколу HTTP версии 1.1
* Используется метод POST
* URL, к которому идут запросы, постоянен и имеет вид: http://54.247.166.174/IPLPhoneServer/PhoneServerSec.do
* Тело запроса и ответа на запрос зашифровано известной схемой, приведённой выше
* Тело каждого запроса, если исключить шифрование и кодирование, это обращение к REST-сервису на основе XML-формата. В каждом запросе упоминается:
* Версия протокола
* Уникальный идентификатор клиента (устройства)
* Запросы от клиента имеют следующие заголовки:
POST /IPLPhoneServer/PhoneServerSec.do HTTP/1.1
Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
User-Agent: RestSharp 104.1.0.0
Content-Type: application/octet-stream
Content-Length: длина-передаваемых-данных
Host: 54.247.166.174 (айпи сервера, постоянен)
Accept-Encoding: gzip, deflate (клиент принимает в качестве ответа от сервера сжатый ZLib/Deflate поток данных)
* Ответы сервера на запросы имеют следующие заголовки:
HTTP/1.1 200 OK
Server: nginx/1.4.7
Date: временная-метка-в-формате-GMT
Content-Length: длина-пакета-данных
Connection: keep-alive
Set-Cookie: JSESSIONID=A7F19DE146D0C1DA921CF279643A0A5A; Path=/IPLPhoneServer/; HttpOnly
Content-Encoding: gzip
========================================================================================================
Краткая схема запросов клиента:
1. Запрос на регистрацию
2. Запрос на данные интернационализации (Loyalty Plant - межнациональная компания, так-то)
3. Запрос на получение информации о партнёре (в нашем случае это Burger King)
4. Запрос на загрузку данных синхронизации
5. Подробный журнал запуска
6. Подробный журнал, в том числе содержащий информацию о модели физического устройства
7. Подробный журнал, содержащий данные метрики BlackBox (какие кнопки когда и где нажаты, какие окна открывались/закрывались и т. п.)
8. Запрос на проверку введённого промо-кода
ПОДРОБНЫЙ РАЗБОР СЕССИИ ПЕРЕДАЧИ ДАННЫХ:
========================================================================================================
* Знаком [!] помечены СУЩЕСТВЕННЫЕ для выполнения ЦЕЛИ вещи
0. [!] Запрос на регистрацию клиента (первая установка)
<?xml version="1.0" encoding="utf-8"?>
<request type="register" protocol-version="9">
<hardware>
<device-ids device-id="298527684033946" device-id-udi="b1fb2d86eccb62e7" device-id-android="309a28a181eaf3a0" ad-tracking-enabled="false" />
<platform phone-model="samsung SM-G900F 4.4.2" type="1" platform-version="4.4.2" />
<screen width="900" height="1392" depth="32" />
</hardware>
<application version="10.39 8139" build="8139" />
<partner id="1579" />
<android-identifiers android-fingerprint="samsung/kltexx/klte:4.4.2/KOT49H/G900FXXU1ANCE:user/release-keys" android-manufacturer="samsung" android-operator="T-Mobile" />
<android-accounts />
</request>
1. [!] Ответ на пакет о первой регистрации
<response protocol-version="9"
type="register"
current-server-timestamp="1409952551734"
accepted="true"
first-install="true"
public-id="1540654"
first-install-timestamp="1409952551737"
client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d"
/>
2. Запрос на получение данных интернационализации (язык, переводы и пр.)
<?xml version="1.0" encoding="utf-8"?><request type="get-i18n" protocol-version="9" client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d" />
3. Ответ на запрос данных интернационализации (готовые кнопки меню)
<response protocol-version="9" type="get-i18n"><!-- длинное содержимое пропущено --></response>
4. Запрос на получение информации о партнёре
<?xml version="1.0" encoding="utf-8"?><request type="get-partner-info" protocol-version="9" client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d" />
5. Ответ на запрос информации о партнёре, возвращает кучу данных о бургер-кинге, включая описание, какая валюта используется, телефон тех. поддержки и т. п.
<response protocol-version="9" type="get-partner-info">
6. [!] Запрос на синхронизацию
<?xml version="1.0" encoding="utf-8"?>
<request type="sync" protocol-version="9" client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d" public-id="1540654">
<application version="10.39 8139" build="8139" />
[!] <device-ids device-id="298527684033946" device-id-udi="b1fb2d86eccb62e7" device-id-android="309a28a181eaf3a0" ad-tracking-enabled="false" last-client-id-ok-da="a122a4f6ec92dc1e1ecc13eb3ec7b95d" />
<texts version="1409749682000" />
<partner-info version="1409574473000" />
<device-token />
<social-networks>
<social-network-info type="vk" />
<social-network-info type="fb" />
<social-network-info type="twi" />
</social-networks>
<date timestamp="1409952610610" />
<points amount="0" />
<coupons>
<hidden />
<shown />
</coupons>
<uses />
<sections wp-fixed-section-id="0" />
<feedback-records />
<features />
</request>
7. Ответ на запрос о синхронизации.
Беглый анализ показывает, что в ответе содержатся следующие данные:
* Текущее время на сервере в формате временной метки POSIX-TIME
* Количество бонусных очков
* Список филиалов Burger King в городе, включая их точные GPS-координаты
* Список купонов
* Шаблон пригласительного смс-сообщения
Заголовок: <response protocol-version="9" type="sync" current-server-timestamp="1409952553144">
8. [!] Запрос на синхронизацию меню
<?xml version="1.0" encoding="utf-8"?><request type="sync-menu" protocol-version="9" client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d"><version value="1" /><menu-items /><categories /></request>
9. Ответ на запрос синхронизации меню
<response protocol-version="9" type="sync-menu" current-server-timestamp="1409952554845">
Содержит:
* Текущее время сервера
* Список элементов меню, включая купоны
* Список категорий
10. [!] Клиент отправляет подробный журнал запуска
<?xml version="1.0" encoding="utf-8"?><request type="log" client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d" build="8139" platform-id="1" protocol-version="9" timestamp="1409952614890"><log timestamp="1409952608470" level="info">
Требуется полностью имитировать его формирование и отправку в целях поддержания максимального сходства с легальным приложением
11. Ответ на высланный лог, подтверждение со стороны сервера
<response protocol-version="9" type="log" accepted="true"/>
12. [!] Очередной посыл лога, содержит важную информацию о модели устройства:
<![CDATA[Log: ======================= CURRENT MODEL =======================
CorrectedCurrentTimestamp: 1409952553254
==================== PERSISTENCE FIELDS ====================
- PartnerId: 1579
- Server: http://54.247.166.174/IPLPhoneServer/PhoneServer.do
==================== MODEL FIELDS ====================
- PublicId: 1540654
- IsLoggedIn (Facebook): False
- IsLoggedIn (Vkontakte): False
- IsLoggedIn (Twitter): False
- IsLoggedIn (Odnoklassniki): False
- DeviceToken:
- ClientId: a122a4f6ec92dc1e1ecc13eb3ec7b95d
- WindowsPhoneFixedSectionId: 0
- PointsAmount: 0
- StartPresentId: 0
- CanUseStartPresentNow: True
- AskToLeaveMarketFeedback: True
- SubscriptionToPush: True
- UserValidatedPresent: False
- UserValidatedBonusCard: False
===================== SHOWN CARDS ====================
]]!>
13. Ответ сервера на высланный лог
14. Клиент посылает запрос типа "log" (журнал) с данными от системы метрики BlackBox:
<?xml version="1.0" encoding="utf-8"?><request type="log" client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d" build="8139" platform-id="1" protocol-version="9" timestamp="1409952631590">
<blackbox version="8">
<![CDATA[{{
ДАННЫЕ МЕТРИКИ
]]></blackbox></request>
15. Ответ сервера на присланный лог
16. Очередные данные о метрике. [!] СУЩЕСТВЕННО: в метрике содержатся данные о том, что открыто окно ввода промо-кода (требуется имитировать и это в целях 100% схожести)
Код запроса:
<?xml version="1.0" encoding="utf-8"?><request type="log" client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d" build="8139" platform-id="1" protocol-version="9" timestamp="1409952650730"><blackbox version="8"><![CDATA[{{
TIME :: 1409952650720
ACTION :: MESSAGE_OPENED
MESSAGE_TYPE :: PleaseEnterPromoCode
TEXT :: Введите промо-код
VISUAL_TYPE :: MessageWithTextField
}}
{{
TIME :: 1409952650720
ACTION :: MESSAGE_BUTTON_CLICKED
MESSAGE_TYPE :: AskAboutPromoCode
I18N_IDENTIFIER :: ENTER_PROMO_CODE
BUTTON_TYPE :: positive
BUTTON_TEXT :: Ввести промо-код
TEXT :: Если у вас есть промо-код, введите его
VISUAL_TYPE :: PlainTextMessage
}}
{{
TIME :: 1409952650720
ACTION :: MESSAGE_CLOSED
MESSAGE_TYPE :: AskAboutPromoCode
TEXT :: Если у вас есть промо-код, введите его
VISUAL_TYPE :: PlainTextMessage
}}
]]></blackbox></request>
17. Ответ сервера на принятый лог (такой же, как и в пунктах №15, №13, №11)
18. [!] Запрос к серверу: пользователь ввёл промо-код
<?xml version="1.0" encoding="utf-8"?>
<request type="check-promo-code" protocol-version="9" client-id="a122a4f6ec92dc1e1ecc13eb3ec7b95d" user-entered-promo-code="[!]ПРОМО-КОД" />
19. [!] Ответ от сервера о статусе принятия промо-кода (это, собственно, цель имитации, дальнейшие действия, скорее всего, будут несущественны)
<response protocol-version="9" type="check-promo-code">
<result value="accepted"/>
</response>
========================================================================================================
Дата последнего изменения: 07.09.14 0:30 МСК
@zhovner
Copy link

zhovner commented Jan 5, 2015

Отлично, спасибо.

@ValdikSS
Copy link

ValdikSS commented Jan 7, 2015

Анализировал приложение "Чайная Ложка" от них же. Есть ранняя версия, которая не использует AES, а только zlib + base64. По какой-то причине, мне так и не удалось обмануть blackbox. Как я предполагаю, это потому, что я исследовал эту версию тогда, когда она была уже отключена. Только вчера удалил все свои наработки, т.к. ничего толком сделано не было.

@IvanMMM
Copy link

IvanMMM commented Oct 17, 2015

Есть какие-нибудь наброски? AES ключ? У меня iOS приложение, его немного сложнее расковырять чем Android. Будет RSA ключ - помогу со всем остальным если ещё есть необходимость

@derlaft
Copy link

derlaft commented Oct 17, 2015

Тыкаю приложение сейчас. Вот мои наработки на текущий момент, включая ключ: http://dpaste.com/2GW8XC6

Какое RSA?

@derlaft
Copy link

derlaft commented Oct 17, 2015

  • похоже, обмен идет по http, т.е. возможен MitM. Сейчас планирую попробовать это на практике осуществить для подмены отпечатков на лету

@IvanMMM
Copy link

IvanMMM commented Oct 17, 2015

Извиняюсь, AES. Не суть важно.
Mitm проходит, могу скинуть архив фиддлера

@derlaft
Copy link

derlaft commented Oct 17, 2015

Давай. Данные никогда не повредят.

@noname9999
Copy link

Пытаюсь расшифровать данные имеющимся ключем, но ничего не выходит. Уже кучу реализаций aes перепробовал, не получается расшифровать. Делаю на PHP. Можете что подсказать?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment