A principios de marzo de 2019, una nueva muestra de malware para macOS del grupo OceanLotus fue cargada al popular servicio para el análisis de muestras online VirusTotal. Este backdoor ejecutable presenta las mismas funcionalidades que la variante previa de macOS que analizamos, pero su estructura cambió y lograron que su detección sea más difícil. Lamentablemente, no pudimos encontrar el dropper asociado con esta muestra, por lo que no conocemos cuál fue el vector de compromiso inicial.

Recientemente hemos publicado un detallado análisis de las actualizaciones de OceanLotus y de cómo sus operadores emplean un amplio abanico de técnicas para lograr ejecutar código, lograr persistencia y dejar el menor rastro posible en sistemas Windows. OceanLotus es también conocido por tener componentes maliciosos dirigidos a macOS. En este sentido, este artículo explica qué cambios fueron realizados en estos componentes maliciosos para macOS con respecto a la versión previa analizada por Trend Micro y, mientras analizamos el código de esta nueva variante, se describirá cómo puedes automatizar el descifrado de cadenas de caracteres utilizando la API de IDA Hex-Rays.

Análisis

Las siguientes tres secciones de este post describen el análisis de la muestra con el hash SHA-1 de E615632C9998E4D3E5ACD8851864ED09B02C77D2. El archivo es nombrado flashlightd y es detectado por los productos de ESET como OSX/OceanLotus.D.

Anti-debug y anti-sandbox

Como es común en los binarios macOS de OceanLotus, la muestra está empaquetada con UPX, pero la mayoría de las herramientas de identificación de paquetes no la reconocen como tal; probablemente debido a que la mayoría incluye una firma que se basa en la presencia de un string “UPX”. Además, firmas Mach-O son menos comunes y no son actualizadas regularmente. Esta característica particular hace que la detección estática sea más difícil. Una vez desempaquetado, un punto interesante es que el punto de entrada está ubicado al principio de la sección __cfstring en el segmento .TEXT. Esta sección presenta los atributos flag que se pueden ver en la Figura 1.

Figura 1 – MACH-O sección atributos __cfstring

Como se aprecia en la Figura 2, el hecho de que el código esté en la sección __cfstring engaña a algunas herramientas de desensamblado para desplegar el código como strings.

Figura 2 – El código del backdoor es definido como datos por IDA

Cuando corre, el binario primero crea un hilo como guardián anti-debugging cuyo único propósito es revisar continuamente si hay un debugger presente. Lo hace de la siguiente manera:

  • Intenta separar cualquier debugger mediante el llamado ptrace con PT_DENY_ATTACH como parámetro de solicitud
  • Comprueba si algunos puertos de excepción están abiertos llamando a la función task_get_exception_ports
  • Comprueba si un debugger está adjuntado, como se aprecia en la Figura 3, verificando si el flag está seteado en el proceso actual

Figura 3 – Comprueba si se adjuntó un debugger mediante la función sysctl

Si el guardián detecta que un debugger está presente llama a la función exit. Además, la muestra luego revisa su entorno emitiendo los siguientes dos comandos:
ioreg -l | grep -e "Manufacturer" y sysctl hw.model
y verifica el valor de retorno contra una lista de claves codificadas (hardcoded) de conocidos strings de sistemas de virtualización: oracle, vmware, virtualbox o parallels. Finalmente, el comando:
system_profiler SPHardwareDataType 2>/dev/null | awk '/Boot ROM Version/ {split($0, line, ":");printf("%s", line[2]);}
verifica si la máquina es una de las siguientes: "MBP", “MBA”, “MB”, “MM”, “IM”, “MP” y “XS”. Estos códigos representan el modelo del sistema. Por ejemplo, “MBP” es para MacBook Pro, “MBA” para MacBook Air y así con los demás…

Principales actualizaciones

Si bien el comando del backdoor no cambió desde la publicación del artículo de Trend Micro, sí hemos notado otro tipo de modificaciones. Los servidores C&C utilizados para esta muestra son bastante recientes, siendo su fecha de creación 22-10-2018.

  • daff.faybilodeau[.]com
  • sarc.onteagleroad[.]com
  • au.charlineopkesston[.]com

El recurso URL utilizado ha cambiado a /dp/B074WC4NHW/ref=gbps_img_m-9_62c3_750e6b35.

El primer paquete enviado al servidor C&C contiene más información sobre la máquina host. Todos los datos recopilados por los comandos en la siguiente tabla son incluidos:

Commands Description
    system_profiler SPHardwareDataType 2>/dev/null

  • awk '/Processor / {split($0,line,":"); printf("%s",line[2]);}'
  • machdep.cpu.brand_string

Gather processor information
    system_profiler SPHardwareDataType 2>/dev/null

  • awk '/Memory/ {split($0,line, ":"); printf("%s", line[2]);}'
Gather memory information
ifconfig -l Gather network interface MAC addresses
    ioreg -rd1 -c IOPlatformExpertDevice

  • awk '/IOPlatformSerialNumber/ { split($0, line, "\""); printf("%s", line[4]); }'
Retrieves the serial number of the device

Entre los principales cambios de configuración, esta muestra no utiliza la librería libcurl para exfiltración de red. En cambio, utiliza una librería externa. Para localizarla, el backdoor intenta descifrar cada archivo en el directorio actual utilizando AES-256-CBC con la llave gFjMXBgyXWULmVVVzyxy rellenada con ceros. Cada archivo es “descifrado” y guardado como /tmp/store y un intento de cargarlo como librería es realizado utilizando la función dlopen. Cuando un intento de descifrado resulta en una exitosa llamada a dlopen, el backdoor entonces recupera las funciones exportadas Boriry y ChadylonV, que parecen ser responsables de la comunicación de la red con el servidor. Como no tenemos el dropper u otros archivos de la ubicación original de la muestra, no pudimos analizar esta librería. Además, dado que el componente está cifrado, una regla basada en YARA en estas strings no coincidirá con el archivo encontrado en el disco.

