10 minuto(s) de lectura

Los sherlocks (De HackTheBox) son retos gamificados enfocados a Blue Team, en ellos, se encuentran distintas situaciones donde uno debe utilizar herramientas de analsis y artefactos para completar las tareas. Y claro, hay categorías según lo que quieras entrenar, como por ejemplo Malware Analysis que se enfocan en el análsis de malware y archivos maliciosos donde habrá que descubrir las características del artefacto malicioso para averiguar qué es lo que hace.

UTMP

Resumen ElectricBreeze-2

Este sherlock es un sherlock fácil enfocado al análisis dinámico de una muestra de malware jar, junta un poquito de todo el proceso de análisis para una muestra sencilla de analizar, ideal para acostumbrarse al proceso de análisis estático.

Laboratorio

Descripción

Your boss is concerned about Volt Typhoon and some of their malware developments. He has requested that you obtain a copy of the associated malware and conduct a static analysis to identify any useful information. Please report back with your findings.

Desarrollo

En este sherlock, no se nos dan archivos directamente, las preguntas nos irán guiando poco a poco para desentrañar las acciones del malware.

Q1: Use MalwareBazaar to download a copy of the file with the hash ‘4bcedac20a75e8f8833f4725adfc87577c32990c3783bf6c743f14599a176c37’. What is the URL to do this?

MalwareBazaar Es una plataforma de abuse.ch y Spamhaus dedicada a compartir muestras de malware con la comunidad de seguridad de la información, inteligencia de amenazas y proveedores de antivirus, es una de las bases de datos más grandes relacionadas con muestras de malware, proveen sus características, reglas YARA, e incluso, la familia del malware.

Para inciar entonces, necesitamos crear una cuenta y buscar el hash; las muestras generalmente se dan con los hases MD5, SHA256, SHA1, entre muchos otros, esto permite diferenciar la muestra de malware de las otras (excepto firmas como imphash o ssdeep que tratan de detectar muestras parecidas). Dada la extensión del hash, podemos sospechar que se trata de un SHA256, por lo que utilizamos la siguiente búsqueda:

sha256:4bcedac20a75e8f8833f4725adfc87577c32990c3783bf6c743f14599a176c37

Nos regresará un hit:

UTMP

Y dando click en el hash, podremos ver sus características y la opción de descargar la muestra, por lo que sólo tendremos que copiar el link de Descargar Muestra:

UTMP

Q1: https://bazaar.abuse.ch/download/4bcedac20a75e8f8833f4725adfc87577c32990c3783bf6c743f14599a176c37/

Q2: What is the password to unlock the zip?

Antes de dar con la respuesta es importante puntualizar algo, debemos estar concientes de que las muestras que descargamos tienen el potencial de comprometer nuestro sistema y a parte de ello, se contribuyen con medidas adicionales (a veces) para tratar de evitar este escenario; se quitan las extensiones y se comprimen con contraseña, esto que se considera estandar en la industria una clase de recordatorio de que estás trabajando con una muestra de malware y debe considerarse peligrosa a la medida de lo posible (Aunque otras veces, puede no ser la misma)

UTMP

Q2: infected

Q3: What is the extension of the file once unzipping?

Descargando el archivo, podemos moverlo a un directorio donde podamos organizarnos tranquilamente y extraemos el archivo (en mi caso, con 7z)

7z x ElectricBreeze2.zip

Y listando, podremos ver el contenido y la respuesta:

UTMP

Q3: .jar

Q4: What is a suspicious directory in META-INF?

El META-INF es un directrio reservado en los .jar (y en .ear y .war) que contiene información de metadatos sobre el archivo, a forma general, el describir el contenido y dar instrucciones de como comportarse al ser ejecutado o utilizado como librería, es decir, que da un insight sobre cómo está armado y cómo se comporta.

Esto, puede hacerse de varias maneras, la sencilla, es descomprimiendo el .jar u otra, analizando los strings, esto aprovechando que sabemos que la respuesta se encuentra en el META-INF:

strings 4bcedac20a75e8f8833f4725adfc87577c32990c3783bf6c743f14599a176c37.jar | grep META-INF

Y nos saldrá un ouput reducido, donde si observamos cada uno, el que salta a la vista tiene un nombre efectivamente sospechoso… ¿será bueno que algo tendría el string memShell?

UTMP

Q4: Director_tomcat_memShell

Q5: One of the files in this directory may give some insight into the threat actor’s origin. What is the file?

Ahora sí, tendremos que descomprimir el .jar para analizarlo más a fondo:

unzip 4bcedac20a75e8f8833f4725adfc87577c32990c3783bf6c743f14599a176c37.jar -d stage0

Y entrando al nuevo directorio stage0 podremos ver los contenidos de META-INF a detalle:

