¿Por qué JMP ESP en lugar de saltar directamente a la pila?

6

En primer lugar, lo siento si esta publicación no encaja exactamente aquí, o puede encajar mejor en RE. Podríamos moverlo si es necesario.

Entonces, estaba leyendo este writeup sobre un exploit in vulnserver (para aquellos que no lo sé, vulnserver es un programa diseñado con fallas en mente, esto es, para practicar técnicas de explotación)

En cierto punto, dice:

  

En este paso tenemos que revisar los registros y la pila. Tenemos que encontrar una manera de saltar a nuestro búfer para ejecutar nuestro código. ESP apunta al comienzo de la parte C de nuestro búfer. Tenemos que encontrar una instrucción JMP ESP o CALL ESP. ¡No olvide que la dirección no debe contener caracteres incorrectos!

Esto tiene sentido, pero; ¿No sería posible y más fácil saltar directamente a la pila ya que controlamos EIP? (Suponemos que ASLR y DEP están deshabilitados, por supuesto). Principalmente porque:

  1. ¿Cómo sabe que ESP apunta a su código de shell? ¿Por qué puntos ESP exactamente allí? ¿No debería apuntar al final de su Shellcode en su lugar?

  2. ¿Cómo se supone que esto funciona a través de reinicios o en diferentes computadoras?

Gracias.

    
pregunta Pedro Javier Fernández 16.04.2017 - 17:11
fuente

2 respuestas

6

Tu carga útil de exploits termina en la pila porque estás desbordando un búfer en la pila, y así es como obtienes el control de la dirección de retorno también.

ESP apunta directamente al inicio de su carga útil (después de la ejecución del ret en la función que está atacando) porque coloca la carga útil justo después de los 4 bytes que sobrescriben la dirección de retorno en la pila. ret coloca 4 (u 8) bytes en EIP, dejando que ESP apunte a la carga útil que sigue directamente.

Pero no sabe qué valor tendrá ESP en ese momento , debido al ASLR de la pila y porque una profundidad diferente de la pila de llamadas que conduce hasta este punto podría cambiar la dirección. Por lo tanto, no puede codificar una dirección de retorno correcta .

Pero si hay bytes que se decodifican como jmp esp o call esp en cualquier lugar en una dirección fija (no ASLRed) en la memoria del proceso , puede codificar que address como la dirección de retorno en tu exploit. La ejecución irá allí, luego a tu carga útil.

De hecho, este es a menudo el caso: algunas DLL no tienen ASLR habilitado para su código, y el código del ejecutable principal puede que tampoco esté ASLRed.

El código de

ASLR para el código de todos anula un ataque jmp esp , a menos que el atacante pueda hacer que el proceso de destino pierda direcciones.

Tenga en cuenta que para el código de 64 bits, es poco probable que pueda utilizar jmp rsp para los desbordamientos de búfer basados en cadenas, porque las direcciones de código contendrán algunos 0 bytes líderes .

Por lo tanto, jmp esp te ofrece un exploit mucho más confiable que adivinar repetidamente una dirección de retorno (con un gran trineo NOP).

Las adivinanzas repetidas bloquearán el proceso de destino cada vez que te equivoques, pero un jmp esp puede darte una alta probabilidad de éxito en el primer intento. Esto evitará dejar registros de fallos. También podría derrotar a un sistema de detección de intrusiones que busca procesos de servidor que fallan y bloquea las conexiones de su dirección IP o similar.

Tenga en cuenta que la instrucción de 2 bytes que está buscando puede aparecer como parte de otra instrucción cuando el programa se ejecuta normalmente o como datos estáticos (especialmente los datos de solo lectura en las páginas ejecutables). Así que solo necesita buscar la secuencia de 2 bytes, no el jmp esp en el desmontaje del programa. Los compiladores nunca usarán jmp esp , por lo que no encontrarás uno de esa manera.

Más generalmente , cualquier función que termine con un puntero de búfer en cualquier registro (por ejemplo, desde un memcpy o especialmente strcpy ) puede permitir un ataque ret2reg , buscando una instrucción jmp eax .

Esto puede funcionar en modo de 64 bits, donde las direcciones tienen algunos bytes de alto cero; Si strcpy 's al final de la escritura escribe ese byte de dirección alto para usted, el final de su cadena de explotación podría ser los bytes de dirección distintos a cero que sobrescriben la dirección de retorno en la pila.

En este caso, la carga útil ejecutable iría antes de la dirección de retorno, en el lugar del búfer donde la función deja un registro apuntando. (Por lo general, el comienzo del búfer si hay algún puntero útil al búfer en los registros).

    
respondido por el Peter Cordes 10.03.2018 - 04:31
fuente
4

Después de que un búfer se haya excedido, ESP tiene el código de shell. Se puede verificar en inmunidad, EIP tiene que apuntar a ESP. Mi comprensión es antes de la explotación, las DLL del sistema, deben usar ESP, dependiendo de cuándo se llaman las DLL.

Pero después de que se haya desbordado el búfer, EIP no tiene idea de a dónde apuntar. Tenga en cuenta que, los 4 bytes que pasamos a EIP pueden ser cualquiera de las direcciones [jmp ESP].

Así es como esto -

  1. Desbordar el búfer exactamente hasta EIP
  2. Pase la dirección [jmp ESP] a EIP
  3. El valor almacenado en ESP se ejecuta (NOP + Shellcode)

Escribí un exploit y utilicé variaciones de dirección en [jmp ESP] y cada vez que pude explotar la vulnerabilidad.

Aquí está el exploit.py, nota que estoy usando dll RPCRT. Pero podemos usar shell32.dll y otros dlls del sistema también.

enlace

Estoy usando shell bind shellcode con algunos NOP adicionales.

  

Por cierto, si el sistema operativo tiene algún tipo de protecciones o el compilador ha agregado algunas   Protecciones durante la compilación del código src original. Esto se convertirá en un   búsqueda del tesoro para encontrar la ubicación del shellcode. Luego necesitaremos usar varios saltos para llegar al código de shell.

Espero que ayude!

    
respondido por el Sangram Kesari Ray 31.05.2017 - 14:00
fuente

Lea otras preguntas en las etiquetas