martes, 24 de febrero de 2015

El malware para Android, cada vez mas sofisticado

En una entrada anterior del blog hablamos de una técnica que consistía a usar una librería nativa como libAPKProtect para descifrar código Dalvik. Durante el análisis de un nuevo APK hemos encontrado un malware que usa un concepto similar al mostrado por libAPKProtect, pero que usa técnicas mas sofisticadas para ofuscar el código y hacer mas difícil la ingeniería inversa. La relevancia de las técnicas empleadas hace interesante su análisis.

En primer lugar, detectamos que el malware carga una librería denominada libprotectClass.so”. Esa librería como sugiere su nombre descifra una parte de la aplicación ofuscada. El malware carga esa librería desde la función “attachBaseContext” que en primera instancia determina la arquitectura del sistema (Intel o ARM), y en segunda instancia carga la librería nativa correspondiente (“libprotectClass.so” en nuestro caso) ejecutando el comando System.load (“libprotectClass.so”).


Analizando la librería nativa del malware, nos damos cuenta que no tiene un formato ELF valido. En efecto, la librería tiene más secciones “header” que secciones definidas. También tiene una sección más grande que el tamaño del malware, y por último tiene un tamaño de sección “header” invalido.

Cada sección es mapeada en la memoria del proceso y tiene una semántica definida. La sección “.text” contiene el código del programa, “.data” contiene las cadenas, etc. Resulta que, por ejemplo, no se puede cargar la librería con readelf (utilidad para mostrar información sobre archivos ELF). Sin embargo, con Android funciona perfectamente, es decir que no es tan riguroso como readelf.


Tras arreglar el tamaño de cada sección de la cabecera a 40 bytes, bajar la cantidad de secciones a 23, y ajustar la sección que excede el tamaño del archivo, se ha podido arreglar el problema. Abajo se muestra la lista de secciones presentes en el malware. 


Cuando una librería nativa se carga por Android desde la llamada System.load de la maquina virtual Dalvik (DVM) se llama a la funcion “JNI_OnLoad” de esa librería. Sin embargo, esa función parece estar cifrada:
JNI_OnLoad cifrada

Mirando a más bajo nivel, en la función “dvmLoadNativeCode” de la libreria “libdvm.so” de Android, vemos que esta función llama a “dlopen” para cargar la librería “libprotectClass.so” en el proceso. La función “dlopen” se encarga de cargar la librería en memoria y llama a los constructores definidos en la librería nativa. Es decir, a la función “init” de la librería nativa (si esta definida) y a las funciones donde las referencias están definidas en la sección “.init_array” del malware. Esas funciones permiten inicializar la librería. El malware usa esta funcionalidad para descifrar la función “JNI_OnLoad”:).

Después de haber inicializado la librería, Android recoge la dirección de la función “JNI_OnLoad” llamando a la función “dlsym”, y por fin llama a “JNI_OnLoad”. Entonces, sabemos que la función está descifrada cuando Android ha recogido la dirección de la función “JNI_OnLoad”, y así podemos poner un breakpoint:).

JNI_OnLoad descifrada

Comprobaciones anti ingeniería inversa

Al principio de la ejecución de la librería nativa, el malware hace cinco comprobaciones para detectar la presencia de un depurador, evitar la lectura de memoria, etc.

El malware realiza las siguientes comprobaciones:

1) Para evitar que un programa externo lea la memoria del malware, se monitorizan todos los accesos a los archivos “/proc/pid/mem” y “/proc/pid/pagemap” gracias a las funciones “inotify_init” y “inotify_add_watch”. Si detecta una lectura de su memoria por un programa externo, el malware termina su ejecución. En efecto, una manera muy rápida para extraer todos los archivos descomprimidos/descifrados es leer la memoria del malware después de descifrarlo y buscar, por ejemplo, con una herramienta como “volatility” los nuevos DEX creados (conteniendo el código Dalvik).

2) “Hookea” las funciones de Android “__android_log_write” y “__android_log_buf_write” de la librería “liblog.so”. Estas funciones, usadas para escribir en el log de Android, ayudan a realizar la ingeniería inversa porque revelan los archivos abiertos, los DEX cargados, etc. El sistema de explotación Android usa ese log tanto a nivel kernel como de usuario.

