Как известно, Android — это тоже Linux, основной особенностью которого является то, что он позволяет устанавливать приложения только на Java/Kotlin в формате apk, запускаемые через свою реализацию JVM — своего рода песочницу. Раз уж это Linux, то и запускать его можно через стандартные средства — LXC-контейнеры, как это делается в том же Waydroid. Главный плюс такого подхода в отличие от реального устройства — полный доступ к файловой системе, что эквивалентно рут-доступу. На реальном устройстве получить рут-права с помощью Magisk несложно, но это приводит к утрате данных вместе с ключом шифрования от sd-карты, хотя их можно и восстановить, если был бекап. Однако большей проблемой является то, что из-за этого перестают запускаться те же банковские приложения…
Установка и запуск
Установка:
# Для тех кто добавил репозитории типа arcglinuxcn и chaotic-aur
sudo pacman -S waydroid
# Можно из AUR
yay -S waydroid
Загружаем последний образ LineageOS с Google Play
sudo waydroid init -f -s GAPPS
В вики арча настройка описана сумбурно. Для waydroid не нужно устанавливать и загружать модуль binder.
Автоматический запуск контейнера, чтобы ускорить открытие приложений при старте системы:
sudo systemctl enable waydroid-container
Примеры команд:
# Останавливает текущую запущенную сессию WayDroid.
waydroid session stop
# Запускает полный графический интерфейс Android (рабочий стол).
waydroid show-full-ui
# Устанавливает APK-файл в WayDroid.
waydroid install <file>
# Запускает конкретное приложение по его пакетному имени.
waydroid launch <app>
# Удаляет приложение из WayDroid.
waydroid remove <app>
# Открывает оболочку (shell) Android внутри контейнера WayDroid с правами суперпользователя.
sudo waydroid shell
Все файлы waydroid в тч конфиги хранятся в сл каталогах:
/var/lib/waydroid
~/.local/share/waydroid
Настройка сети и подключение к эмулятору
Заставляем работать Интернет внутри Waydroid:
# Разрешаем входящие соединения для DHCP (порт 67) и DNS (порт 53).
# DHCP нужен для получения IP-адреса Waydroid, DNS — для разрешения доменных имен.
sudo ufw allow 67
sudo ufw allow 53
# Разрешаем пересылку трафика (FORWARD) по умолчанию.
# Это критически важно, так как Waydroid работает как контейнер и его трафик должен перенаправляться через хост-систему.
sudo ufw default allow FORWARD
# Перезагружаем UFW, чтобы применить новые правила.
sudo ufw reload
Подключение через adb (пакет android-tools
):
# Сначала узнаем ip контейнера
$ sudo waydroid shell ip a
...
2: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
...
inet 192.168.240.112/24 brd 192.168.240.255 scope global eth0
...
# А теперь подключимся к нему
$ adb connect 192.168.240.112:5555
connected to 192.168.240.112:5555
adb удобно использовать для установки приложений и просмотра логов.
This device isn’t Play Protect certified
Google Play из коробки отказывается работать, так как ему не нравится странная модель устройства, которую отдает эмулятор. Чтобы это исправить в официальной группе советуют выполнить команду:
sudo waydroid shell ANDROID_RUNTIME_ROOT=/apex/com.android.runtime ANDROID_DATA=/data ANDROID_TZDATA_ROOT=/apex/com.android.tzdata ANDROID_I18N_ROOT=/apex/com.android.i18n sqlite3 /data/data/com.google.android.gsf/databases/gservices.db "select * from main where name = \"android_id\";"
И зарегистрируйте устройство, а потом перегрузите waydroid.
Проще прикинуться каким Google Pixel:
cat <<EOF | sudo tee -a /var/lib/waydroid/waydroid_base.prop
ro.product.brand=google
ro.product.device=crosshatch
ro.product.manufacturer=google
ro.product.model=Pixel 3
ro.product.name=crosshatch
ro.vendor.product.manufacturer=google
EOF
Доступ к файловой системе Android-контейнера
Файлы на карте памяти лежат тут:
~
❯ sudo ls -ahl ~/.local/share/waydroid/data/media/0
total 0
drwxrwx--- 1 1023 1023 186 Jul 2 17:25 .
drwxrwx--- 1 1023 1023 2 Jul 2 19:17 ..
drwx------ 1 10146 10146 0 Jul 2 17:25 Alarms
drwxrws--x 1 1023 1023 24 Jul 2 17:25 Android
drwx------ 1 10146 10146 0 Jul 2 17:25 Audiobooks
drwx------ 1 10146 10146 0 Jul 2 17:25 DCIM
drwx------ 1 10146 10146 0 Jul 2 17:25 Documents
drwx------ 1 10146 10146 0 Jul 2 17:25 Download
drwx------ 1 10146 10146 22 Jul 2 17:25 Movies
drwx------ 1 10146 10146 22 Jul 2 17:25 Music
drwx------ 1 10146 10146 0 Jul 2 17:25 Notifications
drwx------ 1 10146 10146 22 Jul 2 17:25 Pictures
drwx------ 1 10146 10146 0 Jul 2 17:25 Podcasts
drwx------ 1 10146 10146 0 Jul 2 17:25 Ringtone
Корень смонтирован в ro
в /var/lib/waydroid/rootfs
.
Перехват трафика
Даже школьники знают, что перехват трафика делается через подмену сертификата.
Для начала установим mitmproxy:
sudo pacman -S mitproxy
При первом запуске mitmproxy
создаст ключи для корневого сертификата в каталоге ~/.mitmproxy
:
mitmproxy
Теперь копируем корневой сертификат в /etc/system/cacerts
внутри контейнера:
# Остановим сессию
sudo waydroid session stop
# Увеличим размер системного контейнера, чтобы можно было в него добавиь файлы
sudo truncate -s +100M /var/lib/waydroid/images/system.img
sudo e2fsck -f /var/lib/waydroid/images/system.img
sudo resize2fs /var/lib/waydroid/images/system.img
# Смонтируем образ в /mnt
sudo mount -o loop,rw /var/lib/waydroid/images/system.img /mnt
# Корневой сертификат должен иметь в качестве имени хеш от старого поля subject, который имеет суффикс `.0`.
cert_name="$(openssl x509 -inform PEM -subject_hash_old -in ~/.mitmproxy/mitmproxy-ca-cert.cer | head -1).0"
# Копируем сертификат mitmproxy.
sudo cp ~/.mitmproxy/mitmproxy-ca-cert.cer /mnt/system/etc/security/cacerts/$cert_name
# Устанавливаем права доступа.
sudo chmod 644 /mnt/system/etc/security/cacerts/$cert_name
- На идею выше меня навел этот комментарий к gist. В арче какие-то свои настройки, потому как никакого overlayfs не работает?
- Про сертификаты можно почитать тут.
Вышеописанным способом можно пропатчить и образ, который скачивает Android Studio… лишь бы было желание.
Вариант по-проще:
# Устанавливаем прокси
adb shell settings put global http_proxy "<host_ip>:8080"
# Сбрасываем прокси
adb shell settings delete global http_proxy
# или так
adb shell settings put global http_proxy :0
Можно создать правила iptables для перенаправления всего трафика по умолчанию (вариант лучше):
sudo iptables -t nat -A PREROUTING -i waydroid0 -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -t nat -A PREROUTING -i waydroid0 -p tcp --dport 443 -j REDIRECT --to-port 8080
Так же для этого варианта нужно включить ip forwarding. Это можно сделать разными способами, например:
sudo sysctl -w net.ipv4.ip_forward=1
# Делаем постоянным
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-waydroid-forwarding.conf
# Перечитываем все конфиги
sudo sysctl --system
Запустим прокси:
mitmweb
Вместо mitmproxy
, у которого есть API для написания скриптов на Python, можно использовать Burp Suite для автоматического сканирования на уязвимости… Да что угодно и зачем угодно…
Внедрение кода
Для начала нам потребуется скачать приложение в виде apk. Для этого есть множество способов и специальных сервисов типа этого, не говоря о том, что у вас полный доступ к файловой системе эмулятора.
Установим apktool
:
sudo pacman -S android-apktool
Декомпиляция приложения:
apktool d com.govno.app.apk /path/to/decompiled
cd /path/to/decompiled
В данном каталоге у нас будет куча файлов с расширением .smali
. Я уже выше писал, что у Android своя реализация JVM под названием Dalvik. Smali — это ее байт-код, атомарные операции, выполняемые виртуальной машиной, в понятном для человека виде. Каждый smali-файл соответствует классу Java/Kotlin и легко поддается редактированию. Вы можете поиском через grep/rg/fzf найти нужные вам строки, а затем отредактировать файл.
Например есть какой-то метод, в котором есть интересующее нас значение:
.method public final b()Ljava/lang/String;
.locals 1
# ...
# Вот тут оно присваивается в регистр 0
move-result-object v0
# ...
# А затем возвращается
return-object v0
.end method
Этот код можно изменить так:
.method public final b()Ljava/lang/String;
# Для логера нужно минимум три регистра
.locals 3
# ...
# В регистре 0 лежит интересующее нас значение
move-result-object v0
# Тут вызывается Log.d("TEST_DEBUG", "$0")
const-string v1, "TEST_DEBUG"
invoke-static {v0}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v2
invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
return-object v0
.end method
Перейдем в каталог с декомпилированным приложением и соберем его:
apktool b -f -o ../modified.apk
cd ..
Теперь нужно подписать приложение:
# Сгенерируем ключ для подписи
keytool -genkeypair -v \
-keystore debug.keystore \
-alias androiddebugkey \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-storepass android \
-keypass android \
-dname "CN=Android Debug, OU=Unknown, O=Android, L=Unknown, ST=Unknown, C=US"
# Нужно выровнять архив (jar)
zipalign -v 4 modified.apk aligned.apk
# А теперь все нужно подписать
apksigner sign \
--ks debug.keystore \
--ks-pass pass:android \
--key-pass pass:android \
--v1-signing-enabled true \
--v2-signing-enabled true \
--v3-signing-enabled true \
--min-sdk-version 21 \
aligned.apk
А потом нужно установить aligned.apk
и запустить…
И далее через adb смотрим интересующее нас значение:
$ adb logcat -s "TEST_DEBUG"