Hoy veremos cómo podemos analizar un malware cualquiera con Radare2, ¿Por qué Radare2? Son muchas las razones, entre otras como veremos a continuación, se puede automatizar lo que se nos ocurra, podemos hacernos un script sencillo que nos permita de un vistazo rápido realizar búsquedas u obtener información que nos muestran gran variedad de páginas destinadas a analizar malware (sandboxies) y se encuentran online. Eso sí, hablaremos de análisis estático, no dinámico.

Para ello, me gustaría ir mostrando capturas de unas plataformas de tipo Sandbox e ir viendo lo que se obtiene con unas y otras y lo que se muestra con Radare2, vereis como se puede conseguir lo mismo, otra cosa es que para verlo más bonito haya que currárselo.

Cojemos una muestra cualquiera (Wannacry decryptor) :  Aqui.

Se trata de uno de los ejemplos incluidos en la plataforma de análisis Intezer. Si alguno no la conoce, a grandes rasgos, “trocean” el malware de tal forma que son capaces de identificar el origen de esos trozos de código. Por lo que para detectar actores que se encuentran detrás de una muestra viene al dedillo.

Muestra de WannaCry

Lo dicho, veamos que información hay en esta página y cómo obtener lo mismo con radare2.

Analizar Malware Wanncry con Radare2

Vemos información relativa al ejecutable y una serie de cadenas. Con radare2 podemos obtener esos datos con los siguientes comandos: “i/iI” (información del fichero), “iV” (version_info), “izz” (strings):

Comandos Radare2

Cambiamos de plataforma y vamos a esta otra, con el mismo fichero. Tenemos un menú por donde navegar y tener la información necesaria del fichero.

264b6a2d214586ed9b213d29b2262046

Esta información ya habíamos visto como obtenerla. Pasamos a la cabecera del fichero:

Muestra cabecera

Con el comando “iH” (información de la cabecera) podemos verlo.

Cabeceras Radare2

Pasamos a las secciones:

Secciones de Malware Wannacry

Utilizamos los comandos: “iS md5,sha1,sha256” (información de las secciones y sus respectivos hashes) y por otro lado “iS=” (información de las secciones con barras)

Muestra Secciones Radare2

Llegamos a los “imports” o funciones que se cargan y que va a utilizar el binario (pueden utilizar más cargándolas en tiempo de ejecución y no aparecer aquí).

Más informacion Malware estatico con Radare2

Para ver cuales se cargan utilizamos el comando “ii” (información de los import). Vemos la DLL y el nombre de la función que se carga, además de otros datos.

ii Radare2

Si queremos buscar alguna en concreto: ii~FUNCION .Podemos buscarlo “case sensitive” o “insensitive”.

ii Radare2 casesensitive

Ficheros de Recursos:

Fichero de Recursos Malware Wanncry

Los buscamos con “iR”:

iR Radare2
iR Type Radare2

hybrid-analysis.com

Pasamos a otra plataforma y mismo fichero y vemos que datos aún no tenemos localizados:

WannaCry Hybrid Analysis

Compiler/Packer: Microsoft visual C++ 5.0. Para obtener este tipo de dato podemos jugar con reglas yara.

Necesitaremos ejecutar los siguientes comandos para poder utilizar yara en radare2 .

r2pm -i yara-lib
r2pm -i yara

Reglas Yara Radare2

Después de completar los requerimientos necesarios, ya podemos utilizarlo.

Requisitos Yara Radare2

Localizamos nuestra regla con los “packers” y/o “compilers”, lo añadimos y buscamos coincidencias.

Compiler Yara Radare2
Microsoft_Visual_Cpp_50

Esa coincidencia corresponde con “Microsoft_Visual_Cpp_50”. El resto de datos ya los hemos visto anteriormente:

Resto de informacion Wannacry con Radare2

Si nos vamos a la parte de indicadores, se apoyan en plataformas como VirusTotal o reglas yara (hemos visto cómo utilizarlas desde radare2).

Incicadores Maliciosos de Wanncry

Nos quedamos con este dato por el momento:

Caracteristicas inusuales
izz Radare2

A la hora de buscar API sospechosas es mejor buscarlo como cadenas, lo digo porque muchas veces no están en los imports, se cargan en tiempo de ejecución, esto es un truco muy común, LoadLibrary + GetProcAddress, que vereis muchas veces y esa función que va a utilizar está como un string o cadena. No la busquéis en los imports, se escapará.

Imaginaros que veis esto y queréis investigar un poco más en el binario:

Wana Decrypt0r 2.0

Buscamos “Wana Decrypt0r 2.0” (izz~+Wana Decrypt0r 2.0), ¿desde donde se llaman? (axt@0x00420cd0), nos posicionamos allí (s 0x00420cd0, para el primer caso, idem siguientes), pdf para imprimir el contenido del desensamblado por pantalla, al no ser una función, le decimos que lo trate como tal (af) y volvemos a imprimirlo.

Wana Decrypt0r

Y vemos que hace esa función a la que se le pasa como parámetro esa cadena que andábamos buscando.

Cadena buscada

