Internals

Archivos DEX (Dalvik Executable): La Tabla de Tipos

Seguimos desenmarañando la estructura de los archivos Dex y ahora nos toca la tabla de tipos, es decir, los diferentes tipos de datos que utiliza nuestra aplicación a analizar. En este caso al igual que hicimos con la tabla de strings, obtenemos el offset y numero de elementos en la tabla de tipos de la cabecera. En el caso que estamos analizando la tabla de tipos comienza en 0x000001AC y tiene 28 (0x0000001C) elementos. Recorriendo de 4 en 4 bytes obtenemos las posiciones en la tabla de strings que identifican los tipos a usar: 2,7,8,9,10..

  1. elemento 2 de la lista de STRINGS: I
  2. elemento 7 de la lista de STRINGS: Landroid/app/Activity;
  3. elemento 8 de la lista de STRINGS: Landroid/os/Bundle;
  4. elemento 9 de la lista de STRINGS: Landroid/text/Editable;
  5. elemento 10 de la lista de STRINGS: Landroid/view/View$OnClickListener;
  6. elemento 11 de la lista de STRINGS: Landroid/view/View;
  7. elemento 12 de la lista de STRINGS: Landroid/widget/Button;
  8. elemento 13 de la lista de STRINGS: Landroid/widget/EditText;
  9. elemento 14 de la lista de STRINGS: Landroid/widget/TextView;
  10. elemento 15 de la lista de STRINGS: Lcom/marakana/NDKDemo$1;
  11. elemento 16 de la lista de STRINGS: Lcom/marakana/NDKDemo;
  12. elemento 17 de la lista de STRINGS: Lcom/marakana/NativeLib;
  13. elemento 18 de la lista de STRINGS: Lcom/marakana/R$attr;
  14. elemento 19 de la lista de STRINGS: Lcom/marakana/R$drawable;
  15. elemento 20 de la lista de STRINGS: Lcom/marakana/R$id;
  16. elemento 21 de la lista de STRINGS: Lcom/marakana/R$layout;
  17. elemento 22 de la lista de STRINGS: Lcom/marakana/R$string;
  18. elemento 23 de la lista de STRINGS: Lcom/marakana/R;
  19. elemento 24 de la lista de STRINGS: Ldalvik/annotation/EnclosingClass;
  20. elemento 25 de la lista de STRINGS: Ldalvik/annotation/EnclosingMethod;
  21. elemento 26 de la lista de STRINGS: Ldalvik/annotation/InnerClass;
  22. elemento 27 de la lista de STRINGS: Ldalvik/annotation/MemberClasses;
  23. elemento 28 de la lista de STRINGS: Ljava/lang/CharSequence;
  24. elemento 29 de la lista de STRINGS: Ljava/lang/Integer;
  25. elemento 30 de la lista de STRINGS: Ljava/lang/Object;
  26. elemento 31 de la lista de STRINGS: Ljava/lang/String;
  27. elemento 32 de la lista de STRINGS: Ljava/lang/System;
  28. elemento 37 de la lista de STRINGS: V

Estos strings usan una sintaxis concreta y pueden traducirse a una forma mas común de definir los tipos mediante la siguiente tabla.