tree META-INF
META-INF
├── MANIFEST.MF
└── maven
    ├── org.example
    │   └── Director_tomcat_memShell
    │       ├── pom.properties
    │       └── pom.xml
    └── org.javassist
        └── javassist
            ├── pom.properties
            └── pom.xml

Dado que el archivo sospechoso se encuentra dentro de Director_tomcat_memShell tenemos que enumerar ambos, pero en el .xml, encontramos algo en particular:

UTMP

Q5: pom.xml

Q6: According to Google Translate, what language is the suspicious text?

Para esto, sencillamente sólo tenemos que copiar y pegar:

UTMP

Q6: Chinese

Q7: What is the translation in English?

Con la imagen anterior, también podemos ver la respuesta a esta pregunta:

Q7: Check for the latest version

Q8: According to this file, what is the application’s name?

Revisando el .xml puedes dar con la respuesta, sólo habrá que ver el campo name del archivo:

UTMP

Q9: The VersaMem web shell works by hooking Tomcat. Which file holds the functionality to accomplish this?

Ahora, del XML, podemos extraer un poco de más información, ¿a qué funciones llama?:

UTMP

Esto indica una ruta dentro del .jar la cual apunta a la clase Main que guardará todas las funcionalidades.

com/versa/vnms/ui  tree .       
.
├── config
│   └── Config.class
<SNIP>
├── TestMain.class
├── transformer
<SNIP>
Q9: com/versa/vnms/ui/TestMain.class

Q10: There is a command that determines the PID for the hook. What is the program used in this line of code?

Ahora, para examinar el TestMain.class necesitamos un decompiler para poder ver los contenidos, yo recomiendo utilizar JD-GUI Pero puedes utilizar otro sin problema.

En mi caso:

java -jar ~/Documents/Tools/uncategorized/jd-gui/jd-gui-1.6.6.jar TestMain.class

Navegando al TestMain.class podremos encontrar la función de entrada, más técnicamente el inyector y con ello, nuestra respuesta:

UTMP

Q10: pgrep

Q11:The functionality for the webshell is in a different file. What is its name?

Para esta pregunta, es un poco de seguir el flujo de la ejecución; imaginar visualmente cómo se ejecuta te ayudará a entender a fondo qué es lo que hace, Entonces si iniciamos en Main y bajamos poco a poco, la función llama a otra en la misma clase:

UTMP

Siguiendo el flujo, veremos que llega a TestMain que rápidamente, inicia la clase init; luego init llamará a config.init

UTMP

Cuando la ejecución alcanza la clase Config, que a forma general, empieza a configurar dinámicamente guardando parámetros y parseando cadenas; pero nada más allá, a lo que si continuamos viajando por las clases, parece repetitivo, y no llama a nada más fuera de sí.

UTMP

Esta parte, concluimos que devuelve algún valor y continua la ejecución antes de ser llamada: justo en init en el Main. La siguiente clase que llamará es justo…

CoreClassFileTransformer coreClassFileTransformer = new CoreClassFileTransformer(inst);

Que crea un objeto CoreClassFileTransformer

Y vemos las siguientes 2 clases:

UTMP

Si observamos la clase WriteTestTransformer y su contenido, notaremos el string insertShell y justo después, strings interesantes relacionados con manejo de sesiones http:

UTMP

Lo que nos da una pista sólida de que esta es la clase que buscamos.

Q11: com/versa/vnms/ui/init/WriteTestTransformer.class

Q12: What is the name of the function that deals with authentication into the webshell?

Observando las 2 cadenas, en una de ellas veremos que tiene distintos parámetros como String accessPwd o if (accessPwd.equals(pwd)) || accessPwd.equals(authStr) también es pista sólida de que sea para este propósito:

Q12: getInsertCode

Q13: What request parameter must be present to activate the webshell logic?

Desde aquí, podemos hacer algo para facilitar el análisis; si bien podemos investigar la linea de inicio a fin podemos pasar al formato en el que está escrito el payload; notarás los espacios y los newlines así que sólo habrá que hacer un echo de la función y potencialmente obtendremos el formato funcional y limpio:

❯ echo "{\n            String pwd = <SNIP> this.internalDoFilter($1, $2);\n        }" > Stage1

Y un simple cat, mostrará un formato mucho más cómodo de trabajar

UTMP

Ahora, justo al inicio, está el parámetro esperado por getParameter que es el char p

String pwd = .getParameter("p");
Q13: p

Q14: What is the hardcoded access password used to validate incoming webshell requests?

Dado que el siguiente parámetro es un string MUY parecido a password (accessPwd) es lógico pensar que esta es la clave de acceso.

Q14: 5ea23db511e1ac4a806e002def3b74a1

Q15: What type of encryption is used?

