Módulo Radare2 para Yara

Desde el equipo de YaraRules Project nos gustaría presentaros un nuevo módulo que hemos desarrollado que permite utilizar la información que nos provee radare2 para crear firmas de Yara.

Ya hemos hablado en este blog de Yara (potente herramienta open-source para búsqueda de patrones en binarios) que además, nos permite ampliar sus funcionalidades a través del uso de módulos, bien usando los ya oficialmente distribuidos (PE, ELF, Cuckoo, Math, etc), bien diseñando nuestros propios módulos (como explica muy bien aquí la documentación de Yara).

Por otro lado, todos los que conocemos radare2 sabemos que es un framework de reversing muy versátil, open-source, y que entre otras muchas funcionalidades, nos permite obtener mucha información de un binario y además soporta tantos tipos de formatos de ficheros (ELF, Java Class, Mach-O, COFF, Gameboy, Nintendo Switch bins, SNES roms, WASM, Compiled LUA, PCAP files, etc.), que resulta difícil encontrar otra herramienta de estas características que lo haga.

Bien, hace unos meses a @plutec_net y a mí se nos ocurrió ponernos a cocinar la siguiente receta porque creíamos que podría salir un buen guiso de ella:

Radare2 versatility + Power of Yara = r2.c (Radare2 module for Yara)

Es decir, desarrollar un módulo que amplíe las capacidades de Yara haciendo uso de radare2. Aunque falta mucho que mejorar en el código, y seguro que en la documentación también, lo hemos publicado todo para que podáis usarlo si lo encontráis útil. El código podéis encontrarlo en el Github de YaraRules, y toda la documentación de cómo se usa junto con algunos casos de uso que se nos han ocurrido, aquí. Por supuesto, os invitamos a utilizarlo y reportarnos cualquier feedback que se os ocurra, así como a contribuir con el proyecto.

¿Qué información de toda la que me muestra r2 puedo usar para escribir firmas Yara?

Podemos utilizar prácticamente toda la información que nos genera rabin2 (“imports”, sections, “symbols” -exported symbols-, list archs, headers fields, binary info, libraries, etc.) y rahash2 (md5, sha1, sha256, sha384, sha512, crc16, crc32, md4, xor, xorpair, parity, entropy, hamdist, pcprint, mod255, xxhash…etc.)

¿Cómo hacemos funcionar el módulo?

Al no ser un módulo oficial, hay que hacer una instalación un poco más “especial” de Yara. En la sección de Instalación de la documentación viene todo detallado.

Hemos pensado en dos formas de funcionamiento:

  • Si queremos tirar las firmas contra una gran cantidad de samples, la forma más rápida es obtener en formato json la información que queremos extraer con r2 (habitualmente basta con añadir la opción -j a rabin2) y luego se le pasa a Yara de la siguiente forma:
    yara -x r2=report.json file.yar binary
  • La siguiente forma es mucho más transparente de cara al usuario y pasa por invocar automáticamente a radare2 desde Yara (gracias a r2pipe). Es un método más lento y estamos trabajando para intentar agilizarlo al máximo. La forma de uso es la que generalmente se usa en Yara:
    yara file.yar binary

Veamos algunos casos de uso para ejemplificar la utilización del módulo:

Side effects of Packing

El código ofuscado y empaquetado frecuentemente se caracteriza por presentar niveles altos de entropía. Además, el tamaño de las secciones también puede ser un interesante indicativo. Por ejemplo, si el vsize (virtual size, tamaño que ocuparía en memoria) es mucho mayor que el size (tamaño que ocupa en disco) es un indicativo de código empaquetado. En esta presentación de BlackHat lo explican muy bien con un ejemplo que hemos querido plasmar en una firma Yara usando nuestro módulo:

import "r2"
import "math"

rule difference_size_and_vsize {
  meta: 
    description = "Rule to detect binaries with a big difference between section size and section vsize (after unpack). Also, it includes a big entropy and executable flags"  
    author = "@plutec_net, @mmorenog"  
    reference = "Practical Malware Analysis. BlackHat. Kris Kendall and Chad McMillan. Page 52" 

  condition:  
    for any i in ( 0..r2.number_of_sections ) :  
      ((r2.section[i].vsize > r2.section[i].size*2) and 
      r2.section[i].flags contains "x" and  
      math.entropy(r2.section[i].paddr, r2.section[i].size) > 7) 

}

