1 место Использование Frida для хука функций в android приложении и реализации хэш-функции pikabu

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63
Дисклеймер: Статья создана в развлекательных, ознакомительных и образовательных целях.

Вступление
Примерно 7 месяцев назад один знакомый попросил меня посмотреть мобильное приложение Pikabu, к чему я и приступил.

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


Если скопировать запрос полностью (то есть, ту же почту, логин и т.д.) в зеннопостер, то, вроде бы, всё хорошо, нам пришёл в ответ айди регистрации:
1671608809687.png

Но если мы поменяем в запросе какие-либо данные, к примеру почту, на которую мы будем регистрировать аккаунт, в ответ на запрос уже придёт ошибка:
1671608902178.png

Что такое хэш? По гуглу, это - функция, осуществляющая преобразование массива входных данных произвольной длины в выходную битовую строку установленной длины, выполняемое определённым алгоритмом.
К примеру, если взять алгоритм хэширования MD5, то строка "password" превращается в "5f4dcc3b5aa765d61d8327deb882cf99".

То есть, с регистрацией аккаунтов через мобильное api у нас уже появились проблемы, которые надо как-то решать.
В данной статье я постараюсь максимально (насколько это у меня получится) простым языком объяснить решение данной проблемы. Также возможны недочёты в тексте, буду править, что найду.
Хэш пикабу один из самый простых что я видел.

