Una
vez ganemos el root en nuestro móvil estaremos limitados por los
ejecutables que este contenga de fábrica. Para poder realizar más
acciones necesitaremos instalar binarios ejecutables adicionales que
nos permitirán hacerle todo tipo de cosas al hardware.
¿Cómo funcionan los binarios en Android?
Android contiene binarios ejecutables nativos que provienen de
diferentes fuentes. Los binarios comunes que encuentras en
dispositivos Android comerciales pueden ser parte de toolbox o
toybox, y algunos también pueden provenir del código de AOSP.
Los binarios se encuentran en las rutas /system/bin,
/system/xbin, y /sbin:
/system/bin: En
este directorio se encuentran los binarios esenciales que son parte
de AOSP y son comunes a la mayoría de los dispositivos Android.
Estos ejecutables proporcionan funciones básicas del sistema y
herramientas de línea de comandos.
/system/xbin: Se
usa para almacenar binarios adicionales que pueden no ser esenciales
para las funciones básicas del sistema. En este directorio se
colocan los binarios adicionales que hemos compilado por nuestra
cuenta.
/sbin: Este
directorio se utiliza para almacenar binarios críticos del sistema
que están relacionados con operaciones del sistema a nivel más
bajo. A menudo contiene binarios que son necesarios para el arranque
del sistema y otras operaciones esenciales. En Android, este
directorio podría contener binarios específicos del fabricante o
personalizaciones del sistema.
Para construir bibliotecas nativas (archivos .so)
y binarios ejecutables específicos que puedan ser usados por las
aplicaciones de Android o en una consola, como adb
shell, Google proporciona el Kit de Desarrollo Nativo (NDK).
Esta herramienta es especialmente útil cuando se requiere un
rendimiento optimizado y se elige escribir ciertas partes de la
aplicación en lenguajes de bajo nivel. Sin embargo el hecho de que
un binario ejecutable haya sido optimizado dentro del NDK no
significa que tenga todos los permisos necesarios para funcionar en
Android. Necesitarán el acceso root los binarios que realicen tareas
como: acceder y modificar las particiones del sistema, acceso a
algunos archivos y directorios como archivos de configuración
críticos y directorios sensibles, modificar o controlar procesos y
servicios del sistema operativo, acceso a ciertos componentes de
hardware, como el controlador de la CPU, la interfaz de red avanzada,
o ajustes específicos de hardware. No debemos confundir el NDK,
destinado para construir binarios y bibliotecas con el Software
Development Kit (SDK), destinado para el desarrollo de aplicaciones
.apk.
Instalar binarios sin ser root es complicado por la limitación de
ejecutar chmod para
otorgar permisos de ejecución o el impedimento de ejecutar chown,
ya que el sistema de archivos puede estar montado con restricciones
de seguridad que impiden cambios en los propietarios de ciertos
archivos o directorios, como describíamos en el anterior
artículo sobre cómo conseguir el root. Se podría intentar
instalar en la ruta /data/local/tmp/
ya que esta ruta se utiliza para almacenar y realizar ciertas
operaciones temporales. Por lo general, la instalación de binarios
requiere de root.
Para
instalar binarios estáticos que son aquellos que no dependen de
ninguna biblioteca, por lo que se pueden usar directamente, una forma
sencilla es compilarlos para el hardware de nuestro móvil (arm ó
arm64) y copiarlos a la carpeta destino con adb
push /ruta/de/nuestro/pc/origen /ruta/destino/móvil.
¿Cómo instalar busybox estático, busybox dinámico y/u otros
binarios?
Para ganar algunas nuevas funcionalidades podemos instalar los
binarios individualmente o hacer una instalación de “busybox”
que es una especie de navaja suiza que alberga muchos binarios en un
mismo ejecutable. El repertorio de instrucciones que contiene es
mayor que el de toolbox o toybox, que son sus alternativas. Existen
dos tipos de compilaciones de busybox, la estática que se vale por
sí sola y ocupa más espacio, o la dinámica que depende de
bibliotecas (.so) que
pueden ser compartidas por otras aplicaciones y ocupa menos espacio.
En ambas instalaciones se usan enlaces simbólicos que ejecutan el
binario busybox. Las bibliotecas se suelen almacenar en /system/lib.
Para instalar cualquier binario simplemente basta con haberlo
compilado para la arquitectura en la que estamos trabajando y
copiarlo a su carpeta de destino.
Instalando busybox ganaremos algunas funcionalidades pero aún nos
faltarán otras para poder sacarle todo el provecho al hardware. Otra
forma de actuar sería instalar un sistema operativo Linux con todo
los binarios necesarios para explorar todas las capacidades de
nuestro móvil. El camino más largo es adaptar una distribución
Linux a nuestro hardware o buscar si alguien ya ha implementado una
solución más rápida para nuestro propósito. Las instrucciones más
sencillas para probar un sistema Linux, como podría ser Debian, son
instalar el sistema de archivos en una partición del móvil, como
podría ser el almacenamiento externo y entrar en modo fastboot para
indicarle al móvil que arranque desde el kernel indicado. Estas
instrucciones se pueden encontrar aquí.
En vez de portar un nuevo sistema operativo a nuestro hardware,
podemos aprovechar las propiedades del sistema operativo que ya
tenemos, Android, e implementar los recursos que necesitemos. Esto se
puede conseguir con un entorno “chroot” y de esta forma nos
evitaremos el tedioso trabajo de adaptar todos los controladores y el
software del sistema operativo al hardware, aún coste en ciertas
restricciones al hardware que se podrían superar implementando
modificaciones en el sistema operativo principal.
Si creamos un entorno “chroot” sin “root” muchas de las
operaciones necesarias como la instalación de software y la
manipulación de ciertos directorios del sistema estarán
restringidas y puede que no funcionen, por lo que para un mayor
beneficio necesitaremos el “root” del teléfono.
El comando chroot de
Linux cambia el directorio raíz para un proceso y sus hijos. De esta
forma se consigue un entorno aislado dentro del sistema de archivos
principal, limitando el acceso del proceso a un subdirectorio
específico. Chroot sólo
proporciona aislamiento a nivel de sistema de archivos. No aísla
completamente otros recursos como procesos, red o memoria. Dentro de
este entorno, no se tendrá acceso a recursos fuera de este
directorio por defecto. Por lo que para poder hacer uso de otros
directorios hay que montarlos con mount
y la opción -o rw
(permiso de lectura-escritura) o vincularlo mediante -o
bind. (Recuerda desmontar en orden inverso a como has montado,
para evitar dependencias entre ficheros).
El entorno chroot más básico que podemos construir es una jaula
con busybox. Para ello simplemente ejecutamos:
chroot /mnt/busybox /bin/busybox
--install
chroot
/mnt/Debian /bin/env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/bin/sh
Ó
chroot
/mnt/Debian /bin/sh
export
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
(Definiendo la variable PATH)
Construyendo Debian dentro de Android
Hay diferentes formas de construir un sistema Debian en un entorno
chroot desde Android. Una de ellas es desde una imagen mínima y
luego completar la instalación. En la dirección
https://ftp.debian.org/debian/dists/stable/main/installer-arm64/current/images/
tenemos las opciones “cdrom/”, “device-tree/”, “netboot/”
y “u-boot/”. La imagen “cdrom/” está destinada para
instalaciones desde CD-ROM. La carpeta “device-tree/” contiene
archivos .dtb que son archivos utilizados para describir la
información de hardware específica de una plataforma. Esto ficheros
se usan en sistemas integrados como la Raspberry pi. La carpeta
“u-boot/” contiene imágenes destinada a dispositivos que
funcionan con un gestor de arranque U-Boot.
La carpeta “netboot/” contiene imágenes destinadas a
instalaciones mínimas cómo la que hemos comentado.
Otro tipo de instalación podría ser usar una imagen cloud. En el
caso de Debian se podría descargar desde
https://cloud.debian.org/images/cloud/
e instalarla.
Existen otras distribuciones que ya viene preparadas para entornos
chroot como es el caso de AlpineOS. En este caso solo tenemos que
descomprimir el fichero y configurar el sistema.
Pero la forma más eficiente para instalar Debian en un entorno
chroot, es mediante debootstrap, una herramienta basada en un script
que automatiza la construcción del sistema de archivos de un sistema
Debian en un directorio específico de nuestro PC. Para ello
necesitamos un PC con una distribución de Linux en el que
ejecutaremos “debootstrap”.
Al correr “debootstrap”
con “--foreign”
estaremos indicando que vamos a realizar una instalación en dos
pasos, completándose en un dispositivo distinto, y se le agregamos
el parámetro “--arch=arm64”
le indicamos que el dispositivo de destino tiene una arquitectura ARM
de 64 bits. Esto hace que se genere también una carpeta con todos
los binarios necesarios para hacer uso de debootstrap en esa
arquitectura. Lo ideal sería partir de una jaula chroot con busybox
dentro de Android y poder ejecutar “debootstrap”
directamente en el mismo dispositivo, pero para ello tendríamos que
resolver todas sus dependencias y modificar el script.
Lo ejecutamos en nuestro PC Linux:
sudo
debootstrap --foreign --arch=arm64 stable /home/pc/DebianARM64
http://ftp.debian.org/debian
Comprimimos
el directorio Debian:
sudo
tar -cf DebianARM64.tar ./DebianARM64/
Se lo pasamos al móvil por adb:
adb push ./DebianARM64.tar
/storage/self/primary/
Accedemos a una shell del móvil:
adb
shell
Ya en el móvil, descomprimimos y montamos:
tar
-xf /storage/self/primary/DebianARM64.tar -C /mnt/
mount
-t proc none /mnt/DebianARM64/proc
mount
-t sysfs none /mnt/DebianARM64/sys
mount
-o bind /dev /mnt/DebianARM64/dev
chroot
DebianARM64/ /bin/bash
Definimos variables:
export
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Ejecutamos la segunda etapa de la instalación, que consiste en la
configuración del sistema:
cd
/debootstrap
./debootstrap
--second-stage
Cuando termine, configuramos el password del usuario root, y
añadimos el usuario con el que vamos a trabajar:
passwd
root
adduser
androidDebian
Salimos y volvemos a entrar logueandonos con:
chroot
/mnt/DebianARM64 /bin/login
Una vez logueados tenemos que añadir los usuarios “aid_*”
que utiliza Android para poder hacer uso del hardware. Podemos
encontrar una lista completa de los grupos y usuarios de Android en
su código fuente
https://android.googlesource.com/platform/system/core/+/refs/tags/android-8.1.0_r50/libcutils/include/private/android_filesystem_config.h
groupadd
-g 3001 aid_net_bt_admin
groupadd
-g 3002 aid_net_bt
groupadd
-g 3003 aid_inet
groupadd
-g 3004 aid_net_raw
groupadd
-g 3005 aid_net_admin
groupadd -g 3006 aid_net_bw_stats
groupadd
-g 3007 aid_net_bw_acct
groupadd
-g 3008 aid_net_bt_stack
Añadimos a los grupos los usuarios “root”
y los que hallamos creado, en mi caso “android”
usermod
-G 3003 -a root
usermod
-G 3003 -a android
Para que el gestor de paquetes “apt”
tenga acceso a internet hay que introducirlo en los grupos
secundarios aid_inet y
aid_net_raw. El grupo
principal puede ser cambiado por aid_inet.
usermod
-g 3003 -G 3003,3004 -a _apt
Cuando dejemos de usar el sistema Linux tenemos que desmontar los
discos en sentido inverso al que hemos montado:
umount
-o bind /dev /mnt/DebianARM64/dev
umount
-t sysfs none /mnt/DebianARM64/sys
umount
-t proc none /mnt/DebianARM64/proc
Para guardar nuestro sistema operativo Linux y continuar otro día
con el, podemos comprimirlo en un .tar o crear una imagen de disco.
Si decidimos crear una imagen, creamos el fichero:
touch
/mnt/DebianARM64.img
Lo llenamos de zeros:
dd
if=/dev/zero of=/mnt/DebianARM64.img bs=1M count=2048
Le damos formato ext4:
mke2fs
-t ext4 /mnt/DebianARM64.img
Lo adjudicamos al loop0:
losetup
/dev/block/loop0 ./DebianARM64.img
Lo montamos:
mkdir
/mnt/imagen
mount
-o rw -t ext4 /dev/block/loop0 /mnt/imagen
Copiamos la carpeta raíz:
mv
-r /mnt/DebianARM64 /mnt/imagen
O si decidimos comprimirlo en un fichero .tar:
tar
-cf Debian.tar /mnt/DebianARM64
Aplicaciones y proyectos
Todo
este proceso puede automatizarse por medio de una aplicación para
Android. Así es como trabaja LinuxDeploy,
una app que inicializa un entorno chroot con busybox e instala una
distribución Linux con una versión adaptada del script debootstrap.
LinuxDeploy permite la instalación de Alpine, Arch, CentOS, Debian,
Fedora, Kali, Slackware y Ubuntu en un entorno chroot dentro de
Android, creando para ello, según deseemos, una imagen de disco, un
directorio en una tarjeta flash, una partición o directamente sobre
la RAM. La distribución Linux instalada es accesible desde SSH y VNC
para su uso a distancia, de esta forma puedes convertir tu móvil en
un PC temporalmente. No es funcional al 100% por que el Hardware está
ocupado por los servicios de Android y su kernel. Todos los cambios
realizados en el dispositivo son reversibles, es decir, la aplicación
y los componentes se pueden eliminar por completo.
Un proyecto
pensando para convertir tu móvil Android en un PC completamente
funcional es maruos.com. Este
proyecto esta pensado para hacer un uso dual del hardware. Para ello
reemplaza el sistema operativo Android por el firmware Maru, el cuál
permite tener en el dispositivo móvil una distribución adaptada de
LineageOS y al conectarlo por HDMI a una pantalla tendríamos Maru
Desktop, una versión adaptada de Debian 9, comportándose como si
fuera un PC. Permite conectar teclado y ratón por bluetooth.
Desde Termux también se
puede realizar una instalación de Debian con GUI en un entorno
chroot. Además se puede lograr sin ser root al ejecutar la
instrucción proot, una implementación de chroot en el espacio de
usuario, lo que significa que no necesita ningún privilegio.
Una solución para instalar un sistema Linux completo con su
kernel es hacer uso de Qemu o
KVM.
Podríamos hacer uso de Qemu en dispositivos que no cuenten con
emulación por hardware, corriendo toda la emulación por software,
lo que podría suponer en un alto consumo de recursos. Y hacer uso de
KVM en dispositivos que tengan disponible la emulación por hardware.