Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 10
If the current privilege level is encoded in CS, which is modifiable by user-mode code, why can’t user-mode code modify CS to change CPL?
For a change, this is now a more theoretical than hands-on challenge. In order to address the exercise appropriately, we have to make sure we understood it correctly.
CS (code segment) is the CPU segment register that contains the current ring level in bits 0 and 1. This encoded level is also commonly referred to as CPL (current privilege level).
More information is provided in the Intel 64 and IA-32 Architectures Software Developer’s Manual at https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf.
We learn that the processor fetches instructions from the code segment by using a logical address consisting of both the value in the
CS register and the value in the
EIP contains the offset within the code segment of the next instruction to be executed. Furthermore, the Intel Manual sets out:
CSregister cannot be loaded explicitly by an application program. Instead, it is loaded implicitly by instructions or internal processor operations that change program control (such as, procedure calls, interrupt handling, or task switching).”
This is very similar to the
EIP register, which is only modified indirectly when executing instructions such as
Therefore, the CS register can only be modified with instructions such as
SYSCALL/SYSRET (64bit only) or
With the instruction
SYSENTER, user-mode code (i.e. CPL 3) can access special operating system (kernel-mode) code at privilege level 0. For instance, special privileged instructions can be accessed at CPL 0, such as the
LGDT instruction to load the GDT register.