Установку Frida и сниффера я постараюсь разложить кратко, но без пропуска важных моментов, так как данные этапы уже был описаны на форуме (а именно в https://zennolab.com/discussion/threads/android-na-post-get-s-pomoschju-frida-server-burpsuite-i-bonus.79264/, и ещё где-то).

Инструментарий данной статьи:

  1. Сниффер - Charles proxy. Можно использовать и BurpSuite, и Fiddler, без разницы.
  2. Устройство на android с root – в моём случае это реальный телефон, Redmi 6a, прошитый. Можно использовать и эмулятор. Почему именно реальное устройство? Выбор давно пал в сторону него, ибо с эмуляторами уже не раз было много проблем (в частности, вылеты приложений и т.п.), как раз в арсенале был старенький, но вполне работающий Redmi 6a. Гайды о прошивках можно найти на 4pda, в большинстве случаев всё расписано по шагам. Да и в отдельных, но редко встречающихся случаях приложение имеет детект эмулятора.
  3. Декомпилятор apk файлов - JADX (https://github.com/skylot/jadx)
  4. Frida - https://frida.re/ - это набор инструментов для разработчиков, реверс-инженеров и исследователей безопасности.
  5. Скачиватель apk файлов (входить через впн, если вы из ру) - https://apk.support/apk-downloader

1. Устанавливаем последнюю версию python - https://www.python.org/downloads/
101298


Обязательно ставим галочку на “add to path” в установщике:
1671609222973.png

2. Открываем консоль windows и пишем в ней «pip install frida-tools»
1671609341589.png
По последней строчке видим, что всё успешно установилось.

3. По такому же принципу устанавливаем objection, пишем в консоли команду «pip install objection»

4. Далее скачиваем Android SDK Platform Tools - https://dl.google.com/android/repository/platform-tools-latest-windows.zip и распаковываем в удобной для нас папке.

В окне папки, где мы распаковали наш архим, пишем «cmd» и нажимаем enter, должна открыться консоль с путём нашей папки:
101301
1671609403842.png

Устройство на android должно быть с рутом (root). В настройках разработчика должен быть включен «USB Debugging». Название может отличаться на разных телефонах, о вашем устройстве лучше почитать на 4pda.

Подключаем телефон по usb к пк. В консоли пишем «adb devices», на телефоне может появится уведомление о разрешении доступа, принимаем его. Наш девайс должен появится в консоли:
101303


Далее переходим на https://github.com/frida/frida/releases и скачиваем frida-server для android:
101304

Информацию о том, какой именно файл нужно скачать, можно понять, погуглив конфигурацию вашего устройства.

Распаковываем архив (формата .xz) в нашу папку, куда мы положили Android SDK Platform Tools, и переименовываем распакованный файл в “frida-server” (для удобства, ибо изначально там файл с номером версии).
101305


Далее в уже открытой консоли пишем три команды по очереди:
  • adb root (бывает нужна, в моём случае – нет)
  • adb push frida-server /data/local/tmp/
  • adb shell "chmod 755 /data/local/tmp/frida-server"
101306

Видим, что файл успешно передался на телефон.

И далее запускаем сервер фриды:
101453

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

Всё, данное окно не трогаем.

Примечание. На моём устройстве, для запуска сервера фриды, в начале нужно прописать «adb shell "su -c setenforce 0"». Бывают ещё редкие ошибки, но 99% их решений гуглится.

Если никаких ошибок в консоли нет, то, скорей всего, всё нормально работает.

Откроем новое окно консоли (Именно новое!) и проверим, написав команду frida-ps -Uai:
101454

Как мы видим, нам в ответе показаны все установленные приложения на устройстве, то есть всё работает.

Примечание. Если вы закроете окно консоли, в котором вы запустили сервер фриды, можно убить процесс через данные команды:
  • adb shell su
  • netstat -tunlp
  • Далее ищите процесс «frida-server» в списке, запоминаете его PID, и убиваете командой «kill -9 pid», заменив pid на нужный номер.
Я использую Charles proxy. Мне он нравится из-за простоты и наличия всех нужных мне инструментов.

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

1. В случае с Charles proxy качаем триал версию с их сайта https://www.charlesproxy.com/download/ и генерируем ключ на сайте zzzmode com/mytools/charles/.

2. После запуска сниффера на пк, ставим в настройках wi-fi на устройстве проксю, которая показана вот в этом пункте меню:
101310


101311


3. Проходим по ссылке в браузере устройства на chls.pro/ssl и ставим сертификат.

4. Также сразу отключаем windows прокси (находится в разделе proxy – windows proxy) и включаем обе кнопки в главном меню:
101312

101313

Первая отвечает за запись трафика, вторая – за ssl проксю.

Что касается установки и снятия прокси сниффера на устройстве, когда мне нужно снять трафик с приложения, я использую команды
  • adb shell settings put global http_proxy proxy:port– поставить прокси
  • adb shell settings put global http_proxy :0 – снять прокси
Ибо часто нужно зайти в Google Play, а через прокси соединение не работает, и так получается быстрее.
Переходим на сайт https://apk.support/apk-downloader, копируем ссылку нашего приложения из Google Play и нажимаем кнопку Analyze, далее снизу будут сборки под конкретный регион, я выбрал EU:
101342

Очень важно, чтобы на устройстве и в декомпиляторе оказались одинаковые файлы.

То есть надо скачать apk файл с сайта выше, закинуть его на наше устройство, и также оставить на пк, так как мы в дальнейшем будем его разбирать. Ибо в разных версиях приложения (Имеется в виду не именно номер версии, а отдельные сборки для us/eu) могут содержаться разные классы внутри приложения, что очень затруднит нас

Запускаем приложение
Открываем новую командную строку и пишем «frida-ps -Uai»:
101314


Здесь указаны все установленные приложения, а точнее их PID, имена и идентификаторы. Нам нужен будет Pikabu, а именно ru.pikabu.adndroid

SSL Pinning. Все приложения от просмотра трафика защищены по-разному, в большинстве случаев мне хватало команды «objection --gadget "name" explore --startup-command "android sslpinning disable"» (где name – идентификатор приложения). В случае с Пикабу это не действовало, ошибок никаких не было, но и приложение не работало.
Покопавшись в интернете, я нашёл подходящий скрипт для снятия пиннинга, а именно https://pastebin.com/AxfLBVeG. Создаём файл script.js и вставляем данный код в наш файл. Много подобных готовых скриптов лежит на https://codeshare.frida.re/ и в гугле, не только для обхода SSL Pinning, но и для всяких других штук.

Далее из папки, где лежит наш новосозданный скрипт, запускаем командную строку (Как мы делали в случае с platform tools) и пишем команду:
  • frida -U -l script.js -f ru.pikabu.android

Этой командой мы запустим приложение, одновременно внедрив в него наш скрипт для обхода ssl pinning.

Как видим, посты прогрузились, трафик в Charles proxy появился, значит всё работает:
1671609997575.png

Работа с декомпилятором JADX
Мы будем смотреть код приложения (Нужно же как-то понять, как генерируется наш хэш?) с помощью JADX.
Скачиваем последнюю версию JADX - https://github.com/skylot/jadx/releases и распаковываем его в удобное место.

Открываем наш заранее скачанный apk файл Pikabu:
101316


101317


Ждём прогрузки. У нас открылся проект с декомпилированным кодом:
101318



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

В JADX есть опция поиска:
101319

101320

Можно сразу поставить галочку «Keep open», для удобства:
101321


Как именно искать нужный нам фрагмент кода, где может генерироваться наш хэш?
Примечание: поиск подобного кода во многих случаях значительно отличается от того, который показан в этой статье.

Для начала, попробуем вписать в поиск «"hash"» (именно с кавычками), то есть то имя, которое мы нашли в данных запроса.
101425


Пробуем:
101322


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

Посмотрим на все 5 вариантов:
101427


101428


101429


101430


В общем, мне ничего не приглянулось, нужно искать дальше.
Примечание 1: сразу хочу сказать, что всё-таки прошлые функции скорей всего можно "покрутить", т.е. посмотреть какие именно аргументы они принимают и возвращают, но в случае с нашим приложением всё немного проще, так что дальше я покажу поиск нужного нам кода по-другому.​
Примечание 2. Чтобы попасть в нужную нам функцию в JADX, нужно зажать ctrl и кликнуть на неё.​
К примеру, здесь есть какая-то функция «d», мы можем посмотреть, что она из себя представляет, кликнув на её название (то есть буковку «d») с зажатым ctrl.​
101328

Но вот во втором варианте в поиске есть что-то с названием «CE_SETTINGS_HASH», и ещё там есть “hash”:

101323


101324


Отсюда, по идее, можно продолжить поиск. А именно, по «CE_SETTINGS_HASH»:
101325


Здесь мне сразу приглянулся данный фрагмент кода, потому что он возвращает какую-то функцию (i), и в её параметрах есть наше ключевое слово (CE_SETTINGS_HASH), и ещё какая-то функция "d", и с ней ещё 4 параметра, возможно, это то что нам нужно. Да и код находится в пакете "ru.pikabu.android.server.s":

101326

101327



Далее можно (нужно) осмотреть найденный фрагмент кода, а именно посмотреть данные функции:
101329

Функция i:
101331

Функция d:
101452


Я сразу подумал, что здесь ничего не генерируется, ибо по беглому осмотру мне показалось, что здесь идёт какая-то работа с массивами. Попробуем тогда что-то другое.
Что делать дальше? Как вариант, можно осмотреть всю область текущего файла, где мы нашли прошлые функции. Ибо частенько рядом с такими функциями есть то, что нам нужно, либо то, что укажет нам, как именно дальше надо искать.

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

Видно, что в нём при возврате, есть сразу две функции, ii.p.a и ii.p.b, последняя принимает на вход строку, видимо.

Посмотрим на код самих этих функций, для начала ii.p.b:
101334


MD5 – это алгоритм хэширования. То есть, скорей всего, мы очень близко.

Итак, скорей всего мы нашли нужную функцию, что дальше? Нужно как-то проверить нашу находку.
Наша функция что-то получает на входе, и нам нужно понять, что именно.

В данном случае, анализируя код, мы видим, что функция на вход получает строку, это видно по типу переменной, «String»:
101335


Теперь, надо как-то понять, какие именно аргументы функция получает на входе.

Нам нужно будет сделать хук через Frida. Что такое хук?
  • Из гугла: Хуки — это технология перехвата вызовов функций в чужих процессах.
Коротко говоря, нам надо перехватить аргументы, которые передаются в нужную нам функцию, чтобы понять, из чего именно генерировать хэш.


Код хука функции для Фриды выглядит примерно так:
JavaScript:
Java.perform(function () {
        var foy = Java.use('ii.p');
        foy.b.overload('java.lang.String').implementation = function(a) {
        console.log(a);
    return this.b(a);
    }
    })
Объяснение по коду:
var foy = Java.use('ii.p');, где 'ii.p' - имя нашего пакета, где находится функция. Его можно получить в jadx:
101336


foy.b.overload('java.lang.String') – в данном случае b – это как раз наша функция, а 'java.lang.String' – это тип аргумента, который в неё передаётся, в нашем случае это строка, как сказано ранее.

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

Теперь нам надо поместить наш код хука в файл и внедрить его в приложение. Я добавил его в наш файл script.js. То есть теперь в нашем файле одновременно два скрипта, для обхода SSL Pinning, и для хука функции:
101337


Закрываем прошлое окно консоли, где у нас был включен ssl unpinning, и запускаем наш обновлённый скрипт той же командой:

frida -U -l script.js -f ru.pikabu.android
101338

Как видим, оба скрипта работают одновременно. Не очень удобно, конечно, учитывая, что они вместе пишут лог, но при раздельном запуске (т.е. в двух отдельных окнах командной строки по скрипту), у меня крашилось приложение, в случае с Pikabu.

Помимо работы первого нашего скрипты (для снятия ssl pinning), у нас в логе появляются новые строки, именно их на входе получает хукнутая нами функция.

Сейчас попробуем зарегистрировать аккаунт в приложении. Смотрим наш запрос в сниффере:

101434


Теперь смотрим на консоль, где работают наши скрипты:
101435


Те строки, где присутствует "user.name.check" – очевидно, что это проверка логина (существует он на пикабу, или нет).

А вот самая последняя строка – это как раз то, что нам нужно, судя по "user.register" (Оно совпадает с url регистрации из сниффера). Мы уже понимаем, что на вход в функцию при регистрации попадает вот такая строка «kmq4!2cPl)peZ,user.register,1671570215943,1,123123123,hjfjgjfjfjh,[email protected]»
Можно разобрать её:
  1. kmq4!2cPl)peZ – это что-то похожее на соль. Соль в хэше - это дополнительная случайная строка, которая добавляется к основной строке перед хэшированием.
  2. user.register - часть ссылки для регистрации, где оригинал - «https://api.pikabu.ru/v1/user.register»
  3. 1671570215943 – unix timestamp
  4. 1 – я не знаю что это такое, да и плевать в данном случае, ибо, судя по логу, оно статичное
  5. 123123cfcfZ – наш пароль
  6. Hjfjgjfjfjh - логин
  7. [email protected] – наша почта
