Переход по кольцу с использованием ворот вызова

Я пытаюсь выполнить переход от кольца 3 к кольцу 0, используя "Врата вызовов" вместо "SYSRET & SYSENTER", чтобы увидеть, как "Ворота вызовов" работают на процессорах IA-32e (64-разрядных).

Что я знаю, так это то, что Call Gates - это специальная структура, которую вы можете вставить в 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;

Я установил удаленный отладчик ядра Windows от windbg. Теперь позвольте мне сказать, что моя процедура отправки (место, куда я хочу перейти после того, как процессор перешел с кольца 3 на кольцо 0), расположено в 0xfffff8027f258bc0 поэтому я поставил аппаратную точку останова в этом месте:

ba e 1 fffff802`7f258bc0

Теперь я создал структуру шлюза вызова со следующей информацией:

  • DPL: 0x3
  • Селектор: 0x10 (KGDT64_R0_CODE)
  • Тип: 0xc
  • р (присутствует): 0x1
  • и добавление offset0_15 & offset16_63: fffff8027f258bc0

Структура результата (в шестнадцатеричном формате) выглядит следующим образом:

00000000 fffff8027f25 ec00 0010 8bc0

Теперь, как ворота вызова (и все записи GDT) имеют 128 бит или 0x10 байт. Я выбираю 8-ую запись GDT, чтобы преобразовать ее в шлюз вызова, поэтому сначала найдите местоположение GDT с помощью GDTR, а затем измените его 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

Пришло время использовать нашу запись, используя дальний вызов или дальний JMP. мое приложение пользовательского режима (которое хочет передать выполнение в кольцо 0) выполняет следующую инструкцию:

00000000`00d2114e ea000000000800  jmp     0008:00000000

Но проблема в том, что ничего не происходит, приложение пользовательского режима не аварийно завершает работу и не переводит выполнение в кольцо 0 (потому что моя аппаратная точка останова не сработала).

Теперь мой вопрос: что не так с моими предположениями, из-за которых возникают проблемы при переходе с кольца 3 на кольцо 0?

Обновление: я также проверяю 0x40 и 0x43 в качестве селектора для дальней JMP.

0 ответов

Другие вопросы по тегам