Mi respuesta era a la pregunta 1 y 3. La 2 no la vi.
2) Sacado de AMD_INSTRUCTION_SET
Copies an immediate value or the value in a general-purpose register, segment register, or memory
location (second operand) to a general-purpose register, segment register, or memory location. The
source and destination must be the same size (byte, word, doubleword, or quadword) and cannot both
be memory locations
When reading segment-registers with a 32-bit operand size, the processor zero-extends the 16-bit
selector results to 32 bits. When reading segment-registers with a 64-bit operand size, the processor
zero-extends the 16-bit selector to 64 bits. If the destination operand specifies a segment register (DS,
ES, FS, GS, or SS), the source operand must be a valid segment selector
Attempting to use the MOV instruction to load the CS register generates an invalid opcode exception
(#UD). Use the far JMP, CALL, or RET instructions to load the CS registe
Como destino se puede tener DS, FS, GS, SS y ES (en modo KERNEL, RING0. Si lo haces en modo usuario, el programa muere)
Para modificar CS, lo que se hace es un far jump.
Me imagino que habras visto varias veces algo asi:
mov eax, [fs:0x0]
mov eax, [fs:0x20] etc..
FS en realidad no guarda una direccion de memoria en modo protegido, ni tampoco CS, DS, ES, GS etc...
Lo que guardan es un Indice a una tabla. Y en esa tabla si se guarda la direccion. (gdt). Se los suele llamar "selectores" en vez de "segmento" ya que son eso, un indicde selector. CodeSelector, DataSelector etc...
Para modificar el CS lo que hay que hacer es un far jump indicando que "indice"/selector de esa tabla hay que usar.
jmp pword 0x08: .kernel ;usamos el primer selector
.kernel:
;o tambien
jmp pword 0x1B: 1000h ;el selector que usa windows supongo
;donde luego en la memoria en la direccion [CS: 1000h] esta el codigo
Saludos