P.S. пароль с Z - мой старинный трэш-пароль, к этому году он никакого отношения не имеет.

Собираем код для генерации хэша
Мы успешно получили входные аргументы нашей функции. Также не забываем о том, что в генерации «hash» участвуют две функции:

101343


Первую (ii.p.b) мы уже разобрали. Посмотрим на вторую (ii.p.a):
101345

Здесь происходит преобразование в Base64, если судить по надписи "Base64".

У нас уже есть пример хэша и данных, которые в него попадают. Нужно попробовать собрать его и сравнить со сниффером, то у нас получилось, или нет.
Получается такая схема: Входные данные (То есть наша полученная строка) -> MD5 -> Base64
Нужно проверить, правильно ли мы всё поняли.

Нашу полученную строку "kmq4!2cPl)peZ,user.register,1671570215943,1,123123cfcfZ,hjfjgjfjfjh,[email protected]" преобразуем сначала в md5:
В директивах using пропишем "using System.Security.Cryptography;"
1671612144860.png 1671612165076.png

C#:
string input = project.Variables["text"].Value;
System.Security.Cryptography.MD5 md5Hasher = System.Security.Cryptography.MD5.Create();
byte[] data = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder md5hash = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
    md5hash.Append(data[i].ToString("x2"));
}
return md5hash.ToString();
101349


Теперь преобразуем её в base64:
101350

C#:
project.Variables["result2"].Value = Convert.ToBase64String(Encoding.UTF8.GetBytes(project.Variables["result"].Value));

Теперь сравниваем полученные строки.

Строка из сниффера:
101351


Наша строка:
101352


Почти совпадает. Но что такое "\u003d"? Погуглив, стало понятно, что это равно "=", то есть тоже самое, что и в нашем сгенерированном хэше:
101451


То есть, мы всё сделали верно.

Теперь надо попробовать отправить запрос на регистрацию с изменёнными данными и сгенерированным нами хэшем.
В запросе изменим почту на "[email protected]", логин на "testzenno123", а пароль сделаем "123123zenno". Итого у нас получается входная строка хэша вида "kmq4!2cPl)peZ,user.register,1671608516940,1,123123zenno,testzenno123,[email protected]".