Si avanzamos con la cadena un poco, veremos una serie de números y el string AES lo que nos dice que esta es la llave y justo esta es la que utiliza para encriptar:

SecretKeySpec(new byte[]{56, 50, 97, 100, <SNIP>, 97, 97}, "AES");
Q15: AES

Q16: What cipher mode is used to encrypt the credentials?

Justo después, en la siguiente linea, encontraremos la cadena del modo de cifrado:

ipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
Q16: ECB

Q17: What is the key?

Hace 2 preguntas atrás, hemos conseguido la llave:

Q17: 56, 50, 97, 100, 52, 50, 99, 50, 102, 100, 101, 56, 55, 52, 99, 53, 54, 101, 101, 50, 49, 52, 48, 55, 101, 57, 48, 57, 48, 52, 97, 97

Q18: What is the value of the key after decoding?

Si observamos con atención, podremos notar que los valores se concentran desde los 50 hasta los 100, da un indicio de que pueda ser ASCII.

Para convertirlo, no necesariamente tenemos que quitar las comas ,, sólo usamos un convertidor ASCII como el de RapidTables donde ingresamos toda la cadena al campo Decimal (bytes) y copiamos el texto resultante (el texto decodificado).

UTMP

Q18: 82ad42c2fde874c56ee21407e90904aa

Q19: To avoid static detection, the method name is constructed at runtime and passed to java.lang.reflect.Method, what is the decimal byte array used to construct the string name?

Si continuamos el flujo de la función, veremos el método java.lang.reflect.Method mencionado donde se declara el arreglo buscado.

UTMP

Q19: 100, 101, 102, 105, 110, 101, 67, 108, 97, 115, 115

Que equivale al string defineClass

Q20: What is the Base64-encoded string that is returned to the client if the class is successfully defined?

Siguiendo la lógica del programa, podemos puntualizar que este bloque if está confirmando si se encuentra la clase clzn, en el caso que no se haya cargado, intenta cargarla directamente desde los datos pasados en el parámetro clzd al cargar la clase después de cargarla de forma reflexiva con el ClassLoader, escribe la respuesta cifrada en b64 con httpResponse.getWriter().write:

Q20: R2qBFRx0KAZceVi+MWP6FGGs8MMoJRV5M3KY/GBiOn8=

Q21: What is the decrypted string?

Esto lo podemos hacer con cyberchef; primero, sabemos que es un base64 (por la pregunta anterior pero podemos sospecharlo fuertemente por caracteres como +/=) y el resultante estará cifrado en AES/ECB (pero no olvidemos el PKCS5Padding que indica) que no necesitamos Initialization Vector para descencriptar. Así que sólo tenemos que agregar el From base64, agregar el AES Decrypt ingresar el key (la cadena de la pregunta 18) en UTF-8, El modo ECB/NoPadding y el Raw Input

UTMP

Q21: classDefine by clzd

Q22: There is another class to log passwords for exfiltration. What is this file?

Ahora, retornemos la ejecución a CoreClassFileTransformer, donde fue llamada WriteTestTransformer, avanzando a la siguiente linea, encontramos CapturePassTransformer y un overview rápido, encontramos una función con un nombre muy directo captureLoginPasswordCode que nos da una razón para creer que es este archivo class el que buscamos.

Q22: com/versa/vnms/ui/init/CapturePassTransformer.class

Q23: What is the main malicious function in this class?

Esta pregunta se responde con la anterior, en primera el nombre tan directo pero también repite el patrón de crear un one liner de una función más grande como la clase anterior.

Q23: captureLoginPasswordCode

Q24: The same AES key from the previous method is being used. What is the variable name it is being saved as in this function?

Repitamos el proceso de pasar el one liner a un archivo para facilitar su lectura, y vemos que efectivamente, utiliza la misma llave.

UTMP

Q24: secretKey

Q25: What file is used to hold credentials before exfiltration?

Si observamos el código, podemos darnos cuenta rápidamente de una declaración de una ruta absoluta en una variable llamada logFile, y un bash -c, con estos elementos, podemos interpretar exactamente lo que hace este bloque: logData (que es texto en b64) es buscado dentro de logFile (/tmp/.temp.data) con grep (con la opción -q para indicar quiet), es decir, busca si existe ya dentro del archivo, si NO encuentra esos datos, entonces se añade el logData a logFile, habiendo entendido esto, el archivo que mantiene las credenciales es logFile o bien /tmp/.temp.data

Q25: /tmp/.temp.data
Agradecimiento

Si lees esto, gracias por llegar hasta aquí!, si existen dudas, comentarios y correcciones (que son más que bienvenidas) contáctame con confianza, que siempre he dicho que la ciberseguridad es esfuerzo conjunto.

En caso que no los vea, buenos días, buenas tardes y buenas noches. Happy Hacking!.

Actualizado: