Android — Arquitectura de android 01

CrhystamiL
6 min readNov 19, 2019

--

En esta sección presentaremos la plataforma android desde un punto de vista de la arquitectura. Hablaremos de las siguientes áreas.

  • Arquitectura de seguridad de android.
  • Estructura de las aplicaciones android
  • Inter-process communication (IPC)

Visita la documentación oficial de android para mas detalles sobre la plataforma android. https://developer.android.com/index.html

Arquitectura de seguridad de android

Android es una plataforma de código abierto basado en Linux desarrollado por google. Android se compone de varias capas diferentes, cada capa define interfaces y ofrece servicios específicos.

En el nivel mas bajo, android se basa en una variación del Kernel de Linux.

En la parte superior del Kernel, la capa de abstracción del hardware (Hardware Abstraction Layer HAL) define una interfaz estándar para interactuar con los componentes de hardware integrados, muchas implementaciones de HAL se empaquetan en módulos compartidos que el sistema llama cuando es necesario.

Esta es la base para permitir que las aplicaciones interactúen con los dispositivos del hardware — Por ejemplo, permite a una aplicación del teléfono usar el micrófono y el altavoz.

Las aplicaciones android generalmente están escritas en java y compiladas en Dalvik bytecode, que es algo diferente del bytecode tradicional de java. Dalvik bytecode se crea compilando el código java en archivos .class para luego convertirlo en bytecode JVM en formato .dex de dalvik.

La versión actual de android ejecuta código bytecode sobre Android Runtime (ART). ART es el sucesor en tiempo de ejecución de android, la diferencia entre Dalvik y ART es la forma que ejecuta los bytecodes.

En Dalvik, los bytecode se traducen en código maquina en tiempo de ejecución, un proceso conocido como compilación just-in-time (JIT). La compilación JIT afecta negativamente el rendimiento: la compilación debe ser ejecutada cada vez que la app es ejecutada. Para mejorar el rendimiento, ART introdujo la compilación ahead-of-time (AOT). Como su nombre indica, las aplicaciones se pre-compilan antes de ejecutarse por primera vez. Este código maquina pre-compilado se utiliza para todas las ejecuciones posteriores.

Las aplicaciones android no tienen acceso directo a los recursos de hardware, cada aplicación corre en su propio sandbox (caja de arena). Esto permite un control preciso sobre los recursos y las aplicaciones. Por ejemplo, una aplicación que falla no afecta a otras aplicaciones que se ejecuten en el dispositivo.

Al mismo tiempo, el tiempo de ejecución de android controla la cantidad máxima de recursos del sistema asignados a las aplicaciones, evitando así que cualquier aplicación monopolice demasiado los recursos.

Lectura recomendada:

Usuarios y grupos de android

Aunque el Sistema Operativo (SO) de android es basado en Linux, este no implementa cuentas de usuarios de la misma forma que lo hacen los sistemas UNIX.

En android el soporte multi-usuario para las aplicaciones es un sandbox con algunas excepciones. Cada aplicación se ejecuta como si estuviera bajo un usuario, aislado de otras aplicaciones y del resto del sistema operativo.

El archivo android_filesystem_config.h incluye una lista predefinida de usuarios y grupos a los que se asignan los procesos del sistema. Los UIDs (ID de usuario) para otras aplicaciones se agregan a medida que se instalen.

#define AID_ROOT             0  /* traditional unix root user */
#define AID_SYSTEM 1000 /* system server */
#...
#define AID_SHELL 2000 /* adb and debug shell user */
#...
#define AID_APP 10000 /* first app user */
...

Cifrado del dispositivo Android

Android admite cifrado del dispositivo desde Android 2.3.4 y ha sufrido grandes cambios desde entonces. Google impuso que todos los dispositivos con android 6.0 o superiores tengan el soporte de cifrado de almacenamiento. Aunque algunos dispositivos están exentos ya que afectaría su rendimiento.

Cifrado de disco completo

Android 5 y superiores admite cifrado de disco completo. Este cifrado utiliza una clave única, protegida por la contraseña del dispositivo. Este tipo de cifrado ahora se considera obsoleto y el cifrado basado en archivos debe usarse siempre que sea posible.

El cifrado de disco completo tiene algunos inconvenientes, como no poder recibir llamadas o no tener alarmas operativas después de un reinicio si el usuario no ingresa su contraseña.

Adiantum