Прогоним её через md5 и base64:
101446


Подставим все данные, включая новый хэш, в запрос и отправим его:
101448


Как видим, хэш прошёл и мы получили id регистрации.
То есть, дело сделано, мы смогли реализовать один из самых простых хэшей в мобильных приложениях, дальше уже можно делать регистрацию (Но статья совсем не об этом).
 
Тема статьи
Нестандартные хаки
Номер конкурса статей
Восемнадцатый конкурс статей

Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

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

Последнее редактирование:

Brabus_bots

Client
Регистрация
13.04.2019
Сообщения
647
Благодарностей
428
Баллы
63
Крутая статья)

Возможно стоит сделать уточнение простыми словами для читающих, что такое "соль хэша". Это рандомная строка, которую знают только разрабы приложения (без учета вскрытия приложения). Её специально подмешивают в итоговый хэш для дополнительной защиты от перебора паролей.

Автору лайк, круто оформил статью
 
  • Спасибо
Реакции: radv и southside

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63
Крутая статья)

Возможно стоит сделать уточнение простыми словами для читающих, что такое "соль хэша". Это рандомная строка, которую знают только разрабы приложения (без учета вскрытия приложения). Её специально подмешивают в итоговый хэш для дополнительной защиты от перебора паролей.

Автору лайк, круто оформил статью
Да, спасибо, чуть позже допишу, сразу не подумал об этом)
 
Последнее редактирование:

adept

Client
Регистрация
05.10.2015
Сообщения
44
Благодарностей
11
Баллы
8
Ну это топ, наконец то хоть одна дельная статья на форуме как соль хэша парсить, спасибо.
 
  • Спасибо
Реакции: frion-seo и southside

Dmitriy Ka

Client
Регистрация
03.05.2016
Сообщения
536
Благодарностей
281
Баллы
63
Вот это круто! Такое я люблю!:ay:
Мой голос однозначно))
 
  • Спасибо
Реакции: southside

inilim

Client
Регистрация
16.09.2017
Сообщения
441
Благодарностей
170
Баллы
43
мне стало интересно, можно ли мобильные приложения упаковывать и использовать напрямую языками программирования? например php. А не марочится с эмуляторами.
 

Roman*

Client
Регистрация
25.09.2013
Сообщения
1 649
Благодарностей
653
Баллы
113
Респект за статью, то, что нужно по прилкам. Если можно чуть поподробнее, по функциям и аргументам, запутался как все таки вся цепочка шла поиска, может быть в других прилках получится применить.
 

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63
Респект за статью, то, что нужно по прилкам. Если можно чуть поподробнее, по функциям и аргументам, запутался как все таки вся цепочка шла поиска, может быть в других прилках получится применить.
Без проблем, чуть позже отдельно напишу о логике поиска, сильно занят в эти дни (как обычно под нг)
 

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63
мне стало интересно, можно ли мобильные приложения упаковывать и использовать напрямую языками программирования? например php. А не марочится с эмуляторами.
До конца не понял суть вопроса) "Упаковать" - это как?
 

radv

Client
Регистрация
11.05.2015
Сообщения
3 675
Благодарностей
1 855
Баллы
113
Еще одна познавательная статья по андроид приложениям. :ay: Спасибо автору
:az:
 
  • Спасибо
Реакции: frion-seo и southside

Ilshakin

Client
Регистрация
14.02.2017
Сообщения
630
Благодарностей
540
Баллы
93
мой голос тут, молодец !
чуть дополню линком на старенькую shared статью:

да чего ? приложение можно не только расковырять, но и пересобрать,
внести свои правки, сделать платное - бесплатным, обязательную проверку - необязательной и тд
но искомый ресурс может сверять hash вновь собранного приложения, в таком случае на помощь может придти
fidler core, с помощью которого можно обойти и проверку хеша, работая с подменой запросов (правда не всегда и не везде) ....
 
  • Спасибо
Реакции: fridayman и southside

frion-seo

Client
Регистрация
27.02.2011
Сообщения
506
Благодарностей
451
Баллы
63
Вот это я понимаю ! Голос за тебя !!!!!
 
  • Спасибо
Реакции: southside

sw_sw

Client
Регистрация
24.02.2017
Сообщения
693
Благодарностей
277
Баллы
63
Ну вот и победитель обозначился)
Достойно. И очень годная тема.
 
  • Спасибо
Реакции: frion-seo

fridayman

Client
Регистрация
25.03.2018
Сообщения
167
Благодарностей
259
Баллы
63
Сорян, ребятки, за вопрос не по содержанию, а по теме. То есть, если я правильно понял, разработка на андроид у пикабу дырявая?
 
  • Спасибо
Реакции: southside

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63
Сорян, ребятки, за вопрос не по содержанию, а по теме. То есть, если я правильно понял, разработка на андроид у пикабу дырявая?
Не, у них в общем-то всё нормально)
 

fridayman

Client
Регистрация
25.03.2018
Сообщения
167
Благодарностей
259
Баллы
63
Не, у них в общем-то всё нормально)
Хорошо. Но мне все же хочется понять и признать это классное решение. Расскажи, пожалуйста, про промышленное применение схемы?
 

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63
Хорошо. Но мне все же хочется понять и признать это классное решение. Расскажи, пожалуйста, про промышленное применение схемы?
Имеется в виду, для чего всё это делалось? Если да, то за последний год у меня было не мало сервисов, для которых нужно было сделать софт, были случаи когда через веб сделать не получалось (всякие js были, которые я не осиливал, и прочее), а через приложения, учитывая опыт данной статьи, всё было намного проще
Но, конечно, это для кого как
 
  • Спасибо
