jueves, 4 de abril de 2013

Destripando framework2.odex en Android

Hace algunas semanas estuve programando una pequeña herramienta en Python para ayudarme a crackear los hashes de Android. Durante su desarrollo, me di cuenta que los crackeos en hashes de móviles Samsung nunca funcionaban, además de que tenían un aspecto algo diferente (más corto) al de otros fabricantes. Como ya sabéis, los fabricantes de teléfonos móviles realizan modificaciones sobre el sistema operativo original de Google para adaptarlo a su hardware, mejorar rendimiento, o cualquier otra cosa que se les ocurra, por lo que no era descabellado pensar que Samsung hubiera realizado alguna modificación en el algoritmo de hashing. Por desgracia, no encontré por ninguna parte el código fuente propias de Samsung, así que no quedó más remedio que rebuscar un poco.

En primer lugar, necesitamos saber en que parte del código se realiza la acción del Hashing. En el caso de Android, tenemos la suerte de que el código fuente está disponible, así que una búsqueda rápida puede ayudarnos a obtener unos cuantos candidatos.


De los ficheros obtenidos, parece que uno con nombre "LockPatternUtils.java" tiene toda la pinta de poder contener el código que buscamos. Si accedemos a su código fuente y buscamos cadenas como "hash" o similares, y navegamos un poco por el código, acabamos encontrando funciones como "patternToHash()" o "passwordToHash()", que parecen ser las encargadas de generar los hashes de contraseñas y patrones y guardar el resultado en los ficheros "gesture.key" y "password.key" respectivamente.


Como podéis ver, este es el algoritmo habitual, el que coge la contraseña, la concatena con un salt y realiza dos hashes, un SHA-1 y un MD5, que luego concatena y guarda en el fichero. Viendo el path del fichero en el código fuente podemos ver que se encuentra dentro del framework base de Android, así que ahora solo necesitamos un Samsung con ROM original y descargar este fichero a ver que han modificado:

$ adb pull /system/framework .

Concretamente, el fichero que nos interesa es "framework2.odex", pero necesitamos bajarnos todo el framework porque la herramienta smali lo necesita para poder traducir este ODEX a un fichero DEX. El proceso parece un poco confuso, pero básicamente lo que hacemos es obtener el código smali del ODEX, y posteriormente volvemos a montar un DEX para luego convertirlo en JAR con dex2jar ¿Por qué? Porque el JAR podemos abrirlo con cualquier decompilador de Java como JD-GUI, mientras que el código smali puede ser un poco más complicado de leer. Veamos como lo haríamos:

$ java -jar baksmali-1.4.2.jar -a 15 -x framework2.odex -d framework -o framework2
$ java -jar smali-1.4.2.jar --api-level 15 -o classes.dex framework2
$ d2j-dex2jar.sh classes.dex

Ahora que ya tenemos el fichero "classes-dex2jar.jar" (el nombre lo pone la herramienta dex2jar por si misma), podemos abrirlo con nuestro decompilador de java favorito, en mi caso JD-GUI, y buscar la función passwordToHash() que comentábamos antes a ver que ha cambiado:


Pues... parece que sí que la cosa cambia un poco con respecto a la función original de Android. Para empezar no utiliza para nada el algoritmo MD5, sino únicamente SHA-1. En segundo lugar, no realiza una única ronda, sino que realiza 1024 rondas a las que le va añadiendo en cada una el número de iteración del bucle antes de volver a aplicar el algoritmo de hash.

Ahora solo queda programarlo y ya podemos crackear estos hashes, aunque como podéis imaginar será mucho más lento, debido a las múltiples rondas que se deben realizar para cada prueba. Un punto positivo para Samsung en este aspecto (a priori, que luego cuando tocas algoritmos de cifrado... nunca se sabe como puedes afectar a su seguridad).

6 comentarios :

ivan dijo...

Muy interesante !!

Diego dijo...

Que tal! Muy bueno el post, interesante de hecho. Voy a ver si pruebo algunas cosas con android. Una consulta sobre el codigo de samsung, y disculpa mi ignorancia, pero, el return arrayOfBytes1 que está debajo del while(true) no hace que salga antes de crear todo el hash?
Saludos!

Jose Selvi dijo...

@Diego: Muy buena observación!

Efectivamente, el código tal cual como está no generaría nunca ningún hash, pero ten en cuenta que hemos obtenido este código de decompilar el código smali, que aunque sea de mucho más alto nivel de ensamblador, el decompilador le echa algo de "imaginación" para reconstruir el código Java.

No lo tengo delante ahora, pero seguramente si le pegas un vistazo al código Smali, este "return" estará dento del "if" anterior al "while", después de asignar el array de bytes a null.

Diego dijo...

Gracias por responder Jose! Al no tener experiencia ni siquiera lo supuse, jeje. Voy a empezar con el samsung de mi novia.
Un abrazo!

Diego.

Gabriel Pozo dijo...

Interesante el post, gracias

Anónimo dijo...

Excelente el post,interesante saber como se generan los hashes de telefonos Samsung.

Saludos desde Colombia.