2012-09-04 18 views
5

que lea este artículo: http://static.patater.com/gbaguy/day3pc.htm¿Qué pasaría si se cambia el registro del segmento CS?

Incluye la sentencia

Nunca cambies CS !!

Pero, ¿qué pasaría exactamente si modificó el registro de segmentos CS? ¿Por qué es tan peligroso?

+2

'CS' = segmento de código. Supongo que cambiarlo es equivalente (en cierto sentido) a un 'jmp' pervertido. – valdo

+5

Ese documento parece bastante poco fiable: "¡NO CAMBIE NUNCA' CS' !!, pero puede leer 'CS' como:' mov ds, cs'; poner el valor de 'CS' en' D'S. " Bueno, en x86 no hay instrucciones tales como 'mov ds, cs' ni ningún otro' mov segreg, segreg'. Para leer el valor de 'cs' puedes usar' mov reg, cs; mov ds, reg' (donde 'reg' puede ser' ax', 'bx',' cx' etc ...), o 'push cs; pop ds'. Además, si decide no * ever * cambiar 'cs', todas las llamadas de interrupción están fuera de cuestión (por ejemplo, servicios de BIOS, DOS y Linux). http://web.itu.edu.tr/kesgin/mul06/intel/instr/mov.html – nrz

+1

@nrz: No hay tal cosa como "servicios de Linux" accesibles a través de llamadas 'lejos' (las interrupciones/llamadas de sistema funcionan de manera diferente, aunque esto conlleve un cambio en' cs ', el _caller_ no puede controlar el destino de' cs', eso lo decide el SO al configurar las entradas IDT/syscall msrs). Ack con todo lo demás, obviamente 'cs' _ puede_ cambiarse, solo que a menos que el segmento de código de destino exista y esté configurado de tal manera que el' eip' objetivo sea alcanzable, cualquier llamada de ese tipo causará una falla '# GP' y la aplicación abortará –

Respuesta

7

cs es el segmento del código. cs:ip, que significa cs junto con ip (puntero de instrucción) apunta a la ubicación de la siguiente instrucción. Por lo tanto, cualquier cambio a cs o ip o ambos cambia la dirección desde donde se buscará y ejecutará la siguiente instrucción.

se le cambie cs con un (salto de longitud) jmp, call (llamada de larga duración), retf, int3, int o iret. En 8088 y 8086 pop cs también está disponible (código de operación 0x0F). pop cs no funcionará en 186+, en el que el código de operación 0x0F está reservado para instrucciones multibyte. http://en.wikipedia.org/wiki/X86_instruction_listings

No hay nada intrínsecamente peligroso en el salto largo o la llamada larga. Solo tienes que saber dónde saltas o llamas y, en modo protegido, debes tener suficientes privilegios para hacerlo. En el modo real de 16 bits (por ejemplo, DOS) puede saltar y llamar a la dirección que desee, por ejemplo. jmp 0xF000:0xFFF0 establece cs a 0xF000 y ip a 0xFFF0, que es la dirección de inicio del código de BIOS, y por lo tanto reinicia la computadora. Diferentes direcciones de memoria tienen diferentes códigos y causan diferentes tipos de resultados, en teoría todo puede suceder (si ingresas al código del BIOS utilizado para formatear el disco duro, con valores válidos de registro y/o pila, entonces el disco duro se formateará 'de acuerdo a lo pedido'). En la práctica, jmp y call a la mayoría de las direcciones probablemente resulten en código de operación no válido o alguna otra excepción (división por cero, desbordamiento de división, etc.) muy pronto.

+0

Cambiar solo 'cs' suele ser incorrecto. Normalmente, tanto 'cs' como' xip' cambian juntos o simplemente 'xip' cambia. –

+3

@AlexeyFrunze Bueno, la única manera de cambiar solo 'cs' sin cambiar/configurar' ip'/'eip' /' rip' es 'pop cs', que está disponible solo en 8088 y 8086. En 186+ puedes ' t cambie 'cs' sin cambiar/configurar también' ip'/'eip' /' rip'. 'pop cs' podría usarse posiblemente en código de ofuscación dirigido para 8088/8086 (o emulador 8088/8086). – nrz

0

En modo protegido y modo largo (es decir, no en el modo de 16 bits), los registros de segmento que incluyen CS ya no son solo 4 bits adicionales de dirección. Se indexan en la tabla de descriptores de segmento, con una base + límite (base normal = 0 límite = 4GiB, es decir, un modelo de memoria plana), pero también con otros atributos.

El descriptor de segmento de código determina el modo de CPU (por ejemplo, el modo de compatibilidad de 32 bits frente al modo de 64 bits). En un kernel de 64 bits, un proceso de espacio de usuario de 64 bits podría convertir un far jmp en un código de 32 bits. Esto no es útil en la práctica, e incluso puede romperse cuando el sistema operativo regresa a su proceso después de un cambio de contexto.

TODO: busque un enlace donde alguien haya mostrado cómo hacer esto. Creo que incluso hubo una pregunta reciente sobre esto con una respuesta detallada sobre cómo encontrar los números del segmento correctos.

Cuestiones relacionadas