Реакции: seodamage и lzlmrf

lzlmrf

Client
Регистрация
14.08.2015
Сообщения
487
Благодарностей
148
Баллы
43
спасибо, круто!
 
  • Спасибо
Реакции: southside

ex3maL

Client
Регистрация
22.05.2020
Сообщения
359
Благодарностей
267
Баллы
63

fridayman

Client
Регистрация
25.03.2018
Сообщения
167
Благодарностей
259
Баллы
63
Имеется в виду, для чего всё это делалось? Если да, то за последний год у меня было не мало сервисов, для которых нужно было сделать софт, были случаи когда через веб сделать не получалось (всякие js были, которые я не осиливал, и прочее), а через приложения, учитывая опыт данной статьи, всё было намного проще
Но, конечно, это для кого как
Кажись я теперь понял. Это про автоматизацию регистраций учёток там, где сделать это через стандартные возможности зеннопостера нельзя или более волокитно из-за хитрого фронтенда. В случае с поиском и расшифровкой хэша, а также дальнейшим его применением в составе шаблонов - проект становится реализуем. Все правильно рассудил?
 
  • Спасибо
Реакции: southside

Kaspian

Client
Регистрация
23.12.2013
Сообщения
93
Благодарностей
132
Баллы
33
Отличная статья!
 
  • Спасибо
Реакции: southside

trecho

Client
Регистрация
12.07.2018
Сообщения
171
Благодарностей
124
Баллы
43
лучшая статья в этом конкурсе
 
  • Спасибо
Реакции: southside

lamar015

Client
Регистрация
22.08.2021
Сообщения
23
Благодарностей
4
Баллы
3
Дисклеймер: Статья создана в развлекательных, ознакомительных и образовательных целях.

Вступление
Примерно 7 месяцев назад один знакомый попросил меня посмотреть мобильное приложение Pikabu, к чему я и приступил.

При просмотре запросов регистрации я увидел такую вот штуку в данных запроса:
Посмотреть вложение 101293

Если скопировать запрос полностью (то есть, ту же почту, логин и т.д.) в зеннопостер, то, вроде бы, всё хорошо, нам пришёл в ответ айди регистрации:
Посмотреть вложение 101294

Но если мы поменяем в запросе какие-либо данные, к примеру почту, на которую мы будем регистрировать аккаунт, в ответ на запрос уже придёт ошибка:
Посмотреть вложение 101295

Что такое хэш? По гуглу, это - функция, осуществляющая преобразование массива входных данных произвольной длины в выходную битовую строку установленной длины, выполняемое определённым алгоритмом.
К примеру, если взять алгоритм хэширования MD5, то строка "password" превращается в "5f4dcc3b5aa765d61d8327deb882cf99".

То есть, с регистрацией аккаунтов через мобильное api у нас уже появились проблемы, которые надо как-то решать.
В данной статье я постараюсь максимально (насколько это у меня получится) простым языком объяснить решение данной проблемы. Также возможны недочёты в тексте, буду править, что найду.
Хэш пикабу один из самый простых что я видел.