Imprimimos su contenido (“pdf @ fcn.0040b620”), como veis trata de buscar esa ventana, con ese título.

Llamadas a VirusTotal WannaCry

En todas las plataformas de análisis online vienen referencias a Virus Total, no podemos obviar esta parte, ya que además de la detección de más de 60 antivirus, podemos observar el comportamiento del malware en diferentes sandboxes. Por lo que esa información vendría de perlas tenerla a mano desde radare2.

Podemos cargar cualquier script que tengamos desde radare2, ya lo sé, es ejecutar algo externo y no viene con la herramienta, lo mismo ocurría con las reglas yara. Lo que quiero que veais es que si algo no está integrado, siempre se puede buscar una solución.

VTscan Python

Por ejemplo, podemos cargar un script que con el hash como parámetro nos diga el número de detecciones que hay así como el enlace de una de las sandboxes utilizadas donde se ve el comportamiento que os he mencionado antes.

Pasamos a identificar las funciones existentes, para ello tecleamos “afl”.

afl Radare2

Imaginaros que queréis saber cuáles de ellas se utilizan más veces, esto es muy útil en el caso de funciones que descifran cadenas, por poner algún ejemplo, utilizad “afll” y saldréis de dudas.

Como podéis ver existe la función “main”. Por defecto, cuando cargamos el binario aterrizamos en el entrypoint (“entry0”).

ir Radare2

Podemos ver varias formas de obtener un desensamblado. Con “pdc” tendríamos una sintaxis tipo C. Con “pdg” el desensamblado de Ghidra. Este último hay que instalarlo, no viene por defecto. Para ello ejecutad los comandos:

r2pm update
r2pm -ci r2ghidra

También podemos sacar gráficos al estilo IDA:

agf Radare2

Comandos Radare2

El resumen de los comandos que hemos visto hasta ahora sería:

  • “i/iI” (información del fichero)
  • “iH” (cabecera PE)
  • “iV” (version_info)
  • “it” (hashes principales del binario)
  • “iS md5,sha1,sha256” (secciones con hashes)
  • “iS=” (secciones con bar)
  • “ii” (imports)
  • “iR” (información de los recursos)
  • “izz” (strings)
  • “yara add ./peid.yar” (añadimos fichero de reglas yara para la identificación de compiladores y empaquetadores)
  • “yara scan” (búsqueda de coincidencias con la regla yara añadida)
  • “!python VTScan.py bf293bda73c5b4c1ec66561ad20d7e2bc6692d051282d35ce8b7b7020c753467” (consulta en VT sobre malware)
  • “pdc“ (desensamblado estilo C)
  • “pdg“ (desensamblado estilo C de ghidra)
  • “agf“ (grafico estilo IDA)

Script Analisis de Malware by Rafa

Podemos crear un simple script con Python y mostrar esta misma información, os adelanto que la salida del fichero será grande, ya sólo el comando para la obtención de las cadenas es gigantesco.

Utilizaremos para ello r2pipe (“pip install r2pipe”). Perdonadme por el script, deprisa y corriendo es lo que sale :D Es muy mejorable, parseando la salida (muchos comandos de radare2 pueden terminar en j y su salida es en formato json) y crear una página html, por ejemplo, en definitiva, lo que se os ocurra.

import r2pipe
import sys
import os
import re

def cr():
    print '\n'

def use():
    print "Simple Malware Analysis with Radare2 and r2pipe - by Rafa"
    print "Use: \"" + sys.argv[0] + "\" \"<binary.exe>\""
    sys.exit(1)

if len(sys.argv) != 2:
    print ("You need an argument to filename")
    use()

path = sys.argv[1]

