- Немного истории
- Как был получен root на HTC Dream G1
- Способы получения Root-прав
- Нелегальные root-права и magisk
- Стоит ли делать рут
- Как работают root-права?
- Так стоит ли «рутовать» Android?
- Опасности root-прав
- И пришел root
- Командуем
- Причина #1. Bloatware
- Как устроено хранилище
- SELinux
- Как устроено шифрование хранилища
- Внедряемся в систему с установленными root-правами
- Зачем нужны root-права?
- Причина #4. Реклама
- Несколько примеров
- Преимущества и недостатки рутинга
- Причина #7. Двойная загрузка
- Причина #8. Полная отвязка от Google и других сервисов
Немного истории
Обладатели ранних версий Android обычно получали права root с использованием какой-либо уязвимости в системе безопасности Android или одного из системных приложений, установленных производителем. Использование уязвимостей позволяло приложению «вырваться» из песочницы и получить права системного процесса через эскалацию привилегий.
Чтобы не повторять процесс каждый раз и чтобы предоставить возможность и другим приложениям использовать права суперпользователя, в системный раздел помещали файл su (как правило, в каталоге /system/xbin/) и приложение для обработки запросов прав root (в /system/app/). Чтобы получить права root, приложение запускало su, в этот момент срабатывал менеджер обработки запросов и запрашивал у пользователя подтверждение.
Такая схема прекрасно работала во всех версиях Android вплоть до пятой, а добытый с ее помощью root-доступ чаще всего не мешал получать обновления прошивок и даже иногда сохранялся после таких обновлений. Популярностью пользовались многочисленные приложения, эксплуатировавшие одну или несколько уязвимостей (например, Towelroot). Со временем большую аудиторию набрали китайские приложения KingRoot и Kingo Root, включавшие в себя большие коллекции эксплоитов, которые скачивались непосредственно в момент запуска с китайских серверов. В случае успешной эскалации привилегий эти приложения прописывали в системный раздел много интересного; удалить их можно было либо вместе с root-доступом, либо с помощью специального «чистильщика», сделанного разработчиком SuperSU Chainfire.
В Android 5.0 была введена новая система обновлений. Теперь в файле OTA изменения прописывались не на файловом, а на блочном уровне; чтобы не повредить файловую систему, инсталлятор обновления подсчитывал контрольную сумму системного раздела. Естественно, записанный в раздел /system файл su изменял контрольную сумму раздела, и обновление не устанавливалось (а в тех случаях, когда оно все-таки ставилось, был высокий шанс получить на выходе «кирпич»).
Шестая версия Android принесла и обновленную систему безопасности, которая (временно) сделала невозможным получение прав суперпользователя простой записью приложения в системный раздел. В результате появился обходной путь — так называемый systemless root, внедряющий su в ramdisk вместо модификации системного раздела. На некоторых устройствах с «бессистемным» root-доступом даже получалось устанавливать OTA-обновления; впрочем, гарантии тут никакой.
Как был получен root на HTC Dream G1
Впервые root был получен на первом в мире Android-устройстве HTC Dream G1, выпущенном в далеком 2008 году. На устройстве был запущен сервис Telnet с правами root и без аутентификации. Для получения временного root-доступа было достаточно подключиться к смартфону по Telnet, для постоянного — залить в системный раздел бинарный файл su.
Способы получения Root-прав
Для получения root прав используются различные кастомные рекавери, такие как TWRP, OrangeFox Recovery или CWM, после чего требуется прошить zip-файл SuperSu или Magisk. Также для Magisk имеется способ использующий изменение boot.img в системе, используя его замену с помощью ADB.
На данный момент существует два варианта получения прав root:
Эти программы не используют эксплоиты для получения root прав., а также не используют ПК в большинстве случаев.
Нелегальные root-права и magisk
Я назвал предыдущий подход к получению root-прав «легальным», потому что всё необходимое для этого было намеренно заложено в систему на этапе сборки. Совершенно иной подход использует инструмент для получения root-прав magisk, ставший, де-факто, стандартным инструментом для этих целей в сообществе любителей android. Magisk устанавливается на любые устройства, на любые сборки, на любые версии android, и не только на отладочные варианты сборки, но и на релизные, и даже на те устройства, на которых применяются дополнительные защиты от несанкционированного получения root-прав. Magisk по полной эксплуатирует разблокированный загрузчик и, по сути, совершает настоящий изощрённый взлом за что и будем его называть его «нелегальным». Для нас наиболее важно то, что magisk, по сути, делает всё тоже что хотим сейчас сделать мы. Он закрепляется в системе также, как хотим закрепиться мы, а значит, похоже, что нам с ним по пути.
Для начала постараемся выяснить как magisk получает root-права в рантайме. На устройстве выполняем:
Я сократил вывод команды ps только до тех значений, которые нас интересуют.
Во-первых, мы видим что magisk имеет специальный контекст для своих процессов — u:r:magisk:s0. Наша оболочка с root-правами имеет терминал pts/1 и запущена с этим контекстом. Это явно не встроенный в систему контекст, а значит magisk смог его отредактировать и внедрить дополнительные правила перед запуском процесса init. Поскольку, наши root-права работают, и мы действительно можем делать в системе всё что угодно, контекст u:r:magisk:s0 должен иметь как минимум все те же разрешения, которые прописаны для u:r:su:s0, а может и больше.
Во-вторых, magisk имеет свой демон запущенный в системе – magiskd, он породил наш процесс с рутовым шеллом, а значит именно через него magisk и даёт другим процессам доступ с оболочке с root-правами, этот демон (PID 658) порождён процессом init (PPID 1), т.е. запущен как системный сервис. Демон также работает в контексте u:r:magisk:s0.
Мы подключились по adb и получили шелл на устройстве, терминал pts/0. Видно что процесс sh имеет контекст u:r:shell:s0, PID 5473 и PPID 956 который равен значению PID adbd, а сам adbd уже был порождён процессом init.
Мы вызываем исполняемый файл su и видим что его контекст – u:r:magisk_client:s0, следовательно magisk использует отдельный контекст для того, чтобы знать какие именно исполняемые файлы могут запрашивать доступ к root-правам. Исполняемый файл провоцирует открытие окна подтверждения доступа к root-правам для обычного shell, оно находится в пакете приложения MagiskManager — com.topjohnwu.magisk, получив результатат magiskd (PID 658) породил нам нашу оболочку sh с новым терминалом pts/1 (PID 5708, PPID 658), от которой мы отнаследовали и пользователя root (uid=0), и всемогущий контекст u:r:magisk:s0.
Для нас интересно вот что: если init запускается со своим ограниченным со всех сторон контекстом u:r:init:s0 из которого разрешены transition’ы только в прописанные в *.te файлах контексты для системных служб, а демон маджиска имеет контекст u:r:magisk:s0, значит magisk смог внедрить правило разрешающее прямой transition из u:r:init:s0 в u:r:magisk:s0. Это значит что и мы можем использовать контекст u:r:magisk:s0 в своём сервисе!
Стоит ли делать рут
Делать рут довольно опасно, да и рядовому пользователю абсолютно незачем
Следующий абзац будет полезен неопытным пользователям, которые беспечно решили, что им обязательно нужны root-права.
Обратной стороной любых прав, в том числе и root, является ответственность. Вы должны понимать, что, получая права супер-пользователя, вы берете на себя ответственность за все те неприятности, которые могут случится с вами и вашим устройством. А неприятностей это может доставить гораздо больше, нежели пользы, особенно, если вы плохо понимаете, как всё устроено.
Приложения, требующие рут-прав, требуют особых навыков взаимодействия с таким софтом. Естественно, им обладают не все, и разработчики включает в абсолютно безвредные с виду приложения вредоносный код и собрать ваши платёжные данные. Про приложения, которые оформляют платные подписки, я вообще молчу.
Как сделать звук в Яндекс.Станции лучше
Но хуже всего, что ведоносное ПО, имеющее доступ к рут-правам, с такими возможностями в теории может вмешиваться даже в работу антивирусных приложений, которые сами такими правами не обладают. Ну да, ладно, не буду пугать вас вирусами, ибо самый страшный вирус находится на расстоянии 20-30 см от девайса и чаще всего держит его в руке. Просто помните, что неопытность, незнание и нежелание разораться, пользователя может нанести больше вреда, чем сам рут.
С помощью root можно угробить телефон и превратить его в кирпич ещё в процессе получения прав супер-пользователя. А вредоносный софт попадает на устройство чаще всего по вине самого пользователя с взломанными игрушками или приложениями. Имея root-права, вредоносный софт способен творить страшные вещи. Поэтому прежде, чем получать их, тщательно взвесьте все плюсы и минусы и хорошенько подумайте, а надо ли оно вам?
Как работают root-права?
Когда то, для установки root-прав достаточно было перемонтировать раздел system в режим чтения-записи и скопировать туда исполняемый файл su. Затем появилась необходимость думать также и о политиках SELinux, и об AVB. Сегодня для получения root-прав можно выделить два основных подхода, которые можно условно назвать «легальным» и «нелегальным».
Так стоит ли «рутовать» Android?
Использовать систему с правами суперпользователя — это как водить многотонный грузовик. Если вы действительно умеет это делать — то почему бы и нет. Но если не умеете — то сначала стоит получить необходимые знания и навыки. В общем, если вопрос «Как пропатчить KDE2 под FreeBSD?» у вас ассоциируется исключительно с аниме, то «рутовать» Android мы вам не советуем.
Еще несколько советов:
Опасности root-прав
Не буду утверждать, что root-права это безопасно — любой необкатанный magisk модуль может привести систему в нерабочее состояние, при неумелом редактировании системных файлов система также придет в негодность, а функционал программ, запрашивающих root не всегда прозрачен. Не давайте root права приложениям, которым, по вашему мнению, они не нужны! Периодически такие права запрашивают Яндекс Карты, статистики ради или для чего-то еще — неизвестно, но проверять не хочется.
Говорить о том, что наличие root как-то сильно ослабляет защиту системы тоже не буду — доступ вполне себе контролируемый, и если вы будете соблюдать элементарную цифровую гигену, никаких проблем не будет.
Самое опасное, наверное — потеря гарантии производителя, что логично.
И пришел root
Как я уже сказал, функциональность root-приложений построена на том, чтобы запускать команды от имени пользователя root, то есть суперпользователя. В UNIX-системах (а ею Android является на самом низком уровне) эта операция выполняется с помощью команды su. По умолчанию она просто открывает шелл с правами root, но с помощью флага -c правами root можно наделить любую команду. Например, чтобы выполнить команду id, с правами root достаточно такой строки:
runCommand(«su -c id»);
Команда id, кстати говоря, возвращает идентификатор текущего пользователя (0 = root), так что сразу можно проверить, как все работает. Однако при таком методе запуска возникают проблемы с парсингом. Если ты укажешь дополнительные аргументы (например, su -c uname -a), команда просто не отработает. Обойти ограничение можно, передав ее как массив строк. Для удобства немного модифицируем код метода runCommand, заменив в нем первую строку:
Все, теперь с его помощью можно запускать хоть несколько команд одновременно, все с правами root:
runSuCommand(«id; uname -a; cat /proc/cpuinfo»);
В сущности, это все, и можно переходить к примерам, но есть еще один нюанс: смартфон может быть не рутован. Этот момент необходимо обязательно учитывать и проверять наличие прав root. Наиболее простой и эффективный способ проверки — посмотреть, есть ли бинарник su в системе. Обычно он располагается в каталоге /system/bin/ или /system/xbin/ (в большинстве случаев), поэтому просто напишем такую функцию:
Объяснять тут особо нечего, есть su — true, нет — false.
И еще один, последний нюанс. Чтобы получить доступ на редактирование (удаление/перемещение) файлов в системном разделе (/system), необходимо перемонтировать его в режиме чтение/запись:
runSuCommand(«mount -o remount,rw /system»);
После этого можно спокойно работать с файлами системного раздела, если, конечно, на устройстве не используется блокировка доступа к /system (S-ON). По-хорошему, после окончания работы с файлами рекомендуется снова смонтировать /system с правами «только чтение»:
runSuCommand(«mount -o remount,ro /system»);
Однако это, скорее, правило хорошего тона, на работу системы смонтированный на запись раздел /system никак не влияет.
Стандартное окно запроса прав root в CyanogenMod
Командуем
Запуск внешних команд в Android выполняется точно так же, как и в Java, а именно с помощью такой строки:
Правда, в коде придется обрамить ее try/catch:
Метод exec() запускает шелл и команду в нем в отдельном потоке. После завершения команды поток дестроится. Все просто и понятно, но вот толку нам от этого мало — вывода команды мы все равно не видим. Чтобы решить эту проблему, мы должны прочитать стандартный выходной поток, для чего понадобится примерно такая функция:
Теперь у нас есть возможность запускать команды и видеть результат их работы, но что это нам дает? Ну, как вариант — мы можем прочитать инфу о процессоре. Создаем простую формочку с одной кнопкой сверху и TextView ниже нее. Далее в теле метода onCreate пишем такой код:
Собственный CPU-Z в две строки
Все, результат, как говорится, налицо. Вместо команды cat /proc/cpuinfo можно использовать и что-то поэкзотичнее, например uname -a, которая выводит версию ядра Linux, или cat /system/build.prop для просмотра файла системных настроек. Однако так мы далеко не уедем, система не даст нам сделать что-то серьезнее, чем чтение некоторых файлов или запуск простых команд. Хардкор начнется только при наличии прав суперпользователя.
Причина #1. Bloatware
Практически все устройства на базе Android поставляются с огромным количеством предустановленных приложений. Так, в прошивках HTC в каталогах /system/app и /system/priv-app находится около 400 пакетов, и это не только языковые пакеты и компоненты сервисов самой компании, но и приложения Google, которая требует, чтобы смартфон с предустановленным Google Play Market также содержал и несколько десятков других приложений компании (Gmail, Google Drive, Google Keep и другие).
При достаточном объеме встроенной памяти это может показаться не слишком серьезной проблемой, однако многие из этих приложений не просто установлены и «спокойно лежат» в своих каталогах, а стартуют при загрузке системы, могут будить устройство с помощью AlarmManager (служба, собирающая статистику, например) и просыпаться в ответ на системные события (ты установил сторонний диалер, а встроенный все равно просыпается при звонке). Так что прощай, заряд батареи и свободная оперативка.
Имея права root, удалить «блоат» очень просто. Для этого есть множество приложений, которые легко найти в маркете по запросу «system app remover». Придется, конечно, разобраться, какие приложения можно удалять, а какие лучше оставить, но эту информацию легко найти на форумах, в том числе русскоязычных.
Первый попавшийся System app remover
Как устроено хранилище
Если мы посмотрим на структуру разделов на хранилище смартфона, то увидим что их на устройстве довольно много.
Большинство из них небольшие, и содержат, например, логотип производителя девайса, который отображается сразу после подачи питания на плату устройства. Есть раздел содержащий прошивку, работающую на baseband процессоре и отвечающую за мобильную связь, звонки и интернет по стандартам 2G, 3G, LTE и т.д. Есть разделы содержащие BLOBы необходимые для работы с некоторыми устройствами. Нас будет интересовать всего несколько разделов, содержание которых монтируется в файловую систему и напрямую используется во время работы ОС:
Данные приложений, «internal storage», находятся по пути /data/data. В этой директории сложены директории-песочницы отдельных приложений, соответствующие их полным именам пакетов. Например:
drwx—— 8 u0_a69 u0_a69 4096 2021-01-29 13:31 com.google.android.youtube
Общее хранилище, «external storage», находится по пути /data/media/0, внешние SD-карты соответственно будут называться /data/media/1. Во время работы оно линкуется в /storage.
SELinux
Безопасность в android устроена сложнее чем хотелось бы злоумышленникам и представляет из себя многослойную систему. Unix DAC (discretionary access control), привычная нам система пользователей и назначения прав на файлы типа rwxrwxrwx является лишь частью мер по предотвращению злоупотребления операционной системой и устройством. Помимо неё есть ещё MAC (mandatory access control), в android это SELinux (Security Enhanced Linux). Суть MAC в возможности намного более гибко управлять доступом к различным ресурсам чем DAC, в том числе описывая для этого свои уникальные сущности и правила.
Уровни контроля доступа в android
Отсюда следует несколько неочевидный ранее вывод – на android root-права в привычном для других дистрибутивов linux понимании, т.е. когда uid пользователя в системе равен 0, вовсе не означают что мы можем делать всё что угодно. Несмотря на то, что процесс init запущен с uid=0, он не может запустить сторонний сервис. Дело в том что SELinux не оперирует понятиями системных пользователей и групп, и если какое-то действие не было явно разрешено, то он его запретит и ему безразлично пытается ли его совершить непривилегированный пользователь или root. Он работает «выше» DAC и может запретить любое действие, которое DAC разрешил.
Вот отличный пример в android с самим файлом, содержащим политики SELinux:
$ ls -laZ /sys/fs/selinux/policy
-r—r—r— 1 root root u:object_r:selinuxfs:s0 0 1970-01-01 03:00 /sys/fs/selinux/policy
$ cat /sys/fs/selinux/policy
cat: /sys/fs/selinux/policy: Permission denied
На нём стоит доступ для чтения для любых пользователей, но при попытке прочитать его мы получим Permission denied, потому что ни для процессов с контекстом u:r:shell:s0, ни для процессов с контекстом u:r:untrustedapp:s0 нет разрешения на чтение файлов u:objectr:selinuxfs:s0.
SELinux оперирует понятиями контекстов, которые присваиваются файлам и процессам, и правил взаимодействия между объектами принадлежащим разным контекстам. Наборы этих правил объединяются в политики. Они описываются в файлах *.te в исходниках android, можно посмотреть примеры вот тут. Политики собираются на этапе сборки системы и, теоретически, не могут изменяться во время её работы, они компилируются в специальный бинарный формат, который уже использует система.
Контекст SELinux на процессах и файлах можно посмотреть, добавив к выполняемой команде флаг -Z. Например, для просмотра контекстов на файлах в текущей папке можно вызвать команду ls -laZ, а на процессах, соответсвенно, ps -efZ.
Как было упомянуто выше в секции про процесс загрузки системы, первое действие которое совершает процесс init – загружает и применяет политики SELinux, а одна из первых применяемых политик заключается в том что процессу с контекстом u:r:init:s0 запрещается делать transition в другой контекст. Политики SELinux специально строятся по принципу «запрещено всё что не разрешено», и создатели операционной системы, разумеется, позаботились о том, чтобы злоумышленник получивший возможность прописать запуск какого-то сервиса в автозапуск не смог это сделать. Контекст процесса init организован таким образом что он может запустить только те системные сервисы, для которых явно прописано разрешение на запуск во время загрузки системы, и после сборки системы это изменить нельзя.
SELinux может работает в трёх режимах:
В нормально работающей системе android версии от 5.0 SELinux всегда будет в режиме enforcing. Если по каким-то причинам он будет переведён в режим permissive, то пользователю ещё до ввода кода разблокировки покажут большое страшное уведомление об этом и о том что его система небезопасна. Мы точно не имеем права переводить SELinux в permissive режим, потому что это выдаст пользователю факт модификации его устройства, и он может предпочесть уничтожить данные.
В каждой версии android, начиная с 5 политики SELinux сильно ужесточаются и всё меньше и меньше всего остаётся разрешённым. Иронично, но начиная с android 8 даже если прошить в системный раздел исполняемый файл su и сделать его системным и принадлежащим root:root, он не сможет работать без специально назначенных ему политик.
Тем не менее инструменты для получения root-прав существуют, и они умеют обходить ограничения MAC, работать на самых свежих версиях android и даже на устройствах, которые помимо них дополнительно имеют отдельные механизмы контроля целостности системы (например устройства Samsung). Так как же тогда работает root в современных реалиях?
Как устроено шифрование хранилища
Для начала разберёмся как устроено шифрование хранилища, потому что это самое труднопреодолимое препятствие для изъятия данных. Шифрование применяется на уровне файловой системы. Существует два основных подхода к организации шифрования:
До первого ввода кода разблокировки данные пользователя всегда зашифрованы, после первого ввода – всегда расшифрованы. Даже когда пользователь в дальнейшем нажимает кнопку питания или система сама уходит в сон, то данные, с точки зрения ОС, больше не переходят в зашифрованное состояние, теперь их защищает только экран блокировки. В android пока не предусмотрен механизм очищения ключей для расшифровки файловой системы из памяти после определённого периода неактивности.
Это значит, что если после того, как устройство было разблокировано хотя бы однажды подключиться к нему, например по adb, то пользовательские данные будут доступны и можно получить к ним доступ даже если экран заблокирован.
Вот так выглядит общее хранилище до первого ввода кода разблокировки:
# ls -la /data/media/0/
total 100
drwxrwx— 13 media_rw media_rw 4096 2021-01-29 10:45 .
drwxrwx— 4 media_rw media_rw 4096 2021-01-29 10:43 ..
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 3aIg6706qnt+JRerXQc,9B
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 5RxSnwRfzXH5JsgykyuneB
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 9QCg2626EAEHNRc,IpjzjC
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 XLrhnulSzxYVPwgkHhs8YC
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:45 ZC6kM5uXi6,coHL+OYgLCB
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 kJJ0DN8Tmhcs7hicwcEZ3A
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 mPaCm6PJHF9,MyimVTRozC
drwxrwxr-x 3 media_rw media_rw 4096 2021-01-29 10:43 qIkgta78EOvsfnjupFXQ+C
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 uAP,C13tjXpxdP8PWVeMRD
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 v33cOjp,wu+hlgBIWnQdjB
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 xxjD9tk7bDh9XZUzoDwMbB
А вот так после:
# ls -la /data/media/0/
total 100
drwxrwx— 13 media_rw media_rw 4096 2021-01-29 10:45 .
drwxrwx— 4 media_rw media_rw 4096 2021-01-29 10:43 ..
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 Alarms
drwxrwxr-x 3 media_rw media_rw 4096 2021-01-29 10:43 Android
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 DCIM
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 Download
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 Movies
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 Music
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 Notifications
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 Pictures
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 Podcasts
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:43 Ringtones
drwxrwxr-x 2 media_rw media_rw 4096 2021-01-29 10:45 bluetooth
На самом деле, шифрование хранилища – самая трудно преодолимая часть нашей задачи по извлечению данных. Обойти шифрование с ключами в аппаратном ТЕЕ никак не представляется возможным, но зато из этой информации следует несколько полезных выводов, а наша задача начинает формироваться в конкретные технические требования.
Это подводит нас к мысли о том, что можно воспользоваться возможностью модифицировать никогда не шифруемую часть системы, внедрить в неё агента, который никак не затронет и не испортит зашифрованные данные, а в последствие даст нам доступ к ней после того как устройство будет возвращено пользователю и он сам первый раз введёт код разблокировки. Поскольку пользователь явно не будет вводить код разблокировки подключив устройство к нашему usb кабелю или находясь в нашей локальной сети, то использование adb нам не подходит и необходимо организовать удалённый доступ в формате reverse-shell.
Внедряемся в систему с установленными root-правами
Внесём небольшое изменение, добавим в описание нашего демона seclabel который определяет какой SELinux контекст должен назначить init для запущенного системного сервиса:
service revshell /system/bin/revshell
disabled
seclabel u:r:magisk:s0
shutdown critical
on property:sys.boot_completed=1
start revshell
Подготовим исполняемый файл для демона и соберём его под arm64.
Я использую именно такой подход для демонстрации работы, потому что так легко понять что сервис работает просто подключившись к logcat и почитав логи. Наш исполняемый файл работает следующим образом: запускается, скидывает в логи приветственное сообщение, далее он ожидает расшифровки хранилища, для этого он полагается на то что внутри директории с приватными хранилищами приложений появится запись содержащая строку «android», которая присутствует в имени пакета многих системных приложений, после этого он сбрасывает в логи запись о том что хранилище расшифровано и запускается reverse-shell, а дальше просто раз в пять секунд сбрасывает в логи сообщение о том что он запущен и работает.
Перезагрузимся в TWRP, смонтируем system и скопируем получившийся исполняемый файл в /system/bin/revshell, а скрипт демона в /system/etc/init/revshell.rc
Перезагружаем устройство и начинаем слушать логи:
Когда система загрузилась, и показался экран ввода кода разблокировки видим в логах следующее:
Отлично, хранилище ещё не расшифровано, но демон успешно запустился и работает, трюк с seclabel u:r:magisk:s0 сработал!
Вводим код разблокировки и видим в логах:
01-31 23:42:27.597 3589 3589 D revshell: FS has been decrypted!
01-31 23:42:27.597 3589 3589 D revshell: Starting reverse shell now
01-31 23:42:32.597 3589 3589 D revshell: tick ! 25 seconds since process started
01-31 23:42:37.598 3589 3589 D revshell: tick ! 30 seconds since process started
01-31 23:42:42.599 3589 3589 D revshell: tick ! 35 seconds since process started
01-31 23:42:47.600 3589 3589 D revshell: tick ! 40 seconds since process started
Посмотрим, через adb запущенные процессы и увидим там наш демон:
Он запущен процессом init, как системный сервис, убить его без root-прав мы не можем:
$ kill -9 3589
/system/bin/sh: kill: 3589: Operation not permitted
А убив его c root-правами, увидим что он тут же был перезапущен системой, потому что именно так система поступает с критическими системными сервисами:
Отлично. Это уже похоже на успех. У нас получилось внедрить исполняемый файл, который может открыть нам удалённый доступ к устройству прямо в смартфон с зашифрованным хранилищем. Мы смогли его запустить и нам не пришлось разблокировать смартфон, не пришлось ничего расшифровывать. Достаточно было знать об особенностях шифрования хранилища в смартфонах и о возможностях которые дал нам разблокированный загрузчик.
Однако пока что мы полагаемся на права, которые нам предоставил SELinux контекст маджиска, а для извлечения данных нам необходимо уметь запустить такой же демон, но на любом устройстве, в том числе на устройстве без root-прав.
Зачем нужны root-права?
Честно говоря, когда мне задают вопрос, зачем я получал root-права на своем девайсе, я иногда впадаю в ступор, поскольку использую какое-то специфичное ПО, требующее таких разрешений достаточно редко и точечно.
Как хорошие примеры могу привести эффективное использование программ-firewalls, которые с помощью расширенных прав могут более гибко и эффективно контролировать траффик. Также, программы предназначенные для очистки «мусорных» файлов работают гораздо эффективнее, как и разнообразные файловые менеджеры, которые могут позволить вам редактировать системные файлы. Программы для резервного копирования приложений могут сохранять все данные приложения.
Отдельно хотелось бы упомянуть Xposed Framework — специализированное ПО в виде фреймворка, позволяющее одним приложениям изменять поведение системных функций Android в других приложениях и получать более полный доступ к их ресурсам. Например, именно на этом принципе основан Xposed-модуль для перевода текста на любой язык прямо в целевом приложении.
Причина #4. Реклама
Но если у тебя есть root, проблема решается очень просто, причем раз и навсегда, на уровне всей системы. Достаточно установить AdAway, нажать кнопку «Загрузка файлов и применение блокировки рекламы» и перезагрузиться. В дополнение к полному избавлению от рекламы ты получишь сокращение потребления трафика, так как хосты, раздающие рекламу, жестко блокируются на самом низком уровне (если быть точным, они просто перенаправляются на localhost с помощью файла /system/etc/hosts).
Несколько примеров
В маркете полно разнообразных root-приложений с, казалось бы, действительно крутой функциональностью. Это и софт для запуска ADB в сетевом режиме, и приложения для установки recovery и ядер, и софт для перезагрузки напрямую в recovery. Сейчас я покажу, насколько на самом деле сложны эти приложения. Итак, первый тип софта: bloatware cleaner, приложение для очистки Android от системных (неудаляемых) приложений. Реализуется с помощью трех (можно одной) строк:
String apk = «/system/app/Email.apk»;
runSuCommand(«mount -o remount,rw /system»);
runSuCommand(«rm » + apk);
Все! Мы удалили системное приложение Email. Добавь сюда интерфейс с возможностью выбора приложений (на основе списка, сформированного из содержимого /system/app/ и /system/priv-app/), и у тебя есть полноценный bloatware cleaner. Можно прикручивать рекламу и выкладывать в маркет. Только имей в виду, что, начиная с Android 5.0, приложения в каталоге /system/app/ располагаются в собственных подкаталогах, так что придется смотреть, какая версия ОС стоит, и при необходимости использовать уже другой код:
String app = «/system/app/Email»;
runSuCommand(«mount -o remount,rw /system»);
runSuCommand(«rm -rf » + app);
В Android 5.0 каждое приложение располагается в своем собственном подкаталоге
ОK, а как насчет приложения для перезагрузки в recovery? В кастомах это штатная функция, доступная в Power Menu, но в стоковых прошивках для этого приходится использовать специальный софт. Все сложно? Отнюдь:
Да, это всего одна команда. То есть полноценное приложение с кнопкой «Перезагрузиться в recovery» уместится в 15–20 строк. Неплохо, не так ли? Ладно-ладно, возьмем более сложный пример — прошивку кастомной консоли восстановления прямо из Android. Звучит круто? Конечно, но в коде это выглядит так:
Стоит отметить, что это пример для чипов Qualcomm, в устройствах на базе других SoC путь до раздела recovery будет другим. Ну и в целом пример не вполне корректный, по-хорошему надо писать интерфейс выбора образа recovery (здесь это /sdcard/recovery.img), а дальше прописывать его в переменную recoveryImg. Но в любом случае исходник полноценного приложения вряд ли будет длиннее тридцати строк.
Кстати, проверить, какой чип используется в девайсе, можно с помощью все того же /proc/cpuinfo:
Идем дальше, на очереди приложения в стиле WiFi ADB (это реальное название). В маркете таких полно, и все они выглядят одинаково: экран с одной кнопкой для включения/выключения режима отладки по сети (ADB over WiFi). Функция очень удобная, а потому приложения пользуются популярностью. Как реализовать то же самое? Как всегда, очень просто:
runSuCommand(«setprop service.adb.tcp.port 5555; stop adbd; start adbd»);
runSuCommand(«setprop service.adb.tcp.port -1; stop adbd; start adbd»);
Ну и в завершение поговорим о настройщиках ядра. Таких в маркете достаточно много, один из наиболее популярных — TricksterMod. Он позволяет изменять алгоритм энергосбережения ядра, включать/выключать ADB over WiFi, настраивать подсистему виртуальной памяти и многое другое. Почти все эти операции TricksterMod (и другой схожий софт) выполняет, записывая определенные значения в синтетические файлы в каталогах /proc и /sys.
Реализовать функции TricksterMod не составит труда. К примеру, нам надо написать код, изменяющий алгоритм энергосбережения процессора (governor). Для выполнения этой операции следует записать имя нужного алгоритма в файл /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor, однако для начала следует выяснить, какие алгоритмы поддерживает ядро. Они перечислены в другом файле, поэтому мы напишем простую функцию для его чтения:
Имея список поддерживаемых алгоритмов, мы можем выбрать один из них, записав в файл scaling_governor. Для удобства будем использовать такую функцию:
Обрати внимание, что после записи значения мы вновь читаем файл, чтобы удостовериться, что ядро действительно переключилось на указанный алгоритм. Далее можно создать формочку с кнопочками и менюшками и повесить на них наши функции.
Есть и множество других файлов для тонкой настройки алгоритма энергосбережения
Раньше, когда деревья были высокими а слоны мохнатыми, во времена Android ~4, существовали специальные утилиты как на само устройство так и на ПК, с помощью которых можно было получить root.
Если выражаться точнее, эти утилиты взламывали систему одним из множества способов и снисходительно делились с вами кусочком этого доступа.
Большая часть таких утилит была на китайском языке и тыкаться приходилось буквально вслепую. Вот самые яркие представители этого класса:
Преимущества такого способа получения очевидны — простота получения и относительно высокий шанс успеха. Однако такие недостатки как шпионаж, фоновая установка ПО и в целом непрозрачность схемы, как по мне, перекрывают это преимущество с лихвой. Тем более, что на последних версиях Android вероятность успеха получения прав с помощью этих утилит всё ниже. Не рекомендую данный способ к применению.
В определенный момент, как альтернатива этим утилитам, на арену рутирования выходит OpenSource-проект Magisk разработанный, несомненно, талантливым, программистом, под ником topjohnwu.
Главная особенность данного метода — возможность «внесистемного» внесения изменений с помощью подключаемых модулей. Это означает, что с выключением Magisk-модуля, отменялись изменения в системе, которые вносил этот модуль.
Работает это, на самом деле, проще чем можно подумать. В корне файловой системы создается «зеркало» раздела data (так и называется — data_mirror) и необходимые изменения вносятся в систему посредством создания символических ссылок на этот раздел.
Также, старые версии Magisk «из коробки» способны скрыть факт наличия root-прав от программ, которые не любят их (банковские приложения, например). Новые версии требуют установки дополнительных модулей.
Преимущества и недостатки рутинга
На данный момент смартфонами и планшетами под управлением операционной системы Android пользуются все больше и больше пользователей. Как упоминалось выше, root — это доступ ко всем данным компьютера и возможности их изменения. Так, OS Android имеет свой корневой каталог, который защищен от большинства пользователей, но существуют способы получения доступа ко всем файлам устройства.
Это делается в большинстве случаев для того, чтобы максимально настроить устройство под себя (полная настройка аудио, видео, или даже микрофона), или удаления множества установленных вместе с заводской прошивкой приложений, которые обычно не нужны и при этом занимают много места в внутренней памяти устройства. Именно благодаря root-доступу, пользователь может получить «безграничный» доступ ко всем файлам на устройстве под управление Android OS. Так как iOS тоже является UNIX-подобной системой, на устройствах Apple есть схожий процесс, который называется джейлбрейк (с «jailbreak» — побег из тюрьмы).
На некоторых устройствах root-доступ уже предустановлен (часто на устройствах китайской фирмы)
У этого процесса есть свои плюсы а также минусы.
Причина #7. Двойная загрузка
Имея root, на смартфоне можно организовать двойную, тройную и какую угодно другую загрузку. Просто устанавливаем MultiROM Manager, нажимаем кнопку Install, перезагружаемся и получаем смартфон, на который можно установить сколько угодно прошивок, причем не только Android, но и Ubuntu Touch, Sailfish OS или Firefox OS.
Причина #8. Полная отвязка от Google и других сервисов
Кроме того что помогает избавиться от Bloatware (см. причину номер один), root также позволяет полностью отвязать смартфон от каких-либо сервисов сторонних компаний, будь то Google или сервисы самого производителя устройства. В журнале уже была опубликована большая статья, посвященная этой теме, поэтому не буду повторяться, скажу лишь, что дополнительные сведения о том, какие компоненты системы сливают информацию, а какие нет, всегда можно узнать на профильных форумах, посвященных конкретному устройству или компании-производителю.
1Mobile: анонимный маркет для Android