Установку Frida и сниффера я постараюсь разложить кратко, но без пропуска важных моментов, так как данные этапы уже был описаны на форуме (а именно в https://zennolab.com/discussion/threads/android-na-post-get-s-pomoschju-frida-server-burpsuite-i-bonus.79264/, и ещё где-то).

Инструментарий данной статьи:

  1. Сниффер - Charles proxy. Можно использовать и BurpSuite, и Fiddler, без разницы.
  2. Устройство на android с root – в моём случае это реальный телефон, Redmi 6a, прошитый. Можно использовать и эмулятор. Почему именно реальное устройство? Выбор давно пал в сторону него, ибо с эмуляторами уже не раз было много проблем (в частности, вылеты приложений и т.п.), как раз в арсенале был старенький, но вполне работающий Redmi 6a. Гайды о прошивках можно найти на 4pda, в большинстве случаев всё расписано по шагам. Да и в отдельных, но редко встречающихся случаях приложение имеет детект эмулятора.
  3. Декомпилятор apk файлов - JADX (https://github.com/skylot/jadx)
  4. Frida - https://frida.re/ - это набор инструментов для разработчиков, реверс-инженеров и исследователей безопасности.
  5. Скачиватель apk файлов (входить через впн, если вы из ру) - https://apk.support/apk-downloader

1. Устанавливаем последнюю версию python - https://www.python.org/downloads/Посмотреть вложение 101298

Обязательно ставим галочку на “add to path” в установщике:
Посмотреть вложение 101299

2. Открываем консоль windows и пишем в ней «pip install frida-tools»
Посмотреть вложение 101300
По последней строчке видим, что всё успешно установилось.

3. По такому же принципу устанавливаем objection, пишем в консоли команду «pip install objection»

4. Далее скачиваем Android SDK Platform Tools - https://dl.google.com/android/repository/platform-tools-latest-windows.zip и распаковываем в удобной для нас папке.

В окне папки, где мы распаковали наш архим, пишем «cmd» и нажимаем enter, должна открыться консоль с путём нашей папки:
Посмотреть вложение 101301Посмотреть вложение 101302

Устройство на android должно быть с рутом (root). В настройках разработчика должен быть включен «USB Debugging». Название может отличаться на разных телефонах, о вашем устройстве лучше почитать на 4pda.

Подключаем телефон по usb к пк. В консоли пишем «adb devices», на телефоне может появится уведомление о разрешении доступа, принимаем его. Наш девайс должен появится в консоли:
Посмотреть вложение 101303

Далее переходим на https://github.com/frida/frida/releases и скачиваем frida-server для android:
Посмотреть вложение 101304
Информацию о том, какой именно файл нужно скачать, можно понять, погуглив конфигурацию вашего устройства.

Распаковываем архив (формата .xz) в нашу папку, куда мы положили Android SDK Platform Tools, и переименовываем распакованный файл в “frida-server” (для удобства, ибо изначально там файл с номером версии).
Посмотреть вложение 101305

Далее в уже открытой консоли пишем три команды по очереди:
  • adb root (бывает нужна, в моём случае – нет)
  • adb push frida-server /data/local/tmp/
  • adb shell "chmod 755 /data/local/tmp/frida-server"
Посмотреть вложение 101306
Видим, что файл успешно передался на телефон.

И далее запускаем сервер фриды:
Посмотреть вложение 101453
При этом никаких сообщений быть не должно, т.е. состояние как на скриншоте означает что сервер Фриды запущен.

Всё, данное окно не трогаем.

Примечание. На моём устройстве, для запуска сервера фриды, в начале нужно прописать «adb shell "su -c setenforce 0"». Бывают ещё редкие ошибки, но 99% их решений гуглится.

Если никаких ошибок в консоли нет, то, скорей всего, всё нормально работает.

Откроем новое окно консоли (Именно новое!) и проверим, написав команду frida-ps -Uai:
Посмотреть вложение 101454
Как мы видим, нам в ответе показаны все установленные приложения на устройстве, то есть всё работает.

Примечание. Если вы закроете окно консоли, в котором вы запустили сервер фриды, можно убить процесс через данные команды:
  • adb shell su
  • netstat -tunlp
  • Далее ищите процесс «frida-server» в списке, запоминаете его PID, и убиваете командой «kill -9 pid», заменив pid на нужный номер.
Я использую Charles proxy. Мне он нравится из-за простоты и наличия всех нужных мне инструментов.

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

1. В случае с Charles proxy качаем триал версию с их сайта https://www.charlesproxy.com/download/ и генерируем ключ на сайте zzzmode com/mytools/charles/.

2. После запуска сниффера на пк, ставим в настройках wi-fi на устройстве проксю, которая показана вот в этом пункте меню:
Посмотреть вложение 101310

Посмотреть вложение 101311

3. Проходим по ссылке в браузере устройства на chls.pro/ssl и ставим сертификат.

4. Также сразу отключаем windows прокси (находится в разделе proxy – windows proxy) и включаем обе кнопки в главном меню:
Посмотреть вложение 101312
Посмотреть вложение 101313
Первая отвечает за запись трафика, вторая – за ssl проксю.

Что касается установки и снятия прокси сниффера на устройстве, когда мне нужно снять трафик с приложения, я использую команды
  • adb shell settings put global http_proxy proxy:port– поставить прокси
  • adb shell settings put global http_proxy :0 – снять прокси
Ибо часто нужно зайти в Google Play, а через прокси соединение не работает, и так получается быстрее.
Переходим на сайт https://apk.support/apk-downloader, копируем ссылку нашего приложения из Google Play и нажимаем кнопку Analyze, далее снизу будут сборки под конкретный регион, я выбрал EU:
Посмотреть вложение 101342
Очень важно, чтобы на устройстве и в декомпиляторе оказались одинаковые файлы.

То есть надо скачать apk файл с сайта выше, закинуть его на наше устройство, и также оставить на пк, так как мы в дальнейшем будем его разбирать. Ибо в разных версиях приложения (Имеется в виду не именно номер версии, а отдельные сборки для us/eu) могут содержаться разные классы внутри приложения, что очень затруднит нас

Запускаем приложение
Открываем новую командную строку и пишем «frida-ps -Uai»:
Посмотреть вложение 101314

Здесь указаны все установленные приложения, а точнее их PID, имена и идентификаторы. Нам нужен будет Pikabu, а именно ru.pikabu.adndroid

SSL Pinning. Все приложения от просмотра трафика защищены по-разному, в большинстве случаев мне хватало команды «objection --gadget "name" explore --startup-command "android sslpinning disable"» (где name – идентификатор приложения). В случае с Пикабу это не действовало, ошибок никаких не было, но и приложение не работало.
Покопавшись в интернете, я нашёл подходящий скрипт для снятия пиннинга, а именно https://pastebin.com/AxfLBVeG. Создаём файл script.js и вставляем данный код в наш файл. Много подобных готовых скриптов лежит на https://codeshare.frida.re/ и в гугле, не только для обхода SSL Pinning, но и для всяких других штук.

Далее из папки, где лежит наш новосозданный скрипт, запускаем командную строку (Как мы делали в случае с platform tools) и пишем команду:
  • frida -U -l script.js -f ru.pikabu.android

Этой командой мы запустим приложение, одновременно внедрив в него наш скрипт для обхода ssl pinning.

Как видим, посты прогрузились, трафик в Charles proxy появился, значит всё работает:
Посмотреть вложение 101315

Работа с декомпилятором JADX
Мы будем смотреть код приложения (Нужно же как-то понять, как генерируется наш хэш?) с помощью JADX.
Скачиваем последнюю версию JADX - https://github.com/skylot/jadx/releases и распаковываем его в удобное место.

Открываем наш заранее скачанный apk файл Pikabu:
Посмотреть вложение 101316

Посмотреть вложение 101317

Ждём прогрузки. У нас открылся проект с декомпилированным кодом:
Посмотреть вложение 101318


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

В JADX есть опция поиска:
Посмотреть вложение 101319
Посмотреть вложение 101320
Можно сразу поставить галочку «Keep open», для удобства:
Посмотреть вложение 101321

Как именно искать нужный нам фрагмент кода, где может генерироваться наш хэш?
Примечание: поиск подобного кода во многих случаях значительно отличается от того, который показан в этой статье.

Для начала, попробуем вписать в поиск «"hash"» (именно с кавычками), то есть то имя, которое мы нашли в данных запроса.
Посмотреть вложение 101425

Пробуем:
Посмотреть вложение 101322

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

Посмотрим на все 5 вариантов:
Посмотреть вложение 101427

Посмотреть вложение 101428

Посмотреть вложение 101429

Посмотреть вложение 101430

В общем, мне ничего не приглянулось, нужно искать дальше.
Примечание 1: сразу хочу сказать, что всё-таки прошлые функции скорей всего можно "покрутить", т.е. посмотреть какие именно аргументы они принимают и возвращают, но в случае с нашим приложением всё немного проще, так что дальше я покажу поиск нужного нам кода по-другому.​
Примечание 2. Чтобы попасть в нужную нам функцию в JADX, нужно зажать ctrl и кликнуть на неё.​
К примеру, здесь есть какая-то функция «d», мы можем посмотреть, что она из себя представляет, кликнув на её название (то есть буковку «d») с зажатым ctrl.​

Но вот во втором варианте в поиске есть что-то с названием «CE_SETTINGS_HASH», и ещё там есть “hash”:

Посмотреть вложение 101323

Посмотреть вложение 101324

Отсюда, по идее, можно продолжить поиск. А именно, по «CE_SETTINGS_HASH»:
Посмотреть вложение 101325

Здесь мне сразу приглянулся данный фрагмент кода, потому что он возвращает какую-то функцию (i), и в её параметрах есть наше ключевое слово (CE_SETTINGS_HASH), и ещё какая-то функция "d", и с ней ещё 4 параметра, возможно, это то что нам нужно. Да и код находится в пакете "ru.pikabu.android.server.s":

Посмотреть вложение 101326
Посмотреть вложение 101327


Далее можно (нужно) осмотреть найденный фрагмент кода, а именно посмотреть данные функции:
Посмотреть вложение 101329
Функция i:
Посмотреть вложение 101331
Функция d:
Посмотреть вложение 101452

Я сразу подумал, что здесь ничего не генерируется, ибо по беглому осмотру мне показалось, что здесь идёт какая-то работа с массивами. Попробуем тогда что-то другое.
Что делать дальше? Как вариант, можно осмотреть всю область текущего файла, где мы нашли прошлые функции. Ибо частенько рядом с такими функциями есть то, что нам нужно, либо то, что укажет нам, как именно дальше надо искать.

К примеру, во время просмотра мне приглянулся вот такой фрагмент кода, который был чуть выше наших предыдущих функций:
Посмотреть вложение 101333
Видно, что в нём при возврате, есть сразу две функции, ii.p.a и ii.p.b, последняя принимает на вход строку, видимо.

Посмотрим на код самих этих функций, для начала ii.p.b:
Посмотреть вложение 101334

MD5 – это алгоритм хэширования. То есть, скорей всего, мы очень близко.

Итак, скорей всего мы нашли нужную функцию, что дальше? Нужно как-то проверить нашу находку.
Наша функция что-то получает на входе, и нам нужно понять, что именно.

В данном случае, анализируя код, мы видим, что функция на вход получает строку, это видно по типу переменной, «String»:
Посмотреть вложение 101335

Теперь, надо как-то понять, какие именно аргументы функция получает на входе.

Нам нужно будет сделать хук через Frida. Что такое хук?
  • Из гугла: Хуки — это технология перехвата вызовов функций в чужих процессах.
Коротко говоря, нам надо перехватить аргументы, которые передаются в нужную нам функцию, чтобы понять, из чего именно генерировать хэш.


Код хука функции для Фриды выглядит примерно так:
JavaScript:
Java.perform(function () {
        var foy = Java.use('ii.p');
        foy.b.overload('java.lang.String').implementation = function(a) {
        console.log(a);
    return this.b(a);
    }
    })
Объяснение по коду:
var foy = Java.use('ii.p');, где 'ii.p' - имя нашего пакета, где находится функция. Его можно получить в jadx:
Посмотреть вложение 101336

foy.b.overload('java.lang.String') – в данном случае b – это как раз наша функция, а 'java.lang.String' – это тип аргумента, который в неё передаётся, в нашем случае это строка, как сказано ранее.

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

Теперь нам надо поместить наш код хука в файл и внедрить его в приложение. Я добавил его в наш файл script.js. То есть теперь в нашем файле одновременно два скрипта, для обхода SSL Pinning, и для хука функции:
Посмотреть вложение 101337

Закрываем прошлое окно консоли, где у нас был включен ssl unpinning, и запускаем наш обновлённый скрипт той же командой:

frida -U -l script.js -f ru.pikabu.android
Посмотреть вложение 101338
Как видим, оба скрипта работают одновременно. Не очень удобно, конечно, учитывая, что они вместе пишут лог, но при раздельном запуске (т.е. в двух отдельных окнах командной строки по скрипту), у меня крашилось приложение, в случае с Pikabu.

Помимо работы первого нашего скрипты (для снятия ssl pinning), у нас в логе появляются новые строки, именно их на входе получает хукнутая нами функция.

Сейчас попробуем зарегистрировать аккаунт в приложении. Смотрим наш запрос в сниффере:

Посмотреть вложение 101434

Теперь смотрим на консоль, где работают наши скрипты:
Посмотреть вложение 101435

Те строки, где присутствует "user.name.check" – очевидно, что это проверка логина (существует он на пикабу, или нет).

А вот самая последняя строка – это как раз то, что нам нужно, судя по "user.register" (Оно совпадает с url регистрации из сниффера). Мы уже понимаем, что на вход в функцию при регистрации попадает вот такая строка «kmq4!2cPl)peZ,user.register,1671570215943,1,123123123,hjfjgjfjfjh,[email protected]»
Можно разобрать её:
  1. kmq4!2cPl)peZ – это что-то похожее на соль. Соль в хэше - это дополнительная случайная строка, которая добавляется к основной строке перед хэшированием.
  2. user.register - часть ссылки для регистрации, где оригинал - «https://api.pikabu.ru/v1/user.register»
  3. 1671570215943 – unix timestamp
  4. 1 – я не знаю что это такое, да и плевать в данном случае, ибо, судя по логу, оно статичное
  5. 123123cfcfZ – наш пароль
  6. Hjfjgjfjfjh - логин
  7. [email protected] – наша почта