3) Igualmente tambien “hookea” las funciones usadas por el depurador de código Dalvik como “dvmDbgActive”. Con esto evita que la aplicación pueda estar depurada al nivel de la maquina virtual Dalvik (DVM).

4) Recorre todos los procesos activos y busca la cadena “android_server” que corresponde al depurador de IDA ejecutándose en el dispositivo. Por eso, abre la carpeta “/proc” que contiene todos los PID de los procesos activos. Forma la cadena “/proc/pid/cmdline” y abre el archivo correspondiente para recoger el nombre del proceso y lo compara con “android_server”.

5) Comprueba si el nombre del proceso padre es “strace”, “ltrace”, “gdb” o “android_server”. “Strace” y “ltrace” permiten de listar las llamadas al sistema y así ver los archivos leídos/escritos, memoria leída/escrita, etc. En cuanto a “gdb” y “android_server”, son programas que permiten depurar un proceso.

Cifrado interno

Merece la pena comentar que todas las cadenas usadas por el malware están cifradas. Cada cadena es codificada en base64 antes de pasar por un XOR.


Tras las comprobaciones el malware carga una nueva librería nativa, localiza la función “JNI_OnLoad” y procede a descifrarla.


En la nueva función “JNI_OnLoad”, el malware hace llamadas a métodos Dalvik, definidos en la maquina virtual (DVM). Usa el JNI, que se puede ver como un puente entre la maquina virtual y la librería nativa, para comunicar con la DVM desde la librería nativa. Por ejemplo, se puede usar ésta técnica para “hookear” los métodos Dalvik. Se muestra un ejemplo de uso de la API de Android para recoger la clase “com/qihoo/util/StubApplication”.

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
        JNIEnv *env;
        jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
        jvm->AttachCurrentThread(&env, NULL);
        gJClass = env->FindClass("com/qihoo/util/StubApplication");

        return JNI_VERSION_1_6;
}
En esta función, el malware recoge el hash de la firma del APK llamando a métodos Dalvik. Pensamos que el malware comprueba si el APK fue modificado. En efecto, cada APK necesita estar firmado antes de ser instalado en el móvil. Si queremos modificar el APK, necesitamos firmarlo otra vez, con un certificado diferente.

Comprueba la versión del SDK actual del sistema (“ro.build.version.sdk”) y del Android runtime (Dalvik o ART). Pensamos que hace esas comprobaciones para asegurarse que los métodos Dalvik necesarios para la ejecución del malware existen en la versión del sistema.

Finalmente, reserva memoria en el proceso mapeando el dev “/dev/zero”, copia el DEX cifrado en esta zona de memoria, y lo descifra. Abajo se puede ver el principio del nuevo DEX descifrado:)


Ahora, podemos hacer un volcado del nuevo DEX y abrirlo con un desensamblador de código dalvik. Se muestra una parte de una función desensamblada del nuevo DEX.


Por fin, el malware registra todas las clases del nuevo DEX como “Lcom/astep/pay/theActivity”, “Lcom/astep/pay/rd/Rd1Activity”, “Lcom/common/as/activity/DlActivity”, etc, y cambia la variable strEntryApplication de la clase “com/qihoo/util/StubApplication” a “com.ly.tcmy.application.PeibanApplication” para que la nueva aplicación sea cargada por el malware.


Este malware usa algunos de los métodos de ofuscaciones y anti-debugging mas sofisticados de los que hemos visto, como por ejemplo los incluidos en APKProtect. Estas ofuscaciones están presentes tanto al nivel del DVM como de la librería nativa. Ademas, el malware llama a funciones métodos Dalvik desde la librería nativa y así manipula objetos de la DVM que hace la depuración mas difícil. Por encima, el malware se aprovecha del poco rigor de Android para manipular la librera nativa.

Más información:

SHA256 de la muestra analizada:
1987a8b5858762247b77b62dd7ce8494c5442a19e0c883a5359332e09342b614

Introduction to Dynamic Dalvik Instrumentation,




Laurent Delosières