Pregunta

Este es un código shell para explotar la vulnerabilidad desbordamiento de búfer. Se establece el setuid(0) y genera un shell usando execve(). A continuación se muestra la forma en que lo han interpretado:

xor    %ebx,%ebx       ; Xoring to make ebx value 0
lea    0x17(%ebx),%eax ; adds 23 to 0 and loads effective addr to eax. for setuid()
int    $0x80           ; interrupt
push   %ebx            ; push ebx
push   $0x68732f6e     ; push address // why this address only????
push   $0x69622f2f     ; push address // same question
mov    %esp,%ebx
push   %eax
push   %ebx
mov    %esp,%ecx
cltd                   ; mov execve sys call into al
mov    $0xb,%al
int    $0x80           ; interrupt

Puede alguien explicar claramente los pasos enteros?

¿Fue útil?

Solución

int es el código de operación para la activación de una interrupción de software. interrupciones de software están numeradas (de 0 a 255) y manipulados por el núcleo. En los sistemas Linux, de interrupción 128 (0x80) es el punto de entrada convencional para llamadas al sistema. El núcleo espera que los argumentos de llamada del sistema en los registros; En particular, el registro% eax identifica qué llamada que estamos hablando del sistema.

  1. Set% ebx a 0
  2. Calcular% ebx + 23 y almacenar el resultado en% eax (el código de operación es lea como "carga de dirección efectiva", pero no acceso a la memoria que está involucrado, esto es sólo una forma tortuosa de hacer una adición).
  3. llamada
  4. Sistema. % Eax contiene 23, lo que significa que la llamada de sistema es setuid. Que utiliza la llamada al sistema un argumento (el UID objetivo), que se encuentran en% ebx, que contiene convenientemente 0 en ese momento (que se estableció en la primera instrucción). Nota: a su regreso, los registros son sin modificar, a excepción de% eax que contiene el valor devuelto de la llamada al sistema, normalmente 0 (si la llamada fue un éxito)
  5. .
  6. Pulsar% ebx en la pila (que todavía es 0).
  7. Empuje $ 0x68732f6e en la pila.
  8. Empuje $ 0x69622f2f en la pila. Dado que la pila crece "abajo" y desde los procesadores x86 utilizan poco codificación endian, el efecto de las instrucciones de 4 a 6 es que% esp (el puntero de pila) ahora puntos en una secuencia de doce bytes, de los valores de 2f 2f 2f 62 69 6e 73 68 00 00 00 00 (en hexadecimal). Esa es la codificación de la cadena "// bin / sh" (con un cero de terminación, y tres ceros adicionales después).
  9. Mover% esp a EBX%. Ahora% ebx contiene un puntero a la cadena "// bin / sh" que fue construido anteriormente.
  10. Pulsar% eax en la pila (% eax es 0 en ese punto, que es el estado de regresar de setuid).
  11. Pulsar% ebx en la pila (puntero a "// bin / sh"). Instrucciones de 8 y 9 se basan en la pila de una serie de dos punteros, siendo el primero el puntero a "// bin / sh" y el segundo un puntero NULL. Esa matriz es lo que la llamada al sistema execve usará como segundo argumento.
  12. Mover% esp a% ecx. Ahora% ecx puntos en la matriz construida con instrucciones 8 y 9.
  13. Regístrese extender% eax en% EDX: EAX%. cltd es la sintaxis AT & T por lo que la documentación de Intel llaman cdq. Desde% eax es cero en ese punto, este conjuntos% EDX a cero también.
  14. Set% al (el byte menos significativo de% eax) a 11. Desde% eax era cero, todo el valor de% eax es ahora 11.
  15. llamada
  16. Sistema. El valor de% eax (11) identifica la llamada al sistema como execve. execve espera tres argumentos, en% ebx (puntero a una cadena con el nombre del archivo para ejecutar),% ecx (puntero a un array de punteros a cadenas, que son los argumentos del programa, el primero es una copia del nombre del programa, a ser utilizado por el propio programa invocado) y% edx (puntero a una matriz de punteros a cadenas, que son las variables de entorno;. Linux tolera que el valor a ser NULL, para un entorno de vacío), respectivamente

Así que el código llama primero setuid(0), a continuación, llama execve("//bin/sh", x, 0) donde los puntos x a una serie de dos punteros, primero es un puntero a "// bin / sh", mientras que el otro es NULL.

Este código es bastante enrevesado porque quiere evitar ceros: cuando está montado en opcodes binarios, la secuencia de usos de instrucciones sólo distintos de cero bytes. Por ejemplo, si la instrucción 12 había sido movl $0xb,%eax (ajuste de la totalidad de% eax a 11), entonces la representación binaria de que opcode habría contenido tres bytes de valor 0. La falta de cero marcas que la secuencia se puede usar como el contenido de una cero-cadena terminada C. Esto es para atacar a los programas de buggy por desbordamientos de búfer, por supuesto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top