P.S. пароль с Z - мой старинный трэш-пароль, к этому году он никакого отношения не имеет.

Собираем код для генерации хэша
Мы успешно получили входные аргументы нашей функции. Также не забываем о том, что в генерации «hash» участвуют две функции:

Посмотреть вложение 101343

Первую (ii.p.b) мы уже разобрали. Посмотрим на вторую (ii.p.a):
Посмотреть вложение 101345

Здесь происходит преобразование в Base64, если судить по надписи "Base64".

У нас уже есть пример хэша и данных, которые в него попадают. Нужно попробовать собрать его и сравнить со сниффером, то у нас получилось, или нет.
Получается такая схема: Входные данные (То есть наша полученная строка) -> MD5 -> Base64
Нужно проверить, правильно ли мы всё поняли.

Нашу полученную строку "kmq4!2cPl)peZ,user.register,1671570215943,1,123123cfcfZ,hjfjgjfjfjh,[email protected]" преобразуем сначала в md5:
В директивах using пропишем "using System.Security.Cryptography;"
Посмотреть вложение 101346 Посмотреть вложение 101347

C#:
string input = project.Variables["text"].Value;
System.Security.Cryptography.MD5 md5Hasher = System.Security.Cryptography.MD5.Create();
byte[] data = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder md5hash = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
    md5hash.Append(data[i].ToString("x2"));
}
return md5hash.ToString();
Посмотреть вложение 101349

