Apéndice A - Métodos de Protección de Binarios

a. Introducción
Los sistemas operativos Unix/Linux, *BSD se consideran por los especialistas como avanzados, seguros y estables debido a su diseño de arquitectura y gestión de procesos.

Las distribuciones actuales tienen soporte para varios tipos de ejecutables como AOUT (formato original de Unix), COFF (Unix System V), ECOFF (Mips/Alfpha), XCOFF (IBM RS/6000, AIX) y finalmente ELF (el sucesor de COFF, que ofrece múltiples secciones y valores posibles de 32 o 64 bits). Mientras que los sistemas operativos win32 tienen MZ (dos), NE (Windows 3.xx) y PE (Win9x/NT).

La popularidad y el enfoque comercial de sistemas win32 obligó a las empresas desarrolladoras de software invertir fondos y horas en protección de sus aplicaciones, para evitar obligar a los usuarios comprar el software. Desde el principio los especialistas en ingeniería inversa conseguían, por placer o por negocio, evitar los métodos de protección de los ejecutables que bajo win32 ya entonces tenían múltiples técnicas de protección. En actualidad un fichero ejecutable bajo Windows (PE) puede estar perfectamente cifrado, empaquetado, ofuscado y wrappeado al visa versa a la hora de ejecución lo que muestra la evolución de un binario simple hacía un ejecutable propiamente protegido, lo que proporciona la seguridad a la empresa desarrolladora que su software no podrá ser utilizado de forma ilegal, por lo menos por el público general.

Y lo único (que generalmente se conoce) que podemos hacer actualmente con un binario ELF es quitarle la tabla de símbolos o en otras palabras "strippearlo" que que no ofrece ningún tipo de protección.

Existen pocas herramientas de protección, son experimentales y se conocen/utilizan solo por los hackers de nivel alto medio-alto. A la hora de realizar un análisis forense, nos encontraremos con binarios que el intruso ha ido dejando en el sistema y necesitaríamos saber las funciones de cada uno de ellos, teniendo en cuenta que ejecución de binarios desconocidos puede provocar un desastre, si no estamos seguros de la función de los mismos.

[Subir]

b. Métodos de Protección
En las investigaciones rutinarias de casos de "defacements" de páginas web o de utilización de la máquina comprometida como cluster DDoS no es frecuente encontrar binarios protegidos ya que la mayoría de herramientas están circulando por la red de forma abierta. Mientras que en los compromisos de sistemas importantes como de Bancos, Líneas Aéreas o Universidades, el nivel de intruso es tecnológicamente y intelectualmente superior, por lo tanto también lo son sus herramientas. Hasta que no sepamos el propósito de cada uno de las herramientas del intruso no podremos concluir la investigación con éxito.

Podemos encontrar siguientes métodos de protección de binarios en este caso, según el nivel del atacante y tipo de herramienta utilizada. Puede que se utilicen de forma individual o de forma combinada para complicar el trabajo del investigador.

UPX [3] - "Ultimate Packer for eXecutables", los intrusos con un nivel de conocimientos bajo o medio utilizan compresor de ejecutables UPX como una herramienta de protección de sus aplicaciones. Este software tiene soporte para reducir el tamaño de binarios de tipo dos/exe, dos/com, dos/sys, djgpp2/coff, watcom/le, elf y etc... a través de las funciones de la librería UCL escrita en ANSI C, por lo tanto ofuscando su contenido a nivel superficial.

Si observamos el output del comando strings vemos que es fácilmente detectable por la cadena de texto "$Id: UPX 1.22 Copyright (C) 1996-2002 the UPX Team. All Rights Reserved. $" en caso de que UPX no ha sido modificado. En otros casos cuando el intruso puso su empeño en modificar la fuentes de UPX para confundir (aun mas) al administrador el binario sigue perfectamente reconocible observando las cadenas "/tmp/upxAAAAAAAAAAA", "/prof", etc... en el fichero. Para desempaquetar el binario debemos instalarnos UPX y ejecutar el siguiente comando:

[ervin@activalink.com ervin]$ ./upx -d <fichero empaquetado>

BurnEye [4] - Este tipo de protección se utiliza por los intrusos con nivel de conocimientos medio, medio-alto, que conocen la estructura de binarios ELF. BurnEye ofrece 3 niveles de protección de binarios ELF por capas: ofuscación de código, cifrado de aplicación a través de contraseña y técnica de OS fingerprinting.

Nivel 1. El primer nivel de protección realiza un cifrado del binario y utiliza la técnica de inyección de código dentro del binario ELF. El código es un motor de descifrado que a la hora de ejecutar el programa descifra su contenido y lo ejecuta. Podemos detectar si el binario está protegido con el primer nivel de BurnEye si su output de strings contiene la cadena "TEEE burneye - TESO ELF Encryption Engine". En caso de que el intruso haya modificado las fuentes de BurnEye y no se observe la cadena de texto en el output, se puede detectar ese nivel de protección a través de GDB. Esa protección implementa además una trampa para debuggers que utilizan llamada de sistema ptrace():

[ervin@activalink.com dev]$ gdb ./<binario encriptado con burneye nivel    1> 
   GNU gdb 5.2
   Copyright 2002 Free Software Foundation, Inc.
   [...]
   This GDB was configured as "i686-pc-linux-gnu"...(no debugging symbols    found)...
   (gdb) r
   Starting program: /dev/validate_MoD 
   warning: shared library handler failed to enable breakpoint
