ื_Разработчику нередко нужно изучить данные, которые приложение сохраняет в процессе работы. Я расскажу о том, как на настоящем устройстве посмотреть, что приложение записало в свою базу SQLite. Для этого потребуется «рутовать» устройство и поставить command-line клиент для SQLite. Также расскажу, что делать, если это невозможно._

Статья не претендует на универсальность. У меня получилилось сделать все именно так, как описано. Но я не могу быть уверен, что все произойдет точно также на следующий раз или на другом устройстве. Поэтому смотрите на статью в первую очередь как на набор идей. Итак…

Каждому разработчику время от времени требуется залезть в каталог приложения, полистать и поправить базу SQLite, заглянуть в SharedPreferehces или посмотреть, что оно в процессе работы сохранило на диск. Я в очередной раз столкнулся с этой задачей. Получить доступ к данным приложения можно, но не для всех приложений, не очень просто, не очень удобно, и обязательно требуется компьютер. Мне же потребовалось сделать это после нескольких дней работы на реальном устройстве вдали от рабочего места. Поэтому я решил запастись инструментами на будущее.

Доступ к данным на диске в Android ограничен с помощью стандартного механизма прав, унаследованного от Linux. Чтобы получить беспрепятственный доступ ко всем файлам, необходимо получить права пользователя root. Возможность получить такие права даже у разработчика отсутствует, поэтому нам придется встроить в операционную систему на устройстве соответствующий механизм.

Итак, я решил «рутовать» свой телефон. Слово «рутовать» происходит от имени пользователя root.

Сразу скажу, я — параноик. Поэтому я никогда не запускаю программы, скачанные с торрентов, и никогда не будут рутовать телефон, в котором настоящая SIM-карта и мои основные аккаунты в Google и Facebook. Даже думать не хочу, кто и как этим сможет воспользоваться. И вам не советую. Поэтому насилию был подвергнут специально купленный для нужд разработки Nexus 4.

Свежий андроид

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

Я обновил прошивку и создал себе отдельный аккаунт на этот телефон.

После обновления прошивки не выполяйте «fastboot oem lock», разблокированный загрузчик нам еще потребуется.

Custom recovery

Диск устройства имеет несколько загрузочных разделов. Один из них называется Recovery и предназначен для установки апдейтов, которые невозможно установить при загруженной операционной системе. Существуют самодельные загрузчики (так называемые сustom recovery), которые имеют дополнительные функции, в частности добавление команды su в операционную систему и установка неподписанных апдейтов. Я использовал recovery TWRP. Сравнение с другими я не проводил: все получилось с первого раза, и меня это удовлетворило.

TWRP собирается под каждое конкретное устройство отдельно, нужно в списке устройств найти своё. На сайте есть ссылка для скачивания и инструкция по установке.

Если вы версию операционной системы не обновляли, или команда fastboot сообщит, что загрузчик заблокирован, то необходимо будет загрузчик разблокировать. Учтите, что устройство позволяет это сделать только после удаления всех пользовательских данных, чтобы вы не получили таким способом к ним доступ.

adb reboot bootloader
fastboot oem unlock

Я прошивку только что обновил, и загрузчик у меня остался разблокированным. Мне было достаточно следующего:

adb reboot bootloader
fastboot flash recovery twrp-3.0.2-0-mako.img

Инструкция утверждает, что если перезагрузить устройство, то кастомная recovery будет перезаписана на родную после перезагрузки. Я не знаю, всегда ли это происходит, мне было достаточно после прошивки recovery сразу его загрузить. Для этого, не перезагружая устройство, нажал несколько раз «Volume down» до появления надписи «Recovery mode» и выбрал этот пункт нажатием «Power».

Если все хорошо, то загрузится recovery TWRP. Внизу контрол, чтобы разрешить модификацию системного раздела. Сдвигаю синий ползунок вправо.

Теперь нам нунжы Reboot, затем System. Перед этим любопытные могут походить по менюшкам. Программа замечает, что операционная система ещё не рутована, и предлагает сделать это. То, что нам и нужно. Для этого опять сдвигаю синий ползунок вправо.

Root