Теперь преобразуем её в base64:
Посмотреть вложение 101350
C#:
project.Variables["result2"].Value = Convert.ToBase64String(Encoding.UTF8.GetBytes(project.Variables["result"].Value));

Теперь сравниваем полученные строки.

Строка из сниффера:
Посмотреть вложение 101351

Наша строка:
Посмотреть вложение 101352

Почти совпадает. Но что такое "\u003d"? Погуглив, стало понятно, что это равно "=", то есть тоже самое, что и в нашем сгенерированном хэше:
Посмотреть вложение 101451

То есть, мы всё сделали верно.

Теперь надо попробовать отправить запрос на регистрацию с изменёнными данными и сгенерированным нами хэшем.
В запросе изменим почту на "[email protected]", логин на "testzenno123", а пароль сделаем "123123zenno". Итого у нас получается входная строка хэша вида "kmq4!2cPl)peZ,user.register,1671608516940,1,123123zenno,testzenno123,[email protected]".

Прогоним её через md5 и base64:
Посмотреть вложение 101446

Подставим все данные, включая новый хэш, в запрос и отправим его:
Посмотреть вложение 101448

Как видим, хэш прошёл и мы получили id регистрации.
То есть, дело сделано, мы смогли реализовать один из самых простых хэшей в мобильных приложениях, дальше уже можно делать регистрацию (Но статья совсем не об этом).
одна из лучших статей что я читал на форуме,! 5 балов!
 
  • Спасибо
Реакции: southside

MaxMan

Client
Регистрация
15.02.2021
Сообщения
93
Благодарностей
79
Баллы
18
Спасибо за такое подробное изложение материала. Проголосовал за вашу статью.
Есть вопрос относительно данных, которые получает сервер - что он видит о нас при такой регистрации кроме ip?
 
  • Спасибо
Реакции: southside

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63
Спасибо всем, очень рад что зашла тематика статьи :-)
И извините, всем уже после нг отвечу, в первых числах января (тк кратко не напишешь о вопросах), в том числе лс, ибо сейчас уехал
 
  • Спасибо
Реакции: ex3maL

MaxMan

Client
Регистрация
15.02.2021
Сообщения
93
Благодарностей
79
Баллы
18
Спасибо всем, очень рад что зашла тематика статьи :-)
И извините, всем уже после нг отвечу, в первых числах января (тк кратко не напишешь о вопросах), в том числе лс, ибо сейчас уехал
Хорошо, спасибо. С наступающим!
 
  • Спасибо
Реакции: southside

lamar015

Client
Регистрация
22.08.2021
Сообщения
23
Благодарностей
4
Баллы
3
101740


SSL unpinning прошел, но при попытке вызвать функцию следующая ошибка. Возможно, из-за того что делаю на эмуляторе? Кто-то сталкивался?
 

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63
Посмотреть вложение 101740

SSL unpinning прошел, но при попытке вызвать функцию следующая ошибка. Возможно, из-за того что делаю на эмуляторе? Кто-то сталкивался?
Я с фридой не работал на эмуляторе, смогу посмотреть чуть позже (см. моё сообщение выше)
 

lamar015

Client
Регистрация
22.08.2021
Сообщения
23
Благодарностей
4
Баллы
3

southside

Client
Регистрация
20.04.2019
Сообщения
198
Благодарностей
250
Баллы
63

Кто просматривает тему: (Всего: 2, Пользователи: 0, Гости: 2)