Дисклеймер: Статья создана в развлекательных, ознакомительных и образовательных целях.
Вступление
Примерно 7 месяцев назад один знакомый попросил меня посмотреть мобильное приложение Pikabu, к чему я и приступил.Вступление
При просмотре запросов регистрации я увидел такую вот штуку в данных запроса:
Если скопировать запрос полностью (то есть, ту же почту, логин и т.д.) в зеннопостер, то, вроде бы, всё хорошо, нам пришёл в ответ айди регистрации:
Но если мы поменяем в запросе какие-либо данные, к примеру почту, на которую мы будем регистрировать аккаунт, в ответ на запрос уже придёт ошибка:
Что такое хэш? По гуглу, это - функция, осуществляющая преобразование массива входных данных произвольной длины в выходную битовую строку установленной длины, выполняемое определённым алгоритмом.
К примеру, если взять алгоритм хэширования MD5, то строка "password" превращается в "5f4dcc3b5aa765d61d8327deb882cf99".
То есть, с регистрацией аккаунтов через мобильное api у нас уже появились проблемы, которые надо как-то решать.
В данной статье я постараюсь максимально (насколько это у меня получится) простым языком объяснить решение данной проблемы. Также возможны недочёты в тексте, буду править, что найду.
Хэш пикабу один из самый простых что я видел.
Установку Frida и сниффера я постараюсь разложить кратко, но без пропуска важных моментов, так как данные этапы уже был описаны на форуме (а именно в https://zennolab.com/discussion/threads/android-na-post-get-s-pomoschju-frida-server-burpsuite-i-bonus.79264/, и ещё где-то).
Инструментарий данной статьи:
- Сниффер - Charles proxy. Можно использовать и BurpSuite, и Fiddler, без разницы.
- Устройство на android с root – в моём случае это реальный телефон, Redmi 6a, прошитый. Можно использовать и эмулятор. Почему именно реальное устройство? Выбор давно пал в сторону него, ибо с эмуляторами уже не раз было много проблем (в частности, вылеты приложений и т.п.), как раз в арсенале был старенький, но вполне работающий Redmi 6a. Гайды о прошивках можно найти на 4pda, в большинстве случаев всё расписано по шагам. Да и в отдельных, но редко встречающихся случаях приложение имеет детект эмулятора.
- Декомпилятор apk файлов - JADX (https://github.com/skylot/jadx)
- Frida - https://frida.re/ - это набор инструментов для разработчиков, реверс-инженеров и исследователей безопасности.
- Скачиватель apk файлов (входить через впн, если вы из ру) - https://apk.support/apk-downloader
1. Устанавливаем последнюю версию python - https://www.python.org/downloads/
Обязательно ставим галочку на “add to path” в установщике:
2. Открываем консоль windows и пишем в ней «pip install frida-tools»
По последней строчке видим, что всё успешно установилось.
3. По такому же принципу устанавливаем objection, пишем в консоли команду «pip install objection»
4. Далее скачиваем Android SDK Platform Tools - https://dl.google.com/android/repository/platform-tools-latest-windows.zip и распаковываем в удобной для нас папке.
В окне папки, где мы распаковали наш архим, пишем «cmd» и нажимаем enter, должна открыться консоль с путём нашей папки:
Устройство на android должно быть с рутом (root). В настройках разработчика должен быть включен «USB Debugging». Название может отличаться на разных телефонах, о вашем устройстве лучше почитать на 4pda.
Подключаем телефон по usb к пк. В консоли пишем «adb devices», на телефоне может появится уведомление о разрешении доступа, принимаем его. Наш девайс должен появится в консоли:
Далее переходим на https://github.com/frida/frida/releases и скачиваем frida-server для android:
Информацию о том, какой именно файл нужно скачать, можно понять, погуглив конфигурацию вашего устройства.
Распаковываем архив (формата .xz) в нашу папку, куда мы положили Android SDK Platform Tools, и переименовываем распакованный файл в “frida-server” (для удобства, ибо изначально там файл с номером версии).
Далее в уже открытой консоли пишем три команды по очереди:
Видим, что файл успешно передался на телефон.
И далее запускаем сервер фриды:
При этом никаких сообщений быть не должно, т.е. состояние как на скриншоте означает что сервер Фриды запущен.
Всё, данное окно не трогаем.
Примечание. На моём устройстве, для запуска сервера фриды, в начале нужно прописать «adb shell "su -c setenforce 0"». Бывают ещё редкие ошибки, но 99% их решений гуглится.
Если никаких ошибок в консоли нет, то, скорей всего, всё нормально работает.
Откроем новое окно консоли (Именно новое!) и проверим, написав команду frida-ps -Uai:
Как мы видим, нам в ответе показаны все установленные приложения на устройстве, то есть всё работает.
Примечание. Если вы закроете окно консоли, в котором вы запустили сервер фриды, можно убить процесс через данные команды:
Обязательно ставим галочку на “add to path” в установщике:
2. Открываем консоль windows и пишем в ней «pip install frida-tools»
По последней строчке видим, что всё успешно установилось.
3. По такому же принципу устанавливаем objection, пишем в консоли команду «pip install objection»
4. Далее скачиваем Android SDK Platform Tools - https://dl.google.com/android/repository/platform-tools-latest-windows.zip и распаковываем в удобной для нас папке.
В окне папки, где мы распаковали наш архим, пишем «cmd» и нажимаем enter, должна открыться консоль с путём нашей папки:
Устройство на android должно быть с рутом (root). В настройках разработчика должен быть включен «USB Debugging». Название может отличаться на разных телефонах, о вашем устройстве лучше почитать на 4pda.
Подключаем телефон по usb к пк. В консоли пишем «adb devices», на телефоне может появится уведомление о разрешении доступа, принимаем его. Наш девайс должен появится в консоли:
Далее переходим на https://github.com/frida/frida/releases и скачиваем frida-server для android:
Информацию о том, какой именно файл нужно скачать, можно понять, погуглив конфигурацию вашего устройства.
Распаковываем архив (формата .xz) в нашу папку, куда мы положили Android SDK Platform Tools, и переименовываем распакованный файл в “frida-server” (для удобства, ибо изначально там файл с номером версии).
Далее в уже открытой консоли пишем три команды по очереди:
- adb root (бывает нужна, в моём случае – нет)
- adb push frida-server /data/local/tmp/
- adb shell "chmod 755 /data/local/tmp/frida-server"
Видим, что файл успешно передался на телефон.
И далее запускаем сервер фриды:
При этом никаких сообщений быть не должно, т.е. состояние как на скриншоте означает что сервер Фриды запущен.
Всё, данное окно не трогаем.
Примечание. На моём устройстве, для запуска сервера фриды, в начале нужно прописать «adb shell "su -c setenforce 0"». Бывают ещё редкие ошибки, но 99% их решений гуглится.
Если никаких ошибок в консоли нет, то, скорей всего, всё нормально работает.
Откроем новое окно консоли (Именно новое!) и проверим, написав команду frida-ps -Uai:
Как мы видим, нам в ответе показаны все установленные приложения на устройстве, то есть всё работает.
Примечание. Если вы закроете окно консоли, в котором вы запустили сервер фриды, можно убить процесс через данные команды:
- 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 на устройстве проксю, которая показана вот в этом пункте меню:
3. Проходим по ссылке в браузере устройства на chls.pro/ssl и ставим сертификат.
4. Также сразу отключаем windows прокси (находится в разделе proxy – windows proxy) и включаем обе кнопки в главном меню:
Первая отвечает за запись трафика, вторая – за ssl проксю.
Что касается установки и снятия прокси сниффера на устройстве, когда мне нужно снять трафик с приложения, я использую команды
Можно использовать и BurpSuite, и Fiddler, и другие снифферы, в данном случае я не вижу никакой разницы.
1. В случае с Charles proxy качаем триал версию с их сайта https://www.charlesproxy.com/download/
2. После запуска сниффера на пк, ставим в настройках wi-fi на устройстве проксю, которая показана вот в этом пункте меню:
3. Проходим по ссылке в браузере устройства на chls.pro/ssl и ставим сертификат.
4. Также сразу отключаем windows прокси (находится в разделе proxy – windows proxy) и включаем обе кнопки в главном меню:
Первая отвечает за запись трафика, вторая – за ssl проксю.
Что касается установки и снятия прокси сниффера на устройстве, когда мне нужно снять трафик с приложения, я использую команды
- adb shell settings put global http_proxy proxy:port– поставить прокси
- adb shell settings put global http_proxy :0 – снять прокси
Переходим на сайт https://apk.support/apk-downloader, копируем ссылку нашего приложения из Google Play и нажимаем кнопку Analyze, далее снизу будут сборки под конкретный регион, я выбрал EU:
Очень важно, чтобы на устройстве и в декомпиляторе оказались одинаковые файлы.
То есть надо скачать apk файл с сайта выше, закинуть его на наше устройство, и также оставить на пк, так как мы в дальнейшем будем его разбирать. Ибо в разных версиях приложения (Имеется в виду не именно номер версии, а отдельные сборки для us/eu) могут содержаться разные классы внутри приложения, что очень затруднит нас
Очень важно, чтобы на устройстве и в декомпиляторе оказались одинаковые файлы.
То есть надо скачать apk файл с сайта выше, закинуть его на наше устройство, и также оставить на пк, так как мы в дальнейшем будем его разбирать. Ибо в разных версиях приложения (Имеется в виду не именно номер версии, а отдельные сборки для us/eu) могут содержаться разные классы внутри приложения, что очень затруднит нас
Запускаем приложение
Открываем новую командную строку и пишем «frida-ps -Uai»:
Здесь указаны все установленные приложения, а точнее их 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 появился, значит всё работает:
Работа с декомпилятором JADX
Мы будем смотреть код приложения (Нужно же как-то понять, как генерируется наш хэш?) с помощью JADX.
Скачиваем последнюю версию JADX - https://github.com/skylot/jadx/releases и распаковываем его в удобное место.
Открываем наш заранее скачанный apk файл Pikabu:
Ждём прогрузки. У нас открылся проект с декомпилированным кодом:
Поиск нужного фрагмента кода
В нашем случае нам нужно понять, в каком именно месте генерируется данный хэш, проанализировать код, посмотреть входные параметры и сделать его реализацию.
В JADX есть опция поиска:
Можно сразу поставить галочку «Keep open», для удобства:
Как именно искать нужный нам фрагмент кода, где может генерироваться наш хэш?
Примечание: поиск подобного кода во многих случаях значительно отличается от того, который показан в этой статье.
Для начала, попробуем вписать в поиск «"hash"» (именно с кавычками), то есть то имя, которое мы нашли в данных запроса.
Пробуем:
Для того, чтобы попасть в нужный фрагмент кода, нужно сделать даблклик мышкой по одному из вариантов.
Посмотрим на все 5 вариантов:
В общем, мне ничего не приглянулось, нужно искать дальше.
Примечание 1: сразу хочу сказать, что всё-таки прошлые функции скорей всего можно "покрутить", т.е. посмотреть какие именно аргументы они принимают и возвращают, но в случае с нашим приложением всё немного проще, так что дальше я покажу поиск нужного нам кода по-другому.
Примечание 2. Чтобы попасть в нужную нам функцию в JADX, нужно зажать ctrl и кликнуть на неё.
К примеру, здесь есть какая-то функция «d», мы можем посмотреть, что она из себя представляет, кликнув на её название (то есть буковку «d») с зажатым ctrl.
Но вот во втором варианте в поиске есть что-то с названием «CE_SETTINGS_HASH», и ещё там есть “hash”:
Отсюда, по идее, можно продолжить поиск. А именно, по «CE_SETTINGS_HASH»:
Здесь мне сразу приглянулся данный фрагмент кода, потому что он возвращает какую-то функцию (i), и в её параметрах есть наше ключевое слово (CE_SETTINGS_HASH), и ещё какая-то функция "d", и с ней ещё 4 параметра, возможно, это то что нам нужно. Да и код находится в пакете "ru.pikabu.android.server.s":
Далее можно (нужно) осмотреть найденный фрагмент кода, а именно посмотреть данные функции:
Функция i:
Функция d:
Я сразу подумал, что здесь ничего не генерируется, ибо по беглому осмотру мне показалось, что здесь идёт какая-то работа с массивами. Попробуем тогда что-то другое.
Что делать дальше? Как вариант, можно осмотреть всю область текущего файла, где мы нашли прошлые функции. Ибо частенько рядом с такими функциями есть то, что нам нужно, либо то, что укажет нам, как именно дальше надо искать.
К примеру, во время просмотра мне приглянулся вот такой фрагмент кода, который был чуть выше наших предыдущих функций:
Видно, что в нём при возврате, есть сразу две функции, ii.p.a и ii.p.b, последняя принимает на вход строку, видимо.
Посмотрим на код самих этих функций, для начала ii.p.b:
MD5 – это алгоритм хэширования. То есть, скорей всего, мы очень близко.
Итак, скорей всего мы нашли нужную функцию, что дальше? Нужно как-то проверить нашу находку.
Наша функция что-то получает на входе, и нам нужно понять, что именно.
В данном случае, анализируя код, мы видим, что функция на вход получает строку, это видно по типу переменной, «String»:
Теперь, надо как-то понять, какие именно аргументы функция получает на входе.
Нам нужно будет сделать хук через 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:
foy.b.overload('java.lang.String') – в данном случае b – это как раз наша функция, а 'java.lang.String' – это тип аргумента, который в неё передаётся, в нашем случае это строка, как сказано ранее.
Это один из его вариантов хука функции для фриды, в интернете есть и другие реализации. В данном случае мы привязываемся к нужному нам классу в приложении, и далее к функции. При вызове последней нам в лог будут приходить аргументы, которые передаются в неё.
Теперь нам надо поместить наш код хука в файл и внедрить его в приложение. Я добавил его в наш файл script.js. То есть теперь в нашем файле одновременно два скрипта, для обхода SSL Pinning, и для хука функции:
Закрываем прошлое окно консоли, где у нас был включен ssl unpinning, и запускаем наш обновлённый скрипт той же командой:
frida -U -l script.js -f ru.pikabu.android
Как видим, оба скрипта работают одновременно. Не очень удобно, конечно, учитывая, что они вместе пишут лог, но при раздельном запуске (т.е. в двух отдельных окнах командной строки по скрипту), у меня крашилось приложение, в случае с Pikabu.
Помимо работы первого нашего скрипты (для снятия ssl pinning), у нас в логе появляются новые строки, именно их на входе получает хукнутая нами функция.
Сейчас попробуем зарегистрировать аккаунт в приложении. Смотрим наш запрос в сниффере:
Теперь смотрим на консоль, где работают наши скрипты:
Те строки, где присутствует "user.name.check" – очевидно, что это проверка логина (существует он на пикабу, или нет).
А вот самая последняя строка – это как раз то, что нам нужно, судя по "user.register" (Оно совпадает с url регистрации из сниффера). Мы уже понимаем, что на вход в функцию при регистрации попадает вот такая строка «kmq4!2cPl)peZ,user.register,1671570215943,1,123123123,hjfjgjfjfjh,[email protected]»
Можно разобрать её:
- kmq4!2cPl)peZ – это что-то похожее на соль. Соль в хэше - это дополнительная случайная строка, которая добавляется к основной строке перед хэшированием.
- user.register - часть ссылки для регистрации, где оригинал - «https://api.pikabu.ru/v1/user.register»
- 1671570215943 – unix timestamp
- 1 – я не знаю что это такое, да и плевать в данном случае, ибо, судя по логу, оно статичное
- 123123cfcfZ – наш пароль
- Hjfjgjfjfjh - логин
- [email protected] – наша почта
Собираем код для генерации хэша
Мы успешно получили входные аргументы нашей функции. Также не забываем о том, что в генерации «hash» участвуют две функции:
Первую (ii.p.b) мы уже разобрали. Посмотрим на вторую (ii.p.a):
Здесь происходит преобразование в Base64, если судить по надписи "Base64".
У нас уже есть пример хэша и данных, которые в него попадают. Нужно попробовать собрать его и сравнить со сниффером, то у нас получилось, или нет.
Получается такая схема: Входные данные (То есть наша полученная строка) -> MD5 -> Base64
Нужно проверить, правильно ли мы всё поняли.
Нашу полученную строку "kmq4!2cPl)peZ,user.register,1671570215943,1,123123cfcfZ,hjfjgjfjfjh,[email protected]" преобразуем сначала в md5:
В директивах using пропишем "using System.Security.Cryptography;"
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();
Теперь преобразуем её в base64:
C#:
project.Variables["result2"].Value = Convert.ToBase64String(Encoding.UTF8.GetBytes(project.Variables["result"].Value));
Теперь сравниваем полученные строки.
Строка из сниффера:
Наша строка:
Почти совпадает. Но что такое "\u003d"? Погуглив, стало понятно, что это равно "=", то есть тоже самое, что и в нашем сгенерированном хэше:
То есть, мы всё сделали верно.
Теперь надо попробовать отправить запрос на регистрацию с изменёнными данными и сгенерированным нами хэшем.
В запросе изменим почту на "[email protected]", логин на "testzenno123", а пароль сделаем "123123zenno". Итого у нас получается входная строка хэша вида "kmq4!2cPl)peZ,user.register,1671608516940,1,123123zenno,testzenno123,[email protected]".
Прогоним её через md5 и base64:
Подставим все данные, включая новый хэш, в запрос и отправим его:
Как видим, хэш прошёл и мы получили id регистрации.
То есть, дело сделано, мы смогли реализовать один из самых простых хэшей в мобильных приложениях, дальше уже можно делать регистрацию (Но статья совсем не об этом).
- Тема статьи
- Нестандартные хаки
- Номер конкурса статей
- Восемнадцатый конкурс статей
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование: