¿Qué es Smali?
Las aplicaciones Android contienen ficheros .dex (Dalvik EXecutable). Estos ficheros se pueden decompilar para obtener un código de bajo nivel llamado Dalvik Bytecode. Utilizando smali/baksmali (ensamblador/desensamblador) se puede obtener una representación en un lenguaje de bajo nivel con el que se puede trabajar más fácilmente, al cual llamaremos código Smali. Hoy en día, apktool ya incorpora smali/baksmali, por lo que será suficiente con desempaquetar el fichero .apk con apktool para obtener el código Smali.

El código Smali recuerda al código del lenguaje ensamblador, pero en este caso se ven los nombres de las clases de Java y Android, así como los nombres de los métodos. Para obtener más información sobre la sintaxis de los métodos, clases, tipos primitivos y campos de clases, se puede consultar el siguiente enlace https://github.com/JesusFreke/smali/wiki/TypesMethodsAndFields. A modo de guía rápida para consulta de los nombres de las operaciones propias de Smali, se puede consultar la lista de opcodes de dalvik.
Por tanto, y a modo de resumen, Smali es una representación en lenguaje de bajo nivel del código de bajo nivel Dalvik, el cual está contenido en los ficheros .dex que contienen todo el código de la aplicación (salvo el código de las librerías de código nativo, los ficheros .so), los cuales forman parte del fichero de aplicación .apk.
¿Cómo parchear una aplicación Android?
El flujo de trabajo general para parchear una aplicación Android es:
- Desempaquetar el fichero .apk y obtener una representación en código Java
- Identificar la parte o partes del código Smali a modificar
- Realizar las modificaciones necesarias
- Reempaquetar la aplicación y firmarla
- Instalar el fichero .apk modificado
- Probar las modificaciones
En este caso, vamos a resolver un crackme de Android sencillo mediante una modificación del código Smali. El enlace a la aplicación es Crackme.
El primer paso es desempaquetar la aplicación utilizando la herramienta apktool y obtener una representación aproximada en código Java (la conversión de Java a Dalvik supone una pérdida de información que imposibilita obtener un código Java directamente compilable a partir de su código Dalvik asociado). Para ello utilizaremos el siguiente comando:
apktool d Crackme03.apk && d2j-dex2jar Crackme03.apk

El resultado será la creación de una carpeta con el mismo nombre del fichero apk que contendrá una serie de subcarpetas con el contenido de la aplicación, y entre ellas, una llamada smali que contendrá el código Smali.

Ademas, al mismo nivel que el fichero .apk, aparecera un nuevo fichero JAR llamado nombrecrackme-dex2jar.jar que contiene los ficheros .class de las distintas clases de la aplicación.

Para obtener un código muy similar a java a partir de este fichero .jar, utilizaremos jd-gui (u otro decompilador). Jd-gui es una herramienta gráfica que muestra los archivos fuente de Java a partir de los archivos .class, Esto permitirá identificar más fácilmente el punto donde se debe hacer la modificación. El comando es:
jd-gui Crackme03-dex2jar.jar

En el caso de este crackme, se pide un nombre y un número de serie. En caso de que los datos sean incorrectos, la aplicación mostrará el mensaje “Bad boy”:

La modificación que se va a realizar consiste en hacer que la aplicación acepte cualquier dato que se introduzca y devuelva el mensaje asociado a los datos correctos. En el caso de esta aplicación, el código es muy corto y se puede buscar la cadena mostrada directamente en el código, pero se va a realizar la búsqueda de la cadena en la jerarquia de carpetas que creó apktool con el siguiente comando:
grep -iR "Bad boy" Crackme03/

Ahora sabemos que la cadena está en el archivo Crackme03/smali/com/example/helloandroid/HelloAndroid$2.smali, ese archivo es equivalente a com.example.helloandroid/HelloAndroid.class en jd-gui. El método donde aparece la cadena es el siguiente:

El código Smali asociado a este método tiene 268 lineas. Dicho código realiza las siguientes operaciones:
- Se toman los valores de los dos campos introducidos por el usuario
- Se guarda la longitud del campo nombre
- Se comprueba que la longitud sea 4 o más
-
Se
inicia un bucle que realiza una serie de cálculos para calcular el
valor correcto
- En la parte final de este bucle, se hace la comprobación del valor correcto con el valor introducido
Por tanto, para que la aplicación acepte cualquier valor de los campos, hay que modificar la comprobación de longitud y la comprobación de que el valor introducido es igual al correcto.
La comprobación de longitud en el código Smali se muestra en la siguiente imagen:

Las dos variables de la comprobación son v0 y v1. Si seguimos v0 desde en orden inverso al de ejecución, vemos que se copia desde v11 en la linea 45, se le asocia un nombre en la linea 25, y recibe en la linea 23 el resultado de la operación length de la linea 22. Siguiendo de la misma forma la variable v1, se copia desde v22 en la linea 46 y v22 se inicializa a 4 (0x4 en decimal) en la linea 44. Si la comprobación es correcta, se salta la ejecución a la etiqueta :cond_0 que se corresponde con la siguiente parte de la ejecución en caso correcto.
El código Smali asociado a la comprobación de que el serial introducido es igual al calculado se muestra en la siguiente imagen:

En este caso, la variable que interviene en la comprobación es v22, siguiéndola en sentido contrario a la ejecución se ve que recibe en la linea 164 el resultado de la operación de la linea 163, la cual compara si son iguales las variables v14 y v15. v14 recibe en la linea 160 el resultado de la operación de la linea 159 que es la ultima de la serie de cálculos del valor correcto. v15 es el valor introducido por el usuario y se puede ver en la captura de la comprobación anterior.
Llegados a este punto, los cambios a realizar serían cambiar la comprobación de longitud a un salto incondicional a la etiqueta :cond_0 y comentar la comprobación del serial para que entre en el fragmento de código correcto. Dichas modificaciones serían las siguientes:
Sin embargo estos cambios, concretamente el de la longitud del dato introducido, hace que la aplicación sufra errores (se puede hacer el otro cambio solo e introducir 4 caracteres cualesquiera en el campo nombre), por tanto, vamos a optar por un cambio diferente, consiste en realizar un salto hasta la zona del código correcto, en vez de hacer la comprobación de la longitud. Esto evita realizar todos los cálculos y lleva la ejecución al punto que queremos. Para realizar estos cambios, se comentará la línea 47 y se añadirá un salto incondicional hacia la etiqueta :cond_3 (la cual crearemos a continuación) entre la línea 47 y 48 (y será la nueva línea 48):

Después añadimos la etiqueta :cond_3 entre las lineas 166 y 167 (y será la nueva línea 167):

Una vez hechos estos cambios, lo último que queda es re empaquetar la aplicación, firmarla e instalarla. Para re empaquetar la aplicación usaremos el siguiente comando:
apktool b Crackme03

Este comando crea el archivo apk de la aplicación modificada y lo guarda en la ruta Crackme03/dist/Crackme03.apk. Para firmar la aplicación necesitaremos un almacén de claves o keystore, el cual podemos crearlo con el siguiente comando:
keytool -genkey -v -keystore keystore.keystore -alias alias -keyalg RSA -keysize 2048 -validity 3650

Finalmente se firma la aplicación con el siguiente comando:
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore keystore.keystore Crackme03/dist/Crackme03.apk alias

En este momento se debe borrar la aplicación original del dispositivo o emulador ya que al intentar instalarla reemplazándola, aparecerá un error por que los certificados no coinciden. Una vez eliminada la aplicación, instalaremos la aplicación en el dispositivo:
adb install Crackme03/dist/Crackme03.apk
Ahora, sin introducir ningún dato, la aplicación nos devuelve el mensaje correcto:

Hasta aquí la entrada, espero que os haya servido de ayuda y finalmente agradecer enormemente a mi compañero Javier Olmedo por la oportunidad de escribir en su blog!.
Un saludo y hasta la próxima.
Gracias por la explicacion y ejemplo. Podemos hacer las apk sin necesitar de las herramientas de google? Es para hacer una aplicacion de un dataloger con protocolo rs232 y tomar datos. Gracias. le agradezco la sugerencia
hola, es muy interesante tu post y esta increible. estoy en aprendisaje de crear apks para android ( tengo que obviar el echo de que no tengo estudios sobre el tema , es puro coraje ) y me parece una exelente idea aprender de esto. me gustaria estar en contacto para que pudieras guiarme en caso de que ponga en practica lo desarmar y montar apks. saludoss
Ok, por aquí estamos, Ángel.
Saludos!!