Como fue descrito en el artículo mencionado, una clientID es creada. Este identificador es el hash MD5 del valor de retorno de uno de los siguientes comandos:

  • ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformSerialNumber/ { split($0, line, "\""); printf("%s", line[4]); }'
  • ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, "\""); printf("%s", line[4]); }'
  • ifconfig en0 | awk \'/ether /{print $2}\' (obtiene la dirección MAC)
  • un comando desconocido ("\x1e\x72\x0a") el cual es utilizado para ser “uuidgen” en las muestras previas

Antes de ser hasheado, el caracter “0” o “1” es añadido al valor de retorno indicando privilegios raíz. Este clientID es almacenado en /Library/Storage/File System/HFS/25cf5d02-e50b-4288-870a-528d56c3cf6e/pivtoken.appex si el código corre como raíz, o de otra manera en ~/Library/SmartCardsServices/Technology/PlugIns/drivers/snippets.ecgML. Este archivo es normalmente escondido a través de la función _chflags y su timestamp es modificado utilizando el comando “touch –t” con un valor aleatorio.

Descifrado del string

Al igual que en variantes previas, las strings están cifradas utilizando AES-256-CBC (llave hex codificado: 9D7274AD7BCEF0DED29BDBB428C251DF8B350B92 rellenadas con ceros y el IV es completado con ceros) utilizando la función CCCrypt. La llave ha cambiado con respecto a versiones previas, pero dado que el grupo sigue utilizando el mismo algoritmo para cifrar strings, el descifrado podría ser automatizado. Junto con este artículo estamos lanzando un script de IDA que aprovecha la API Hex-Rays para descifrar los strings presentes en el binario. Este script puede resultar de ayuda para futuros análisis de OceanLotus y para el análisis de muestras existentes que aún no hemos podido obtener. Además, busca la asignación de parámetros para poder encontrar sus valores. Este método podría ser reutilizado para recuperar la lista de argumentos de una función y luego pasarlos a una función de llamada.

Conociendo el prototipo de la función decrypt, el script primero busca todas las referencias cruzadas a esta función, busca todos los argumentos, descifra los datos y pone el texto plano dentro de un comentario en la dirección de la referencia cruzada. Con el fin de que el script funcione correctamente, el alfabeto personalizado y utilizado por la función de codificado en base64 debe estar seteado en el script y la variante global que contiene la longitud de la llave debe ser definida (como un DWORD en este caso; ver Figura 4).

Figura 4 – Definiendo la variante global key_len

En la ventana Function, puedes hacer clic derecho en la función descifrado y clic en “Extraer y descifrar argumentos”. El script deberá colocar el string descifrado en los comentarios, como se puede apreciar en la Figura 5.

Figura 5 – Texto descifrado es colocado en los comentarios

Esto lista los strings descifrados de forma conjunta en la ventana xrefs to de IDA para esa función, como se puede apreciar en la Figura 6.

Figura 6 – Xrefs to de la función f_decrypt

El script final puede encontrarse en nuestro repositorio de Github.

Conclusión

Tal como mencionamos en otro artículo reciente sobre OceanLotus, el grupo continúa mejorando y actualizando su conjunto de herramientas, y una vez más, las ha mejorado también para afectar a usuarios de Mac. El código no ha cambiado mucho, pero debido a que muchos usuarios de Mac no utilizan en sus equipos una solución de seguridad, la necesidad de evadir la detección de estos productos es de menor importancia. Los productos de ESET ya detectaron este archivo cuando lo encontraron. Desde que la librería de red utilizada para la comunicación C&C está ahora cifrada en el disco, el protocolo de red utilizado permanece desconocido.

Indicadores de Compromiso (IoCs)

Los IoCs en este blogpost, así como los atributos de MITRE ATT&CK, están disponibles en nuestro repositorio en GitHub.

Nombres de dominio

  • daff.faybilodeau[.]com
  • sarc.onteagleroad[.]com
  • au.charlineopkesston[.]com

Recurso de URL

  • /dp/B074WC4NHW/ref=gbps_img_m-9_62c3_750e6b35

Rutas de archivo

  • ~/Library/SmartCardsServices/Technology/PlugIns/drivers/snippets.ecgML
  • /Library/Storage/File System/HFS/25cf5d02-e50b-4288-870a-528d56c3cf6e/pivtoken.appex
  • /tmp/store

Sample analyzed SHA-1 hash ESET detection name
fleshlightd E615632C9998E4D3E5ACD8851864ED09B02C77D2 OSX/OceanLotus.D

Técnicas MITRE ATT&CK

Tactic ID Name Description
Defense Evasion T1158 Hidden Files and Directories The backdoor hides the clientID file via chflags function.
T1107 File Deletion The backdoor can receive a “delete” command.
T1222 File Permissions Modification The backdoor changes the permission of the file it wants to execute to 755.
T1027 Obfuscated Files or Information The library used for network exfiltration is encrypted with AES-256 in CBC mode.
T1099 (macOS) Timestomp The timestamp of the file storing the clientID is modified with a random value.
Discovery T1082 System Information Discovery The backdoor performs a fingerprint of the machine on its first connection to the C&C server.
Exfiltration T1022 Data Encrypted The backdoor encrypts the data before exfiltration.
Command and Control T1094 Custom Command and Control Protocol The backdoor implements a specific format for the packet involving random values. See Trend Micro article.