if os.path.exists(path):
    path = sys.argv[1]
    r2=r2pipe.open(path)
    pe = r2.cmd("e file.type").split('\n')[0]
    if pe not in ('pe','elf'):
        print  "The file \"" + path + "\" is not a PE/ELF"
        use()

    arch = r2.cmd("e asm.arch").split('\n')[0]
    r2.cmd("e asm.arch = " + arch)
    r2.cmd("aaa")
    r2.cmd("e scr.rows        = 100")
    r2.cmd("e scr.columns     = 80")
    r2.cmd("e scr.utf8        = true")
    r2.cmd("e asm.emu         = false")
    r2.cmd("e asm.section     = true")
    r2.cmd("e asm.section.col = 14")
    sha256sum = r2.cmd("it~sha256[1]")
    print ("\nInformation File\n"+"=" * 80)
    info = r2.cmd("i")
    print info.encode('utf-8')
    print ("\nInformation Headers\n"+"=" * 80)
    infoH = r2.cmd("iH")
    print infoH.encode('utf-8')
    print ("\nInformation VersionInfo\n"+"=" * 80)
    infoV = r2.cmd("iV")
    print infoV.encode('utf-8')
    print ("\nHashes\n"+"=" * 80)
    hashes = r2.cmd("it")
    print hashes.encode('utf-8')
    iS = r2.cmd("iS").replace('[Sections]',("\nSections\n"+"=" * 80))
    print iS.encode('utf-8')
    print ("\nEntropy\n"+"=" * 80)
    iSe = r2.cmd("iS md5,sha1,sha256")
    print iSe.encode('utf-8')
    iSeB = r2.cmd("iS=")
    print iSeB.encode('utf-8')
    print ("\nResources\n"+"=" * 80)
    iR = r2.cmd("iR")
    print iR.encode('utf-8')
    ii =  r2.cmd("ii").replace('[Imports]',("\nImports\n"+"=" * 80))
    print ii.encode('utf-8')
    print ("Functions\n"+("=" * 80)+"\n")
    afl = r2.cmd("afl")
    print afl.encode('utf-8')
    izz = r2.cmd("izz").replace('[Strings]',("\nStrings\n"+"=" * 80))
    print izz.encode('utf-8')
    print ("Graphics\n"+("=" * 80)+"\n")
    agf = r2.cmd("agf")
    print agf.encode('utf-8')
    print ("Packers/Compilers\n"+("=" * 80)+"\n")
    packer = r2.cmd("yara add ./peid.yar")
    packer = r2.cmd("yara scan")
    print packer.encode('utf-8')
    print ("Virus Total Information\n"+("=" * 80)+"\n")
    VTinfo = r2.cmd("!python VTScan.py "+sha256sum)
    print VTinfo.encode('utf-8')

    urls = [
        re.compile("((http|ftp|mailto|telnet|ssh)(s){0,1}\:\/\/[\w|\/|\.|\#|\?|\&|\=|\-|\%]+)+", re.IGNORECASE | re.MULTILINE)

    print ("URLs\n"+("=" * 80)+"\n")
    for findurl in urls:
        for izzfound in findurl.findall(izz, re.IGNORECASE | re.MULTILINE):
            for url in izzfound:
                if len(url) > 8 and url:
                    print (url)

    cr()

    suspicious =
"RegCloseKey|GetUserNameA|RegCreateKeyW|CopyFileW|GetDriveTypeW|LoadLibraryA|GetFileAttributesA|FindFirstFileW|CopyFileA|GetFileAttributesW|GetModuleFileNameA|GetStartupInfoA|FindNextFileW|GetFileSize|CreateDirectoryA|DeleteFileA|GetProcAddress|CreateThread|GetModuleHandleA|FindFirstFileA|WriteFile|GetTempFileNameA|GetComputerNameA|FindNextFileA|TerminateProcess|CreateProcessA|Sleep|CreateFileA|GetTickCount|ShellExecuteExA|ShellExecuteA|FindWindowW|recv|socket|bind|send|WSAStartup|connect|closesocket|URLDownloadToFileA"
    print ("Suspicious\n"+("=" * 80)+"\n")
    for func in suspicious.split('|'):
        for izzline in izz.split('\n'):
	    if func in izzline:
                print ("[Suspicious]: " + func + " [" + izzline + "]")

    cr()

    antidbgs =
"CheckRemoteDebuggerPresent|FindWindow|GetWindowThreadProcessId|IsDebuggerPresen
t|OutputDebugString|Process32First|Process32Next|TerminateProcess|UnhandledExcep
tionFilter|ZwQueryInformation"
    print ("Antidebugs\n"+("=" * 80)+"\n")
    for func in antidbgs.split('|'):
        for izzline in izz.split('\n'):
	    if func in izzline:
                print ("[Antidebugs]: " + func + " [" + izzline + "]")

    cr()

else:
    print "The file \"" + path + "\" not exists!"
    sys.exit(1)```

Veamos la salida del script. Lo primero que vemos es la información del fichero:

Salida Script Malware Rafa

Seguido de la información de las cabeceras:

Informacion de cabeceras Malware script Rafa

El “Version Info”:

Version Info Script Analisis de Malware

Las secciones:

Secciones Info Script Analisis de Malware

Los recursos:

Recursos análisis de Malware

Los “imports”:

Imports Info Script Analisis de Malware by Rafa

Las funciones que son detectadas:

Funciones Info Script Analisis de Malware by Rafa

Las strings:

Strings Info Script Analisis de Malware by Rafa

Podemos ver todas las extensiones que buscaba para descifrar su contenido.

Extensiones Info Script Analisis de Malware by Rafa

O como nos informaba como los ficheros podían se descifrados si pasabas por caja, virtual, claro.

Descifrado Info Script Analisis de Malware by Rafa

Los gráficos, por defecto el entry0:

Grafico Info Script Analisis de Malware by Rafa

Los compiladores/empaquetadores y la información de Virus Total:

Compiladores Virus Total Info Script Analisis de Malware by Rafa

Las URLs y cadenas sospechosas:

URLs Sospechosas Info Script Analisis de Malware by Rafa

Trucos antidebug:

Trucos antidebug

Como habéis podido ver y leer, con un sencillo script en Python hemos accedido a la herramienta radare2, ejecutado una serie de comandos para obtener la misma información que aparece en cualquier plataforma de análisis online del tipo Sandbox.

Espero haberos dado una visión de lo que se puede hacer con herramientas como radare2 a la hora de analizar un malware cualquiera. Hay mucho más que ver, debugging, ESIL, etc. Quizás en otro POST.

Hasta otra!!