En esta entrada explicamos el proceso seguido para rootear una tablet Energy Sistem NEO2 como esta:
Por defecto la tablet está protegida por el fabricante, si intentas acceder con el superusuario "root", obtendrás este mensaje de error:
$ adb root adbd cannot run as root in production builds
Los fabricantes son rehacios a dejar que los usuarios normales tenga acceso root a sus dispositivos, ya que no les gusta que los usuarios normales puedan customizar sus dispositivos (y tampoco que usuarios que no saben lo que hacen los puedan estropear). Si no eres root, tu capacidad de hacer modificaciones en tu dispositivo estará bastante limitada. La intención de esta articulo es hacerse root de la tablet Energy Sistem NEO2. Usaremos como sistema host un Ubuntu Linux 14.04. Advierto que el procedimiento es altamente destructivo si no se hace con cuidado. Advertido quedas, lector!
Averigua el product-id y el vendor-id
Conecta la tablet a tu PC con el cable USB y mira la salida del comando "lsusb":
$ lsusb
Identifica en el listado una linea como esta:
Bus 003 Device 066: ID 2207:0011
El ID 2207:0011 se corresponde con tu tablet Energy Sistem de 10.1 pulgadas.
Acceso al dispositivo a través de USB
Configurar el sistema operativo de tu PC para que tenga acceso al dispositivo Android a través del USB. Bajo Ubuntu, los usuarios regulares no pueden acceder directamente a los dispositivos USB por defecto. El sistema necesita estar configurado para permitir tal acceso. La mejor solución consiste en crear un fichero (como usuario root):
$ sudo vi /etc/udev/rules.d/51-android.rules
Y añadir el siguiente contenido:
SUBSYSTEM=="usb", ATTR{idVendor}=="<idvendor>", ATTR{idProduct}=="<idproduct>", MODE="0600", OWNER="<username>"
Donde:
- <username>: es el nombre del usuario que estará autorizado a acceder al dispositivo a través del USB
- <idvendor>: es el identificador del vendedor del dispositivo
- <idproduct>: es el identificador del producto
Para el dispositivo que nos ocupa:
<username> es "aicastell" <idvendor> es "2207" <idproduct> es "0011"
Por tanto, añade este contenido:
# adb protocol SUBSYSTEM=="usb", ATTR{idVendor}=="2207", ATTR{idProduct}=="0011", MODE="0600", OWNER="aicastell"
Cambia los permisos del fichero:
$ chmod a+r /etc/udev/rules.d/51-android.rules
Reinicia el servicio del udev:
$ sudo service udev restart
Estas reglas nuevas pasan a tener efecto la siguiente vez que se conecta un dispositivo. Por tanto, será necesario desconectar el dispositivo y volver a conectarlo al USB.
Customización especial
Este paso no es habitual en todos los dispositivos Android, pero SI es necesario para los dispositivos SOC Rockchip. Si no lo haces, el comando "adb devices" no detectará el dispositivo Android conectado. Crea este directorio:
$ mkdir ~/.android
Y crea este fichero, con este contenido:
$ vi ~/.android/adb_usb.ini # ANDROID 3RD PARTY USB VENDOR ID LIST -- DO NOT EDIT. # USE 'android update adb' TO GENERATE. # 1 USB VENDOR ID PER LINE 0x2207
Habilitar el modo desarrollador Android
En tu dispositivo Android, navega hasta el menu de configuración y busca la opción:
{ } Opciones de desarrollo
Si no tienes acceso a estas opciones, ves al apartado:
Ajustes > información de la tablet > Numero de compilación
Pulsa varias veces sobre la opción "Numero de compilación" hasta que se active la opción "Opciones de desarrollo".
Ahora navega a traves de estas opciones:
"Opciones de desarrollo" > "Depuración" > "Depuración USB"
para activar el modo de depuración cuando el dispositivo este conectado por USB.
Android Debug Bridge (ADB)
La herramienta “adb" es esencial para depurar, manejar y personalizar dispositivos Android. "adb" son las siglas de Android Debug Bridge. Esta herramienta esta disponible a partir de Ubuntu 14.04 como binario precompilado. Puedes instalarla usando este comando:
$ sudo apt-get install android-tools-adb
También se podría compilar descargando los fuentes del Android Open Source Project (AOSP), aunque no es el objetivo de este documento.
Detección del dispositivo
Cuando conectes el dispositivo Android por USB a tu PC, podrás verificar que tu dispositivo esta conectado ejecutando el comando:
$ adb devices
Desde Android 4.2.2 en adelante se introdujo una nueva caracteristica de seguridad. Debes confirmar que tu dispositivo android esta conectado a un PC autorizado antes de que se permita ningún dialogo. Por tanto, si es la primera vez que lanzas este comando, verás esta salida:
List of devices attached d1548bec06f16120 unauthorized
En este caso, en el dispositivo de Android saldrá una ventana de dialogo preguntando si quieres aceptar la clave RSA que acepte la depuración del dispositivo a través del PC desde el que has conectado. Este mecanismo de seguridad protege al dispositivo frente a ataques remotos, porque asegura que el debugging USB y otros comandos adb no puedan ser ejecutados a menos que seas capaz de desbloquear el dispositivo confirmando este dialogo.
Si no es la primera vez que lanzas el comando, verás esta salida, sin mas:
$ adb devices List of devices attached 0123456789ABCDEF device
El problema
El fabricante protege la tablet y no podremos lanzar este comando, ya que genera error:
$ adb root adbd cannot run as root in production builds
El objetivo de este post es encontrar una solución a este problema, así que vamos a analizar este error. Lo primero es buscar en los fuentes de Android (proyecto AOSP) el string del error. Encontramos el mensaje en este fichero:
$ vi aosp/system/core/adb/services.c property_get("ro.debuggable", value, ""); if (strcmp(value, "1") != 0) { snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n"); writex(fd, buf, strlen(buf)); adb_close(fd); return; }
Como vemos, el método "property_get" lee el valor de la propiedad "ro.debuggable" y si su valor no es 1, muestra el error "adbd cannot run as root in production builds".
Buscando mas a fondo en los fuentes de Android, encontramos que la función property_get esta definida en este fichero:
$ vi aosp/system/core/libcutils/properties.c int property_get(const char *key, char *value, const char *default_value) { int len; len = __system_property_get(key, value); if(len > 0) { return len; } if(default_value) { len = strlen(default_value); memcpy(value, default_value, len + 1); } return len; }
Por el nombre del método __system_property_get, deducimos que se trata de una propiedad de la partición "system" de Android. Por tanto, el primer objetivo será obtener el contenido de la partición system de la tablet, para modificar su fichero de propiedades (build.prop), añadiendo en su interior la propiedad ro.debuggable=1.
La herramienta rkflashtool
La herramienta "rkflashtool" permite leer/escribir el contenido de cualquier partición de la tablet. Para instalar esta herramienta, lo primero es instalar las dependencias de Ubuntu necesarias para su compilación:
$ sudo apt-get install build-essential libusb-1.0-0-dev
Descarga la herramienta:
$ git clone https://github.com/linux-rockchip/rkflashtool
Compila e instala:
$ cd rkflashtool $ make $ sudo cp rkflashtool rkcrc rkunpack rkunsign /usr/local/bin
Despues arrancas la tablet en modo bootloader:
$ adb reboot bootloader
Y ya puedes obtener el layout de la memoria flash con este comando:
$ rkflashtool p > parameters.txt
En mi caso concreto, tengo este layout:
NAME OFFSET NSECTORS misc 0x00002000 0x00002000 kernel 0x00004000 0x00006000 boot 0x0000a000 0x00006000 recovery 0x00010000 0x00010000 backup 0x00020000 0x00020000 cache 0x00040000 0x00040000 metadata 0x00080000 0x00002000 kpanic 0x00082000 0x00002000 system 0x00084000 0x00200000 vendor 0x00284000 0x00002000 userdata 0x00286000 -
Ahora puedo leer el contenido de cualquier partición con este comando:
$ rkflashtool r <nombre_particion> > <nombre_particion>.img
Y puedo grabar el contenido de cualquier partición con este comando:
$ rkflashtool w <nombre_particion> <nombre_particion>.img
Añadir ro.debuggable=1
Para obtener el contenido de la partición de system hacemos:
$ sudo rkflashtool r system > system.img
Vemos que system.img es la imagen de un sistema de ficheros en formato ext4:
$ file system.img system.img: Linux rev 1.0 ext4 filesystem data, UUID=da594c53-9beb-f85c-85c5-cedf76546f7a, volume name "system" (extents) (large files)
Podemos montar esta partición system.img en modo loopback:
$ sudo mount -o loop system.img /media/removable
Cambiar el contenido del fichero build.prop:
$ vi /media/removable/build.prop ro.debuggable=1
Tras desmontar la partición:
$ sudo umount /media/removable
Vuelve a grabar el contenido con este comando:
$ rkflashtool w system < system.img
Sin embargo, el problema sigue manifestándose:
$ adb root adbd cannot run as root in production builds
Con esto deducimos que el cliente "adb" conecta con un servicio de la tablet (llamado adbd), que se encarga de decodificar el contenido del fichero build.prop y proporcionar una respuesta al cliente "adb". Si el fichero build.prop tiene la propiedad ro.debuggable=1 y sigue sin funcionar, debe ser porque este servicio adbd esta capado, y siempre devuelve error, independientemente del contenido del fichero de propiedades build.prop.
La herramienta imgrepackerrk
Para solucionar este problema intentaremos reemplazar el adbd capado por uno no-capado. Para ello lo primero es averiguar donde está almacenado el adbd capado. Tras buscar adbd en la partición system, no lo encontramos. Podría estar almacenado en la partición de boot, así que lo primero es leer su contenido con la herramienta rkflashtool:
$ rkflashtool r boot > boot.img
Vemos que la imagen de boot (boot.img) no se puede montar, pues se trata de un fichero de datos, no de un sistema de ficheros:
$ file boot.img boot.img: data
Necesitamos una herramienta para extraer el contenido de esta partición. En este foro de xda-developers:
http://forum.xda-developers.com/showthread.php?t=2257331
encontramos la herramienta "imgrepackerrk" (versión 104). Esta utilidad permite desempaquetar/reempaquetar imágenes de boot.img.
Tras descargar la herramienta, la instalámos en nuestra máquina, copiandola en /usr/local/bin:
$ cp imgrepackerrk /usr/local/bin $ chmod 755 /usr/local/bin/imgrepackerrk
Usamos esta herramienta para extraer el contenido de la imagen boot.img:
$ imgrepackerrk boot.img
Una vez desempaquetado el contenido de boot.img, buscamos el servicio adbd en su interior:
$ find boot.img.dump/ | grep adbd boot.img.dump/ramdisk.dump/sbin/adbd
Efectivamente, el servicio se encuentra dentro de esta partición. Este fichero es el que creemos que está capado, y hay que reemplazar por un servicio adbd que no este capado.
El servicio adbd no-capado
El servicio adbd no-capado lo vamos a obtener descargando el paquete adbd-Insecure-v2.00.apk desde esta URL:
http://forum.xda-developers.com/showthread.php?t=1687590
El checksum del archivo descargado es este:
$ md5sum adbd-Insecure-v2.00.apk df9ef24983dd29530bbbe2a7caeb35d8 adbd-Insecure-v2.00.apk
Descomprime su contenido:
$ unzip adbd-Insecure-v2.00.apk
Dentro de este apk encontraremos el nuevo adbd no-capado, que curiosamente tiene una extensión .png (normalmente usada para fotos), aunque vemos que en realidad no se trata de una foto, se trata de un binario ejecutable:
$ file ./assets/adbd.21.png ./assets/adbd.21.png: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, stripped
Reemplaza este archivo adbd.21.png por el adb capado:
$ cp ./assets/adbd.21.png boot.img.dump/ramdisk.dump/sbin/adbd
Reempaqueta la imagen boot.img con el nuevo servicio adbd no-capado:
$ imgrepackerrk boot.img.cfg
El comando anterior reempaqueta la imagen boot.img con un adbd no-capado que esperamos que resuelva nuestro problema inicial.
Graba el nuevo boot.img en la flash:
$ rkflashtool w boot < boot.img
Disfrutar del resultado
Reinicia la tablet. Si todo ha ido bien podrás disfrutar de tu tablet rooteada:
# adb root adbd is already running as root # adb remount remount succeeded