Intel® ISA Extensions
Use hardware-based isolation and memory encryption to provide more code protection in your solutions.

Ring transitioning using call gates


I don't know if it's a correct forum to put my question so sorry in advance.


I'm trying to perform a Ring 3 to Ring 0 transition using Call Gates rather than SYSRET & SYSENTER to see how call gates work on IA-32e (64 Bit) processors.

What I know is Call Gates are special structure that you can put into GDT so it can be used in order to perform a transition between different rings.

The structure of call gates are like this :

    typedef struct CALL_GATE
    unsigned __int32 offset0_15 : 16;
    unsigned __int32 selector :16;
    union {
        struct {
            unsigned __int16 ist : 3;
            unsigned __int16 ignored : 5;
            unsigned __int16 type : 5;
            unsigned __int16 dpl : 2;
            unsigned __int16 p : 1;
        } part;
        unsigned __int16 all;
    } dummy;
    unsigned __int64 offset16_63 : 48;
    unsigned __int32 reserved : 32;


I set up a windbg remote Windows kernel debugger. Now let say my dispatch routine (the location where I want to go after the processor transferred from ring 3 to ring 0) is located at 0xfffff8027f258bc0 so I put a hardware breakpoint in this location :

ba e 1 fffff802`7f258bc0

Now I created a call gate structure with the following information :

DPL : 0x3

Selector : 0x10 (KGDT64_R0_CODE)

Type : 0xc

p (present) : 0x1

and append of offset0_15 & offset16_63 : fffff8027f258bc0

The result structure (in hex) is like this :

00000000 fffff8027f25 ec00 0010 8bc0

Now, as call gates (and every GDT entries) are 128 bit or 0x10 Byte. I choose the GDT's 8th entry to convert it into a call gate thus first find the GDT location using GDTR and then modify its 8th entry (0x8th entry * 0x10 size of every entries).

kd> r gdtr gdtr=fffff8028185afb0 kd> eb fffff8028185afb0+(0x8 * 0x10) 00 00 00 00 ff ff f8 02 7f 25 ec 00 00 10 8b c0

It's time to use our entry using a far call or a far jmp. my user mode application (which wants to transfer execution to ring 0) executes the following instruction :


00000000`00d2114e ea000000000800 jmp 0008:00000000

But the problem is nothing happens, the user mode application neither crash nor transfer execution to ring 0 (because my hardware breakpoint not triggered.).

Now my question is, what's wrong with my assumptions that makes problem transferring from ring 3 to ring 0?

I also test 0x40 and 0x43 as the selector for far jmp and test all of them with far call.

0 Kudos
0 Replies