1

我正在尝试使用调用门而不是 SYSRET 和 SYSENTER 执行环 3 到环 0 的转换,以查看调用门如何在 IA-32e(64 位)处理器上工作。

我所知道的是呼叫门是您可以放入 GDT 的特殊结构,因此可以使用它来执行不同环之间的转换。

调用门的结构是这样的:

    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;


}CALL_GATE, *PCALL_GATE;

我设置了一个windbg 远程Windows 内核调试器。现在假设我的调度例程(处理器从环 3 转移到环 0 后我想要去的位置)位于,0xfffff8027f258bc0所以我在这个位置放置了一个硬件断点:

ba e 1 fffff802`7f258bc0

现在我使用以下信息创建了一个调用门结构:

  • DPL:0x3
  • 选择器:0x10 (KGDT64_R0_CODE)
  • 类型:0xc
  • p(现在):0x1
  • 并附加 offset0_15 和 offset16_63 : fffff8027f258bc0

结果结构(十六进制)是这样的:

00000000 fffff8027f25 ec00 0010 8bc0

现在,调用门(和每个 GDT 条目)都是 128 位或 0x10 字节。我选择 GDT 的第 8 个条目将其转换为调用门,因此首先使用 GDTR 找到 GDT 位置,然后修改其第 8 个条目(第 0x8 个条目 * 每个条目的 0x10 大小)。

    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

是时候使用 far call 或 far jmp 来使用我们的条目了。我的用户模式应用程序(希望将执行转移到环 0)执行以下指令:

00000000`00d2114e ea000000000800  jmp     0008:00000000

但问题是什么也没有发生,用户模式应用程序既没有崩溃也没有将执行转移到环 0(因为我的硬件断点没有触发。)。

现在我的问题是,我的假设有什么问题导致问题从环 3 转移到环 0?

更新:我还测试了 0x40 和 0x43 作为 far jmp 的选择器。

4

0 回答 0