Como ven, es solo una aproximación, que probablemente dé muchos falsos positivos, pero que ejemplifica lo que pretendemos, que podríamos modelar comportamiento de código ofuscado/empaquetado a través de firmas Yara usando el módulo de radare2.

Detección de ficheros maliciosos basándonos en la entropía

Como hemos comentado en el ejemplo anterior los niveles de entropía del binario o en determinadas secciones pueden ayudarnos a identificar cierto tipo de código dañino. Podemos para ello crear firmas a medida para buscar los niveles de entropía que queramos estudiar e incluyo añadir otro tipo de condiciones a la firma. Por ejemplo:

import "r2"
import "math"

rule sections_entropy {
   condition:
     for any i in (0..r2.number_of_sections):
        (r2.sections[i].name contains “note.ABI_tag” and 
         math.entropy(r2.sections[i].paddr, r2.section_array[i].size > 1.5)
}

Resources & Languages

Otro ejemplo interesante de uso podría ser el siguiente. Por ejemplo si nos centrásemos en los “resources” del binario y estuviésemos interesados en saber si el idioma en el que están los de tipo “STRING” fuese ruso o chino, podríamos hacer una firma Yara como la siguiente y lanzarla contra un set de binarios en busca de esas características:

import "r2"

rule res_string_jap { 
  condition: 
    r2.resource("STRING", "LANG_RUSSIAN") or 
    r2.resource("STRING", "LANG_CHINESE") 
}

A lo mejor queremos afinar un poco más y solo queremos centrarnos en las que su size sea > 2KB:

import "r2"

rule resource { 
  condition: 
    for any i in ( 0..r2.number_of_resources ) :  
      (r2.resources[i].size > 2KB and 
      r2.resources[i].type == "STRING" and 
      r2.resources[i].lang contains "RUSSIAN" or
      r2.resources[i].lang contains "CHINESE") 

}

Búsqueda protecciones en un binario

Es posible que en algún momento determinado nos pueda interesar comprobar si un binario presenta ciertas protecciones como Canary, PIC (Position Indepent Code), NX (Non-executable stack) con lo que podemos hacer firmas Yara similares a la siguiente:

import "r2"

rule protections { 
  condition: 
    r2.info.canary == 1 and 
    r2.info.pic == 1 and
    r2.info.nx == 1      

}

En este enlace de la documentación pueden encontrar más casos de uso (como por ejemplo un modelado de un potencial keylogger, la detección de un determinado packer, creación de firmas reputacionales basadas en nombres de funciones habitualmente conocidas en malware -como ya os contamos en este post– ) así como en toda la documentación hemos intentado poner ejemplos de todo, y por supuesto les invitamos a que nos sugieran muchos más.

Comentaos de nuevo que seguimos trabajando en mejorar el módulo, en aprovecharlo para el desarrollo de nuevas firmas interesantes y recordaros que además de éste módulo, en YaraRules hay disponibles otras herramientas que hemos desarrollado para el “universo-Yara” como YaraRules Analyzer, en el que hemos llevado a la nube todas las firmas de Yara del repositorio, para que podáis testear vuestros binarios allí, o por ejemplo YaGo una interesante tool que nos convierte nuestras firmas Yara en formato json.

Finalizar agradeciendo a @pancake y toda la comunidad radare2 (especialmente a @newlog_ y @alvaro_fe :) su esfuerzo por facilitarnos en la medida de lo posible el trabajo de integración, a Victor @plusvic su apoyo y dedicación continua a mantener Yara y a todos los que formáis parte de @huntingmalware por vuestro feedback durante el camino.

Comments

  1. Me encantaría tener tiempo libre para probar estas cosas, la verdad es que cada vez que entro a los post que publicais, me entran ganas de probar lo que reflejais, pero no hay tiempo :S. Un saludo :).

  2. Muchas gracias Alberto por tu comentario! Te animo a que -sin prisa- busques el tiempo necesario para probar todas estas cosas que contamos en el blog si realmente te gustan , y que luego compartas con nosotros tus opiniones. No es fácil sacar tiempo libre pero poco a poco, lo importante es estar motivado para hacer el trabajo que te gusta.

    Gracias por leernos.

    Saludos,