Se utiliza AES en la mayoría de los dispositivos android modernos para el cifrado de almacenamiento. Actualmente AES se ha convertido en un algoritmo muy utilizado, se proporcionaron operaciones de cifrado y descifrado, aceleradas por hardware.

Algunos dispositivos con procesadores ARM cotex A7, Android GO y otros de gama baja no tienen AES acelerado por hardware.

Adiantum es una composición de otros cifrados:

  • NH
  • POLY1350
  • XChaCha12
  • AES-256

Adiantum es un nuevo cifrado pero es seguro mientras ChaCha12 y AES-256 se consideren seguros.

Aplicaciones android

Las aplicaciones en android interactuan con los servicios del sistema a través de un framework, una capa de abstracción que ofrece la API de java. La mayoría de estos servicios se invocan mediante métodos de java normales y se traducen a llamadas a la IPC, estos servicios del sistema que se ejecutan en segundo plano.

Estos incluyen:

  • Conectividad (WiFi, Bluetooth, NFC, etc)
  • Archivos/Carpetas
  • Camara
  • Geolocalizacion (GPS)
  • Microfono

El framework también ofrece funciones de seguridad como el cifrado.

UID/GID de Linux para aplicaciones

Android aprovecha la gestión de usuarios de Linux para aislar aplicaciones. Android crea un único UID para cada aplicación y ejecuta la aplicación en un proceso separado, consecuentemente cada aplicación puede acceder solo a sus propios recursos. Esta protección es forzada por el Kernel de Linux de android.

A las aplicaciones se les asigna un UID en el rango de 10000 a 99999. Las aplicaciones reciben un nombre de usuario basados en el UID. Por ejemplo: la app con el UID 10188 recibe el nombre de usuario u0_a188. Si se otorga los permisos que solicito una aplicación, el ID del grupo correspondiente se agrega al proceso de la aplicación.

Por ejemplo: el ID de la aplicación es 10188, entonces este pertenece al grupo 3003(inet). Este grupo esta relacionado con el permiso de INTERNET. la salida del comando id seria:

$ id
uid=10188(u0_a188) gid=10188(u0_a188) groups=10188 (u0_a188), 3003 (inet),9997(everybody),50188(all_a188)Context=u:r:untrusted_app:s0
:c512,c768

Los ID de grupo y permisos se definen en el archivo

framework/base/data/etc/platform.xml

Sandbox de aplicaciones

Las aplicaciones son ejecutadas en un Sandbox(cada de arena, aisladas), que separa los datos de la aplicación y el código de ejecución de otras aplicaciones. Esta separación agrega una capa de seguridad.

La instalación de una nueva aplicación crea un nuevo directorio con el nombre del paquete, que reside en la siguiente ruta /data/data/[package-name] . Esta carpeta mantiene los datos de la aplicación. Los permisos del directorio de linux se configuran de modo que el directorio se puede leer y escribir solo con el UID de la aplicación.

Algunos desarrolladores desean que sus aplicaciones compartan información. Cuando dos aplicaciones se firman con el mismo certificado y comparten explicita-mente el mismo ID de usuario (debe ser un SharedUserId declarado en el archivo AndroidManifest.xml), cada aplicación puede acceder a los datos de la otra.

Zygote

El proceso Zygote se inicia durante la inicialización de android. Zygote es un servicio del sistema que inicia las aplicaciones. El proceso de zygote es un proceso base que contiene todas las librerías que una aplicación necesita. Al iniciarse zygote este abre el socket /dev/socket/zygote y escucha todas las conexiones de los clientes locales. Cuando recibe una conexión este proceso carga y ejecuta el código de la aplicación.

Ciclo de vida de una aplicación (App lifecycle)

En android, el sistema operativo controla la vida útil de un proceso de aplicación. Se crea un nuevo proceso de linux cuando se inicia un componente de la aplicación y la misma aplicación todavía no tiene otros componentes en ejecución.

Android puede matar este proceso cuando este ultimo ya no es necesario o cuando sea necesario recuperar memoria para ejecutar aplicaciones mas importantes.

La decisión de matar un proceso esta relacionada principalmente con el estado de la interacción del usuario con el proceso. En general los procesos puede estar en uno de los cuatro estados.

  • Foregound process
  • Visible process
  • Service process
  • Cache process

--

--

CrhystamiL

CEH, CyberSecurity Researcher,Ethical Hacker, GNU/Linux Lover.