После загрузки вы увидите нотификацию, предлагающую установить утилиту SuperSU. Поскольку выполнение команды su даёт слишком много прав, а выполнить её может любое приложение, пользуется популярностю реализация команды su, которая каждый раз запрашивает разрешение у пользователя. Чтобы все было под контролем. SuperSU — это приложение, которое будет показывать пользователю этот запрос.

Я выбираю вариант установки через Google Play: нажимую Play, в загрузившемся приложении Google Play на странице SuperSU нажимаю Update, посли успешного обновления — Open. Я, разумеется, Expert (нажимаю соответствующую кнопку). Для установки нажимаю Normal, на Nexus этого достаточно. В соответствии с рекомендацией перезагружаюсь.

Дальше можно зайти на устройство и насладиться. В момент выполнения команды su обязательно посмотрите на экран устройства. У вас есть 10 секунд на то, чтобы разрешить получение прав.

$ adb shell
shell@mako:/ $ su

root@mako:/ # id
uid=0(root) gid=0(root) context=u:r:init:s0

root@mako:/ # cd /data/data
root@mako:/data/data #
root@mako:/data/data # cd com.android.chrome

root@mako:/data/data/com.android.chrome # ls -la
drwxrwx--x u0_a37   u0_a37            2016-10-29 21:43 cache
drwxrwx--x u0_a37   u0_a37            2016-10-29 21:43 files
lrwxrwxrwx install  install           2016-10-29 21:30 lib -> /data/app-lib/com.android.chrome
drwxrwx--x u0_a37   u0_a37            2016-10-29 21:45 shared_prefs

root@mako:/data/data/com.android.chrome # cd shared_prefs/                                                               <
root@mako:/data/data/com.android.chrome/shared_prefs # ls -l
-rw-rw---- u0_a37   u0_a37        305 2016-10-29 21:45 com.android.chrome_preferences.xml

root@mako:/data/data/com.android.chrome/shared_prefs #  cat com.android.chrome_preferences.xml                                         <
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name=“delayed_account”>helloworld@gmail.com</string>
    <set name="ToS acknowledged accounts">
        <string>helloworld@gmail.com</string>
    </set>
    <boolean name="prefs_sync_accounts_changed" value="true" />
</map>

root@mako:/data/data/com.android.chrome/shared_prefs #

BusyBox

Андроид — это не полноценный Linux, и большинство привычных command-line tools на нём отсутствует. Поэтому дальше вам нужно поставить BusyBox с комплектом любимых всеми нами команд.
Вот этот. BusyBox — это реализация стандартных линуксовых команд, оптимизированная для встраиваемых (embedded) устройств.

Устанавливаем, запускаем, разрешаем получение прав, жмём Install. Всё, BusyBox установлен, приложение нам больше не нужно.

shell@mako:/ $ ls /system/xbin/ | wc -l                                       
342
shell@mako:/ $

SQLite3 command-line client

Команда sqlite3, описанная в документации, установлена «из коробки» только на эмуляторе, на устройстве её нет. Соответственно, её надо где-то взять. Очевидный способ — взять в эмуляторе. У меня эмулятор работает медленно, поэтому я не люблю его запускать, нашёл бинарники в интернете.

shell@mako:/ $ uname -a                                                        
Linux localhost 3.4.0-perf-gdffc258 #1 SMP PREEMPT Wed Jul 8 23:25:22 UTC 2015 armv7l GNU/Linux
shell@mako:/ $

Итак, платформа ARMv7. StackOverflow подсказывает, что начиная c Андроида 4.1, нужен PIE.

Выкачиваю, переименовываю, заливаю на устройство в каталог /sdcard. Затем захожу на устройство и переношу бинарник в каталог /system/bin. Обратите внимание, что раздел /system по умолчанию смонтирован read only, поэтому его необходимо перемонтировать. И не забудьте в конце перемонтировать обратно в read only.

$ mv sqlite3.armv7-pie sqlite3

$ adb push sqlite3 /sdcard/
[100%] /sdcard/sqlite3 

$ adb shell

shell@mako:/ $ mount | grep system
/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 ro,seclabel,relatime,data=ordered 0 0

shell@mako:/ $ su                                                         

root@mako:/ # mount -o remount,rw /system

root@mako:/ # mount | grep system
/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 rw,seclabel,relatime,data=ordered 0 0