Syntax Meaning
V void
Z boolean
B byte
S short
C char
I int
J long
F float
D double
Lnombre/completo/Clase; la clase nombre.completo.Clase
[descriptor Array de elementos descriptor, es posible crear arrays de arrays, con limite de profundidad 255
Ejemplo: [I ~ array de ints (int[])

Por tanto, la tabla, nos quedaria de esta manera:

  1. int
  2. android.app.Activity
  3. android.os.Bundle
  4. android.text.Editable
  5. android.view.View.OnClickListener
  6. android.view.View
  7. android.widget.Button
  8. android.widget.EditText
  9. android.widget.TextView
  10. com.marakana.NDKDemo.1
  11. com.marakana.NDKDemo
  12. com.marakana.NativeLib
  13. com.marakana.R.attr
  14. com.marakana.R.drawable
  15. com.marakana.R.id
  16. com.marakana.R.layout
  17. com.marakana.R.string
  18. com.marakana.R
  19. dalvik.annotation.EnclosingClass
  20. dalvik.annotation.EnclosingMethod
  21. dalvik.annotation.InnerClass
  22. dalvik.annotation.MemberClasses
  23. java.lang.CharSequence
  24. java.lang.Integer
  25. java.lang.Object
  26. java.lang.String
  27. java.lang.System
  28. void

Otro recurso mas, que sera utilizado junto a la tabla de strings para desensamblar el resto de estructuras de nuestra aplicación.

Archivos DEX (Dalvik Executable): La Tabla de Strings

La tabla strings, es una estructura que contiene las posiciones de los recursos string que utiliza nuestra aplicación. En esta lista de strings tendremos desde nombres de clases, métodos, variables o constantes que nos indicaran el tipo de los datos. Es una lista ordenada ya que desde otras estructuras se hará referencia a los strings en función de su posición en la lista. Es decir, en el proceso de compilación, se extraen los strings de todas las estructuras y código, se eliminan duplicados y se meten en una lista ordenada, por lo que a partir de entonces, ahí donde había un string ahora hay un entero que hace referencia a la posición del string en la lista. Con esto se consigue reducir el tamaño de la aplicación evitando la redundancia de recursos.

Para entenderlo mejor, a partir de este momento vamos a desensamblar, paso a paso, un archivo .dex de ejemplo que hemos obtenido a partir de este ejemplo http://marakana.com/forums/android/examples/49.html que es pequeño y usa la NDK (de cara a ser un ejemplo relativamente completo).

Analizando la cabecera como explicamos en el artículo anterior obtenemos el offset o desplazamiento desde el inicio del fichero donde empieza la tabla de posiciones de los strings, y el numero de strings. Por tanto obtenemos que la tabla de strings empieza en la posición 0×00000070 y que tiene 79 (0x0000004F) elementos. Por tanto deberemos recorrer el archivo desde la posición 0×00000070 en bloques de 32bist, 79 veces para obtener la posición de los 79 strings.

En el ejemplo de la imagen superior recorremos los tres primeros strings. La estructura de cada string es, un byte que indica la longitud del string y a continuación el string, por tanto, el primer string esta en la posición 0x0000084E, su longitud es de 0×08 caracteres y su valor es “<clinit>”. El segundo string esta en la posición 0×00000858, es de longitud 0×06 y valor “<init>”, el tercero esta en la posición 0×00000860 es de longitud 0×01 y valor “I”. Seguiríamos así con los 79 strings, con lo que en el ejemplo de la imagen obtendríamos la siguiente lista.

  1. <clinit>
  2. <init>
  3. I
  4. III
  5. IL
  6. L
  7. LI
  8. Landroid/app/Activity;
  9. Landroid/os/Bundle;
  10. Landroid/text/Editable;
  11. Landroid/view/View$OnClickListener;
  12. Landroid/view/View;
  13. Landroid/widget/Button;
  14. Landroid/widget/EditText;
  15. Landroid/widget/TextView;
  16. Lcom/marakana/NDKDemo$1;
  17. Lcom/marakana/NDKDemo;
  18. Lcom/marakana/NativeLib;
  19. Lcom/marakana/R$attr;
  20. Lcom/marakana/R$drawable;
  21. Lcom/marakana/R$id;
  22. Lcom/marakana/R$layout;
  23. Lcom/marakana/R$string;
  24. Lcom/marakana/R;
  25. Ldalvik/annotation/EnclosingClass;
  26. Ldalvik/annotation/EnclosingMethod;
  27. Ldalvik/annotation/InnerClass;
  28. Ldalvik/annotation/MemberClasses;
  29. Ljava/lang/CharSequence;
  30. Ljava/lang/Integer;
  31. Ljava/lang/Object;
  32. Ljava/lang/String;
  33. Ljava/lang/System;
  34. NDKDemo.java
  35. NativeLib.java
  36. R.java
  37. TextView01
  38. V
  39. VI
  40. VL
  41. accessFlags
  42. add
  43. app_name
  44. attr
  45. buttonCalc
  46. drawable
  47. findViewById
  48. getText
  49. hello
  50. helloText
  51. icon
  52. id
  53. layout
  54. loadLibrary
  55. main
  56. name
  57. nativeLib
  58. ndk_demo
  59. onClick
  60. onCreate
  61. outText
  62. parseInt
  63. res
  64. result
  65. savedInstanceState
  66. setContentView
  67. setOnClickListener
  68. setText
  69. string
  70. textOut
  71. this
  72. this$0
  73. toString
  74. v
  75. v1
  76. v2
  77. value
  78. value1
  79. value2

A partir de ahora las siguientes estructuras que vayamos desensamblando harán referencia a esta lista de strings.

Archivos DEX (Dalvik Executable): La Cabecera

La cabecera es como cabe de esperar, una de las partes mas importantes de la estructura el archivo .dex. Contiene el magic que nos permite identificar el formato de archivo, además de diferentes chechsums y hashes para comprobar la integridad del propio archivo. Pero lo que es mas importante, en la cabecera se encuentra el “mapa” para entender y descomponer el formato .dex en sus diferentes partes, ya que contiene una lista con los offsets y longitud de las diferentes parte de el archivo que comentábamos en el artículo anterior.

  • Tabla con las posiciones de los Strings
  • Tabla con las posiciones de los Tipos
  • Tabla con las posiciones de las estructuras/Prototipos de los métodos
  • Tabla con las posiciones de las Propiedades de las clases o Campos de los métodos
  • Tabla con las posiciones de los Métodos
  • Tabla con las posiciones de las Clases
  • Datos



Name Format Description
magic ubyte[8] Este valor es el que identifica el tipo de fichero.
checksum uint Checksum (adler32) calculado en base a todo el fichero, menos magic y checksum.
signature ubyte[20] Firma HashSHA-1 de todo el fichero menos magic, checksum y la propia firma.
file_size uint Tamaño de todo el fichero incluida la cabecera (en bytes).
header_size uint Tamañode la cabecera (en bytes). Actualmente siempre toma el valor de 0×70 (112)
endian_tag uint Nos indica que tipo de formato endian usa el fichero. Importante de cara a interpretar los valores de los datos del archivo, pero defecto es litle-endian. [aclaración]
link_size uint Indicael tamaño de la sección de enlace (link section) o 0, si elfichero es enlazado de forma dinámica.
link_off uint Desplazamientoal comienzo de la sección de enlace desde el inicio del ficheroo 0 si link_size == 0.
map_off uint Desplazamientoal map_list en caso que éste exista o 0 en caso contrario. Elmap_list es una lista con todo el contenido del fichero. Estaestructura de datos puede contener datos redundantes, pero laintención de la misma es el poder recorrer el contenido delfichero de una forma más cómoda. Esta lista está ordenada.
string_ids_size uint Númerode elementos en la lista de strings.
string_ids_off uint Desplazamientoa la lista de strings o 0 en caso que dicha lista este vacía,circunstancia que raramente se va a dar.
type_ids_size uint Númerode elementos en la lista de tipos (type).
type_ids_off uint Desplazamientoa la lista de tipos o 0 en caso que dicha lista este vacía. Casoque raramente también se dará.
proto_ids_size uint Númerode elementos en la lista de prototipos.
proto_ids_off uint Desplazamientoa la lista de prototipos. 0 en caso que dicha lista este vacía.De nuevo, situación que raramente se dará.
field_ids_size uint Númerode elementos en la lista de campos.
field_ids_off uint Desplazamientoa la lista de campos o 0 en caso que dicha lista esté vacía.
method_ids_size uint Númerode elementos en la lista de métodos.
method_ids_off uint Desplazamientoa la lista de métodos. 0 si la lista está vacía.
class_defs_size uint Númerode elementos en la lista de clases.
class_defs_off uint Desplazamientoa la lista de clases. 0 en caso dicha lista este vacía,situación poco probable.
data_size uint Tamañoen bytes de la sección de datos. Debe ser un número parmúltiplo del tamaño de un uint (sizeof(uint)).
data_off uint Desplazamientoa la sección de datos.


ENDIAN_CONSTANT y REVERSE_ENDIAN_CONSTANT

En caso de que el valor se el campo endian_tag sea igual a REVERSE_ENDIAN_CONSTANT (0×78563412), consideraremos que el archivo esta en formato litle-endian, lo cual es el estandar y lo mas común. A pesar de ello, es posible usar otras configuraciones, tipo big-endian, en tal caso el campo endian_tag tomara el valor ENDIAN_CONSTANT (0×12345678).

Fuente: http://www.netmite.com/android/mydroid/dalvik/docs/dex-format.html

Archivos DEX (Dalvik Executable): Introducción

En los entornos Java estándar, el código fuente de Java es compilado en bytecode de Java, y almacenado en archivos .class. Los archivos .class son leídos por la máquina virtual Java en tiempo de ejecución. Cada clase en tu código Java se traducirá en un archivo .class. Esto significa que si tienes, por ejemplo, un archivo .java (código fuente) que contiene una clase pública, una clase interna estática, y tres clases anónimas, el proceso de compilación (javac) nos generará 5 archivos .class.

En la plataforma Android, el código fuente de Java también se compila en archivos .class. Pero después de generar los archivos .class, mediante la herramienta dx son convertidos a un único archivo dex (Dalvik Executable). Mientras que un archivo .class contiene una sola clase, un archivo .dex contiene múltiples clases. Es el archivo .dex el que se ejecuta en la máquina virtual Dalvik.

El archivo .dex ha sido optimizado para el mínimo consumo de memoria y el diseño esta condicionado por la reutilización de datos. El siguiente diagrama compara el formato de los archivos .class utilizado por la JVM con el formato de .dex utilizado por la máquina virtual Dalvik.

.jar vs .dex

A grandes rasgos las estructura de un Archivo .dex consta de las siguientes partes:

  • Cabecera
  • Tabla con las posiciones de los Strings
  • Tabla con las posiciones de los Tipos
  • Tabla con las posiciones de las estructuras/Prototipos de los métodos
  • Tabla con las posiciones de las Propiedades de las clases o Campos de los métodos
  • Tabla con las posiciones de los Métodos
  • Tabla con las posiciones de las Clases
  • Datos

Salvo la tabla de Strings (que es a la que hacen referencia todas las tablas ya que es en esta parte donde se almacenan todos los nombre de clases, métodos, funciones, variable y tipos de datos), el resto sigue un orden jerárquico inverso, es decir, si quisiéramos desensamblar el archivos dex, tras obtener el listado de Strings, obtendríamos el listado de Clases, sus métodos, sus propiedades y campos de los métodos, la estructura de dichos métodos – que relaciona métodos y campos – y por ultimo los tipos, que nos indicaría los tipos de los campos de los métodos y los tipos que devuelven los métodos. Es decir, es una estructura relacional, que tiene como objetivo el reaprovechamiento máximo de la información, evitando redundancias y así conseguir un formato optimo para terminales móviles.

Como he indicado, son tablas donde se indica la posición donde esta la información que compone dicha tabla, normalmente mediante un Offset y opcionalmente una longitud. Estos datos junto con el código maquina están en la sección de datos.

En próximos artículos iremos desgranando con mas detalle, cada parte de la estructura del formato Dalvik Executable.

Fuente 1:http://davidehringer.com/software/android/The_Dalvik_Virtual_Machine.pdf
Fuente 2:http://www.scribd.com/doc/17194679/DalvikVMInternals#

 Scroll to top