2009-06-29 11 views
12

¿Cómo protege Windows contra un subproceso en modo de usuario al hacer una transición arbitraria de la CPU al modo kernel?¿Cómo protege Windows la transición al modo kernel?

yo entendemos que estas cosas son ciertas:

  1. hilos de modo de usuario realmente hacer la transición a modo de núcleo cuando una llamada al sistema se realiza a través NTDLL.
  2. La transición al modo kernel se realiza mediante instrucciones específicas del procesador.

¿Qué tiene de especial estas llamadas de sistema a través de NTDLL? ¿Por qué el hilo del modo de usuario no puede falsificarlo y ejecutar las instrucciones específicas del procesador para pasar al modo kernel? Sé que me falta una pieza clave de la arquitectura de Windows aquí ... ¿qué es?

+0

El subproceso de modo de usuario puede simularlo, pero ¿cómo sería eso diferente a usar ntdll.dll? Agregue a las preguntas más información sobre por qué esto le preocupa. –

+2

Creo que al OP le preocupa la transición al anillo 0 y luego ejecutar código no-O/S arbitrario mientras está en el anillo 0. – ChrisW

+1

Windows realiza la validación en sus parámetros expuestos (a modo de usuario). No puede * pasar datos inválidos sin que lo sepa. Sí, hay casos de esquina pasados ​​por alto. Solo busca vulnerabilidades de escalada de privilegios locales. Hay un montón de ellos – unixman83

Respuesta

17

Probablemente esté pensando que el subproceso que se ejecuta en modo de usuario está llamando al timbre 0, pero eso no es lo que realmente está sucediendo. El subproceso de modo de usuario está provocando una excepción captada por el código Ring 0. El subproceso de modo de usuario se detiene y la CPU cambia a una secuencia kernel/ring 0, que luego puede inspeccionar el contexto (por ejemplo, pila de llamadas y registros) del subproceso de modo de usuario para descubrir qué hacer. Antes de syscall, realmente era una excepción en lugar de una excepción especial específicamente para invocar el código del anillo 0.

Si sigue los consejos de las otras respuestas y lee the Intel manuals, verá que syscall/sysenter no toma ningún parámetro: el sistema operativo decide qué sucede. No puedes llamar a un código arbitrario. WinNT usa números de función que asignan a qué función de modo kernel se ejecutará el código de modo de usuario (por ejemplo, NtOpenFile es fnc 75h en mi máquina con Windows   XP (los números cambian todo el tiempo; uno de los trabajos de NTDll es mapear un llame a un número fnc, colóquelo en EAX, señale EDX a los parámetros entrantes y luego invoque a sysenter).

9

Las CPU Intel imponen la seguridad utilizando lo que se llama 'Anillos de protección'.

Hay 4 de ellos, numerados de 0 a 3. El código que se ejecuta en el anillo 0 tiene los privilegios más altos; puede (prácticamente) hacer lo que le plazca con su computadora. El código en el anillo 3, por otro lado, siempre está ajustado; solo tiene poderes limitados para influir en las cosas. Y los anillos 1 y 2 actualmente no se usan para ningún propósito.

Un hilo que se ejecuta en un anillo con mayor privilegio (como el anillo 0) puede pasar al anillo de privilegios inferior (como el anillo 1, 2 o 3) a voluntad. Sin embargo, la transición al revés está estrictamente regulada. Así es como se mantiene la seguridad de los recursos con alto nivel de privilegios (como la memoria), etc. Naturalmente, su código de modo de usuario (aplicaciones y todo) se ejecuta en el anillo 3 mientras que el código del sistema operativo se ejecuta en el anillo 0. Esto asegura que los hilos del modo de usuario

Para obtener detalles sobre cómo se implementa todo esto, puede leer el artículo this. Además, es posible que desee revisar los Manuales de Intel, especialmente el Vol. 1 y el Vol. 3A, que puede descargar here.

Esta es la historia de los procesadores Intel. Estoy seguro de que otras arquitecturas tienen algo similar.

+2

La mayoría de los otros procesadores solo molestan con dos niveles de privilegio esencialmente equivalentes en efecto a los Anillos x86 0 y 3. Los anillos 1 y 2 probablemente parecían una buena idea en ese momento, pero resultaron no agregar ningún valor por la complejidad que costaban. – RBerteig

+1

IIRC Windows solo usa 2 anillos porque eso es todo lo que admiten las arquitecturas RISC. Como querían soportar RISC con la misma arquitectura básica, solo se usan los anillos x86 extremos. – noctonura

7

Creo que (puedo estar equivocado) que el mecanismo que se utiliza para la transición es simple:

  • código en modo usuario ejecuta un software de interrupción
  • Este (interrupción) hace que una rama de una ubicación especificado en la tabla de descriptores de interrupción (IDT)

Lo que impide que el código en modo de usuario usurpe esto es el siguiente: debe tener privilegios para escribir en IDT; así que solo el núcleo puede especificar qué sucede cuando se ejecuta una interrupción.

+0

Big chris respondiendo al joven Chris. –

+0

Así es como * usa * para funcionar, pero la respuesta de Tony Lee es mucho más cercana a lo que Windows hace hoy. –

+1

Me salté la parte sobre IDT/cómo la CPU sabe por dónde empezar a ejecutar, así que esto también es interesante de incluir. –

4

El código que se ejecuta en el modo de usuario (Anillo 3) no puede cambiar arbitrariamente al modo Kernel (Anillo 0). solo puede hacerlo usando rutas especiales - jump gates, interrupts, y sysenter vectores. Estas rutas están altamente protegidas y la entrada se borra para que los datos incorrectos no puedan (no deberían) causar un mal comportamiento.

Todo esto es configurado por el kernel, usualmente al inicio. Solo se puede configurar en el Modo Kernel para que el Usuario-Mo de code no puede modificarlo.

3

Probablemente sea justo decir que lo hace de forma (relativamente) similar a lo que hace Linux. En ambos casos, va a ser específico de la CPU, pero en x86 probablemente sea una interrupción de software con la instrucción INT o mediante la instrucción SYSENTER.

La ventaja de ver cómo lo hace Linux es que puede hacerlo sin una licencia de origen de Windows.

El userspace source part is here here a LXR y la kernel space bit - mira entry_32.S y entry_64.S

Bajo Linux en x86 existen tres mecanismos diferentes, int 0x80, syscall y SYSENTER.

Una biblioteca que está construida en tiempo de ejecución por el kernel llamado vdso es llamada por la biblioteca C para implementar la función syscall, que utiliza un mecanismo diferente dependiendo de la CPU y qué sistema es. El kernel tiene controladores para esos mecanismos (si existen en la variante de CPU específica).

Cuestiones relacionadas