Writeup: "Android UnCrackable L1" (mas.owasp.org)

  • Название: Android UnCrackable L1
  • Категория: reverse (android)
  • Платформа:
Примечание от автора:
A secret string is hidden somewhere in this app. Find a way to extract it.

Сегодняшний райтап, как и, возможно, несколько последующих, будут посвящены небольшим андроид-крякмисам от OWASP. Сегодня будем разбирать самый лёгкий - в качестве введения, так сказать.

Скачиваем apk, устанавливаем его (можно на эмулятор), запускаем:

1721820297386.png


Опа! С порога нас встречают детектом рута на устройстве (я запустил на ручёном смартфоне). Рут я ставил через magisk, а в нём есть один интересный плагин - DenyList, тот позволяет скрыть наличие рута от выбранных приложений. Вдаваться в подробности, как он работает, я особо не буду - лишь в конце статьи украду у Вас пару минут, да и в сети полно материала, пытливый читатель найдёт. Включим наш крякмис в списки DenyList и попробуем запустить приложение снова:

1721820708050.png


Получилось! Теперь можно полноценно потыкать наше приложение, хотя тыкать тут особо нечего: лишь поле для ввода, кнопка Verify и благодарность создателю. По традиции попытаем удачи:

1721820815486.png


Штош, ожидаемо, не получилось. Теперь уже займёмся делом - закинем наш apk в JADX - мощную тулзу для декомпила dex в Java, считайте, декомпилятор IDA для андроида.

1721821021585.png


Теперь нам доступны несколько файлов, каждый со своими классами и функциями. Заглянем, для начала, в MainActivity:

1721821104513.png


Благо, код вполне читаемый, и даже для не-джависта вполне понятный. Сразу можно заметить наше первое препятствие (к нему я ещё вернусь в конце статьи):

1721821214610.png


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

1721821291227.png


А вот и то, что нам нужно: условие проверки нашего ввода. Всё держится на возвращаемом значении функции a.a(), в которую передаётся наш текст - давайте посмотрим, что там такого интересного:

1721821431653.png


Тут нужно ненадолго остановиться, мы наткнулись на кое-что интересное. Давайте анализировать функцию с конца: её возвращаемое значение - результат работы equals() - аналога функции strcmp, проверяющей, одинаковы ли строки. Заметьте, наш аргумент str нигде больше в функции не мелькает, а значит, интерес представляет второй подопытный - bArr. Последний формируется через функцию sg.vantagepoint.a.a.a(), где первым аргументом идёт результат соседней функции b() с какой-то строкой, а второй - набор байт, декодированный из base64. С последним, думаю, всё понятно, а функция b(), как видно из скриншота, превращает hex-строку в набор байт, ничего другого. После bArr можно заметить строку с упоминанием AES - наводит на некоторые мысли, не правда ли? Не будем гадать - заглянем внутрь sg.vantagepoint.a.a.a():

1721822066803.png


Перед вами самый сок - функция, расшифровывающая AES-строку. В качестве первого аргумента (bArr) выступает секретный ключ, а в качестве второго (bArr2) - сам зашифрованный набор байт. И раз и то, и то у нас под рукой имеется, давайте это дело расшифруем сами - с помощью прелестной тулзы :

1721823910023.png


Получили вполне читабельную строку - давайте попробуем её ввести в приложение:

1721824036031.jpeg


Получилось, мы зарешали крякмис! Было довольно просто, но это только начало - дальше будет сложнее (если я сам их зарешаю и выложу райтапы XD). Да, возвращаясь к коду выше, хочу обратить ваше внимание на, как мне показалось, один интересный момент:

1721824378783.png


Это проверка на наличие рута на устройстве и текущего дебаггинга приложения. Последняя проверка проверяет текущие флаги запуска приложения:

1721824512547.png


А вот в проверке на наличие рута фигурируют сразу 3 функции:

1721824547835.png


Первая функция тривиальная - она просто проверяет наличие бинарника su по пути PATH. Третья функция является более комплексной версией первой - несколько распространённых путей и вариантов переименованного su и связанных с ним файлов. Вторая же функция работает интереснее: она проверяет флаги текущего билда системы (android.os.Build.TAGS) и ищет флаг подписи test-keys.
Дело в том, что при компиляции ядра системы, последнее подписывается верифицированным ключом от проверенного разработчика - release-keys. Наличие же test-keys означает, что оно было подписано пользовательским ключом, сгенерированным сторонним девелопером. А, как вы уже можете догадаться, рутирование системы - не тот процесс, который предполагается подписать релизными ключами.

Тем не менее, все эти три функции мы через DenyList обошли, а значит - технологии и методы защиты и антизащиты не стоят на месте. Конечно, это лишь одни из примитивных методов проверки на рута - есть более комплексные, которые просто через DenyList не обойдёшь, но это не к сегодняшнему райтапу.

Надеюсь, эта небольшая статья поможет Вам в нашей нелёгкой стезе.

Удачного ревёрса!

made 4 @rev_with_da_boys
 
  • Нравится
Реакции: nsk, Edmon Dantes и GoBL1n
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!