jueves, 4 de septiembre de 2014

APKProtect: desempaquetador de bytecode Dalvik dentro de una libreria nativa

En nuestro departamento de antifraude hemos analizado el APK de un troyano Android para envío de SMS, en él hemos encontrado una técnica de desempaquetado muy interesante. El malware usa una librería nativa integrada (libAPKProtect.so) en el APK para desempaquetar el bytecode Dalvik. Además de eso, implementa técnicas para hacer mas difícil el volcado de la memoria del proceso y extraer el bytecode Dalvik también implementa un control para terminar la ejecución en caso de que el APK haya sido reempaquetado. Entendemos que el lector está familiarizado con el entorno Android y con las herramientas para depurar las aplicaciones Android como ndk-gdb de la NDK de Android.



Al abrir el archivo "classes.dex" del APK que contiene el bytecode Dalvik, vemos que hay instrucciones que no fueron interpretadas porque los byte codes están cifrados. El cifrado dificulta la ingeniería inversa, evita que los sistemas automatizados inserten "hooks", etc.

Ejemplo de la funcion "onCreate" cifrada:












Recorriendo el archivo, vemos el constructor de la clase "APKMainAPP12D0C" que carga una librería llamada "APKProtect". El desempaquetador seguramente está dentro de la librería nativa. ¿Cómo? Sí, un desempaquetador de bytecode Dalvik está contenido en una librería nativa compilada para procesadores ARM. Necesitamos de depurar la librería nativa. Por eso, nos hemos inspirado en el blog "The Cobra Den" para configurar el entorno de depuración y la instalación de ndk-gdb de Google.


Cuando el malware carga la librería nativa con la función "loadLibrary", el sistema operativo llama a la funcion "On_JNILoad" de esa misma librería nativa. Depurando la librería, hemos puesto un breakpoint a esa función "On_JNILoad".

En esa función, la primera parte se encarga de  llamar a la función "ptrace" con el parámetro PTRACE_TRACEME. Evita el funcionamiento de todo tipo de depuradores como GDB al igual que tampoco funcionará cualquier tentativa de volcado de memoria.

En la segunda parte, el malware abre el archivo "/proc/self/maps" que contiene el mapeado de su memoria. Itera cada línea hasta encontrar la cadena "classes.dex", es decir la zona de memoria que contiene el mapa del archivo "classes.dex". Analizando esa misma línea, el malware conoce la localización en memoria del mapa del archivo "classes.dex".

Ejemplo del mapeado del codigo Dalvik en el proceso donde vemos que el archivo “classes.dex” esta mapeado entre la dirección 0x47c46000 y 0x47c53000.

47c46000-47c53000 r--p 00000000 1f:01 525 /data/dalvik-cache/data@app@google.service-1.apk@classes.dex

Luego el malware comprueba si es un DEX o un DEX optimizado (DEY) buscando la cadena "dex" o "dey". Si es un DEX, recoge 20 bytes y compara esos 20 bytes con bytes de su librería. Si no hay correspondencias, el malware lanza un hilo que termina la ejecución del proceso en un tiempo aleatorio. ¿Pero…? un momento, ¿20 bytes no es el tamaño de una firma SHA1? En la documentación de Google, vemos que cada archivo DEX tiene una firma SHA1 en su cabecera excepto los códigos optimizados (DEY). Sirve para asegurarse de la integridad del archivo, es decir que el archivo no fue modificado. Si el archivo fue modificado, vuelve a matar su proceso de la misma manera. Pensamos, que el malware comprueba eso para evitar todos los tipos de reempaquetado que consisten en desempaquetar, insertar hooks, y re-empaquetar.

Esta es la firma SHA1 del archivo "classes.dex" que hemos encontrado:
0x73 0xAD 0x50 0x7F 0x1C 0xC6 0x8A 0x4D 0x2E 0x8C 0xEE 0xF5 0xDA 0xF8 0xE7 0x7C 0x27 0x4D 0x97 0xE7

En la tercera parte, el malware recoge el bytecode Dalvik (dentro del map del archivo classes.dex), llama a la funcion mprotect para cambiar la proteccion de las paginas de memoria a escritura. Por cada parte del bytecode Dalvik cifrado, recoge cada byte (LDRB), aplica un Exclusive OR (EORS) con bytes de su libreria, y guarda el resultado (STRB) a la misma ubicacion. Cuando todas las partes estan decifradas, el malware llama de nuevo a la funcion “mprotect” para cambiar las paginas de memoria al modo lectura. Solo en modo lectura, porque es la maquina Dalvik quien va a leer los byte codes, ejecutarlos y no el procesador ARM :=).



Ahora que sabemos donde descifra el malware los bytecode, solo es necesario poner un breakpoint cuando ha terminado, es decir a la funcion "mprotect". Con el comando "dump memory /home/ubuntu/dump.bin 0x47c46000 0x47c53000" dentro de la consola de gdb, conseguimos un volcado de la memoria.  Solo falta abrir el volcado con un intérprete de bytecode Dalvik como IDA para ver el código descifrado.

La misma función "onCreate" pero descifrada: 

El desempaquetador APKProtect no fue diseñado por el autor de malware. En efecto, APKProtect es un producto que se encarga de proteger los APKs ante ingeniería inversa. Desafortunadamente, ayuda tanto a los buenos como a los malos.

Más información:

SHA256 de la muestra analizada  3aee81db24540fb6b3666a38683259fd32713187ec6e0b421da9b91bd216205f

NDK,

Debugging Apps with Native Code - part 1

Dalvik Executable Format

ApkProtect,



  
Laurent Delosières