root@mako:/ # cp /sdcard/sqlite3 /system/bin/

root@mako:/ # chmod 4755 /system/bin/sqlite3

root@mako:/ # mount -o remount,ro /system                                     

root@mako:/ # rm /sdcard/sqlite3                                              

root@mako:/ #

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

root@mako:/ # cd /data/data/com.google.android.email/databases

root@mako:/data/data/com.google.android.email/databases # ls
EmailProvider.db
EmailProvider.db-journal
EmailProviderBody.db
EmailProviderBody.db-journal

root@mako:/data/data/com.google.android.email/databases # sqlite3 EmailProvider.db
SQLite version 3.8.11.1 2015-07-29 20:00:57
Enter ".help" for usage hints.
sqlite> .tables
Account             Mailbox             Message_Deletes     android_metadata 
Attachment          Message             Message_Updates  
Credential          MessageMove         Policy           
HostAuth            MessageStateChange  QuickResponse    
sqlite>

Документацию о возможностях CLI клиента SQLite можно посмотреть здесь.

Для начала:

  • .tables — список таблиц
  • .schema Tablename — устройство таблицы с именем Tablename
  • select * from Tablename — содержимое таблицы с именем Tablename
  • .help — встроенный справочник

Терминал

Если поставить эмулятор терминала, то можно получить доступ к шеллу прямо с устройства.

Для того, чтобы нажать Ctrl-C или Ctrl-D на виртуальной клавиатуре, нажимайте C и D вместе с нажатой клавишей «Volume Down». Это меняется в настройках приложения, загляните туда.

Альтернативные способы

Если лень возиться с установкой command-line клиента, можно после рутования поставить из Google Play приложение для просмотра таблиц, например, aSQLiteManager.

Если телефон рутовать нельзя

Я знаю два способа для нерутованых телефонов. Первый — извлечь файл на компьютер и открыть. На некоторых у стройствах есть команда run-as, которая позволяет выполнять команды с правами определенного приложения:

130|shell@mako:/ $ run-as ru.mobiledimension.krm ls /data/data/ru.mobiledimension.krm/shared_prefs/
TwitterAdvertisingInfoPreferences.xml
com.crashlytics.prefs.xml
com.crashlytics.sdk.android:answers:settings.xml
io.fabric.sdk.android:fabric:io.fabric.sdk.android.Onboarding.xml
shell@mako:/ $

Соответственно, можно скопировать с устройства файл и открыть любым доступным на компьютере способом.

В команде ниже com.yourpackge.name — id приложения, filename.db — имя файла с базой.

adb -d shell "run-as com.yourpackge.name ls /data/data/com.yourpackge.name/databases/”
adb -d shell "run-as com.yourpackge.name cat /data/data/com.yourpackge.name/databases/filename.db > /sdcard/filename.sqlite"
adb pull /sdcard/filename.sqlite

Аналогично можно посмотреть содержимое файла SharedPrefereces:

adb -d shell "run-as com.yourpackge.name cat /data/data/com.yourpackge.name/shared_prefs/com.yourpackge.name_preferences.xml"

Второй способ — добавить в приложение специальную библиотеку для мониторинга, например, Stetho. Но это уже тема для отдельной статьи.

Для настоящих сварщиков

Хотите понять, как приложение под Aндроид может использовать команду su, чтобы получить дополнительные права? Ниже пример того, как это можно сделать.

final Process process = Runtime.getRuntime().exec("su");
final DataInputStream is = new DataInputStream(process.getInputStream());
final DataInputStream eis = new DataInputStream(process.getErrorStream());
final DataOutputStream os = new DataOutputStream(process.getOutputStream());

os.writeBytes(cmd + "\n");
os.writeBytes("exit\n");
os.flush();
os.close();

final BufferedReader readerOut = new BufferedReader(new InputStreamReader(is));
final BufferedReader readerErr = new BufferedReader(new InputStreamReader(eis));

process.waitFor();

То есть приложение какие-то дополнительные права на самом деле не получает. Но команда su дает возможность выполнять команды с привилегиями рута, это могут быть встроенные команды операционной системы, написанные скрипты или записанные самим приложением программы.

Подробнее можете почитать об этом в документации к библиотеке libsuperuser.

Ссылки