Program received signal SIGTRAP, Trace/breakpoint trap.
   0x053714c7 in ?? ()
   (gdb) 

Normalmente el SIGTRAP en binarios protegidos con BurnEye suele estar situado en 0x053714c7. Ese nivel de protección de binarios puede ser superado realizando un dump de memoria, con herramienta memdump y extracción manual del motor de cifrado (Ver [5] para más información).

Nivel 2. El segundo nivel de protección de binarios es más completo que el anterior. Su funcionamiento utiliza la misma técnica de inyección de código dentro de ELF y cifrado (wrapping). Sólo que en este caso el motor que se inserta dentro del binario tiene capacidad de cifrar y descifrar información, realizando una comprobación por contraseña como clave de cifrado (SHA1). Una vez la clave ha sido aceptada el nivel de control utiliza RC4 para descifrar el binario original.

Para detectar la diferencia entre el nivel 1 y nivel 2, hay que ejecutar el programa. Por lo tanto hay que asegurarse que no es ni sGID, sUID. Si lo es hay que crear un usuario con privilegios muy limitados, cambiar la pertenencia del fichero y quitarle sGID y sUID. A continuación se puede intentar obtener el listado de librerías dinámicas utilizadas por el binario:

[ervin@activalink.com dev]$ ldd ./void 
   ldd: /lib/ld-linux.so.2 exited with unknown exit code (139)

Si se produce el output similar, entonces queda confirmado que el binario está cifrado y la única opción que tenemos es intentar ejecutarlo, pero sólo desde la cuenta del usuario con menos privilegios, por razones de seguridad.

[noone@activalink.com dev]$ ./void 
   password: 
   invalid key

Una vez ejecutado el fichero vemos que nos solicita la contraseña y si pulsamos Enter, nos informa que la clave no es correcta. Ahora estamos seguros que el fichero está cifrado con BurnEye con protección de Nivel 2. Este nivel de protección es fácil de romper como el anterior, será necesario utilizar las técnicas de debugging avanzadas y buen conocimiento de ensamblador [6]. Se aconseja utilizar un debugger que no utilice llamada de sistema ptrace(), para intentar saltar la protección de binarios protegidos [7]. La interacción entre el motor de cifrado con el binario original es todavía débil por lo tanto teóricamente se puede utilizar técnicas de "unwrapping" pero si la contraseña ha sido elegida bien por el intruso, el binario es casi indescifrable.

Nivel 3. Esta capa de protección tiene un modo de funcionamiento diferente a los niveles anteriores. Este nivel asegura que el binario no pueda ser ejecutado en otro sistema que no sea el de máquina dónde ha sido encontrado (utilizado). El binario incluye internamente un "sello" del equipo permitido. Y cada vez que se ejecuta el motor de cifrado interno busca el "sello" de la máquina y si no coincide con el "fingerprint" almacenado dentro del algoritmo, no permite la ejecución de la aplicación. El "sello" es único en cada máquina que se calcula a través de un algoritmo propio desarrollado por TESO; utiliza valores sysinstall, procpci, proccpu, procmem, procroute, procpartitions (/proc en general) para generar un único "sello" (fingerprint). Los binarios protegidos con éste nivel de BurnEye heredan las mismas pruebas que los niveles anteriores: output strings, breakpoint trap, etc.

Si estamos estudiando el binario, doy por sentado que nos encontramos en una estación de análisis y no en el equipo comprometido, por lo tanto si intentamos ejecutar la aplicación protegida con este nivel de BurnEye en un entorno seguro (no sUID, no sGID y como usuario con privilegios limitados) obtendremos el siguiente output:

[chrooted@beta.activalink.com chrooted]# ./output 
   invalid fingerprint

Es casí imposible de obtener el binario original si no nos encontramos en la máquina con un sello reconocido por el ejecutable ya que el fichero original está cifrado y se descifra con el stream cipher RC4.

Elfe [8] - Este tipo de protección se utiliza por los intrusos con nivel de conocimientos medio, medio-alto, que conocen la estructura de binarios ELF. Elfe ofrece 1 nivel de protección de binarios ELF a través de RC4. A través de esta herramienta se puede especificar cual de las secciones del binario (.text, .data, .rodata) se quiere proteger. Esa aplicación funciona sólo bajo la arquitectura x86 y únicamente puede proteger binarios producidos por el compilador gcc y stripeados, tiene soporte para binarios linkados de forma estática así como dinámica.

Comparando esa herramienta con las anteriores, podemos decir que ofrece menor nivel de protección que BurnEye y mayor que UPX. Se puede detectar fácilmente que el binario está cifrado con Elfe ya que el output de la utilidad strings informa en las últimas líneas un texto similar:

password: 
   Done. Returning to program.
   QZ^&

También podemos encontrar en el output cadenas de texto de las secciones que no han sido cifradas, ya que Elfe se limita a cifrar sólo .text, .data, .rodata máximo y si no se especifica sólo la sección .text. Las herramientas strace, objdump, de la colección de herramientas binutils nos podrán ser de utilidad. Si se ejecuta la aplicación sin saber la contraseña correcta la aplicación puede colgarse, o producir SIGSEGV Segmentation Fault.

Aunque el método de protección no implementa detección de debuggers, el nivel de dificultad de descifrado de binarios protegidos con Elfe es similar al 2º y 3º nivel de BurnEye (Para más información ver [9]).

[Subir]


[Anterior] [Menu Principal] [Siguiente]