Я изучаю трансляцию виртуальных адресов в Windows 10 x64. Я также читал о PML4, PDP, PDE и PTE, и теперь я пытаюсь изменить nx-бит стека, чтобы выполнить код в стеке, изменив структуры подкачки.
Я видел следующее изображение, которое описывает nx-бит в PML4E, PDPE, PDE и PTE:
Давайте предположим, что мы создали Windbg для отладки ядра с помощью VMWare, а на гостевой машине мы отлаживаем простое приложение с помощью xdbg64.
После присоединения к целевому процессу с помощью xdbg64 теперь rsp
указывает на 00000089F06FF848
. Я меняю поток программы и выполняю jmp rsp
, и теперь rip
указывает на rsp
, но дает access_violation exception
из-за DEP, поэтому я не могу выполнить какой-либо код в стеке. (ранее я изменил стек на что-то вроде xor rax,rax
, чтобы там был правильный ассемблерный код).
Теперь я приостанавливаю гостевую машину с помощью Windbg с хоста и, чтобы сделать правильный перевод, меняю явный процесс на целевой процесс, используя .process /f /i ffffa9841d9952c0
, и после нажатия g
теперь наш cr3
действителен для перевода.
Затем я использую следующую команду, чтобы получить физический адрес PML4E, PDPE, PDE, PTE:
kd> !vtop 0 00000089F06FF848
Amd64VtoP: Virt 00000089`f06ff848, pagedir 34848000
Amd64VtoP: PML4E 34848008
Amd64VtoP: PDPE 3316e138
Amd64VtoP: PDE 340efc18
Amd64VtoP: PTE 31de77f8
Amd64VtoP: Mapped phys 68a6b848
Virtual address 89f06ff848 translates to physical address 68a6b848.
Из картинки выше 63-й бит предназначен для NX-Bit, тогда я получаю все записи(PML4E, PDPE, PDE, PTE), чтобы увидеть, что там есть.
В случае PML4E это:
kd> !db 34848008
#34848008 67 e8 16 33 00 00 00 0a-00 00 00 00 00 00 00 00 g..3............
#34848018 67 88 77 55 00 00 00 0a-00 00 00 00 00 00 00 00 g.wU............
#34848028 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848038 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848048 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848058 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848068 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848078 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
Преобразование 67 e8 16 33 00 00 00 0a (01100111 11101000 00010110 00110011 00000000 00000000 00000000 00001010)
to
67 e8 16 33 00 00 00 0b (01100111 11101000 00010110 00110011 00000000 00000000 00000000 00001011)
(Обратите внимание на жирный бит.)
ПДПЭ это:
kd> !db 3316e138
#3316e138 67 f8 0e 34 00 00 00 0a-00 00 00 00 00 00 00 00 g..4............
#3316e148 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e158 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e168 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e178 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e188 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e198 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e1a8 00 00 00 00 00 00 00 00-67 f8 0e 34 00 00 00 0a00 00 00 00 00 00 00 00 ................
Преобразование 67 f8 0e 34 00 00 00 0a (01100111 11111000 00001110 00110100 00000000 00000000 00000000 00001010)
to
67 f8 0e 34 00 00 00 0b (01100111 11111000 00001110 00110100 00000000 00000000 00000000 00001011)
ПДЭ это:
kd> !db 340efc18
#340efc18 67 78 de 31 00 00 00 0a-00 00 00 00 00 00 00 00 gx.1............
#340efc28 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc38 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc48 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc58 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc68 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc78 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc88 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
Преобразование 67 78 de 31 00 00 00 0a (01100111 01111000 11011110 00110001 00000000 00000000 00000000 00001010)
to
67 78 de 31 00 00 00 0b (01100111 01111000 11011110 00110001 00000000 00000000 00000000 00001011)
А ПТЭ это:
kd> !db 31de77f8
#31de77f8 67 b8 a6 68 00 00 00 81-00 00 00 00 00 00 00 00 g..h............
#31de7808 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7818 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7828 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7838 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7848 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7858 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7868 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
И в этом случае я ничего не менял, потому что 67 b8 a6 68 00 00 00 81 равно 01100111 10111000 10100110 01101000 00000000 00000000 00000000 10000001, так как его последний бит равен 1.
На последнем шаге я снова запускаю !vtop
, чтобы убедиться, что он по-прежнему транслируется на тот же физический адрес, и вижу, что это правильно (указывает на то же место).
Затем я нажимаю g
, чтобы проверить, может ли он выполнить содержимое стека или нет, но я вижу, что он по-прежнему выдает ту же ошибку (access_violation) и не может выполнить этот адрес (rsp
).
Итак, у меня есть следующие вопросы:
Что не так с моей модификацией, которая не имеет никакого эффекта?
Я слышал, что у GDT также есть что-то вроде NX-Bit, которое предотвращает выполнение стека. В чем разница между предотвращением выполнения GDT и NX-Bit на уровне подкачки?
Почему существуют 4 уровня, определяющие nx-бит? Влияет ли изменение только одной из вышеуказанных записей, например pml4e, на все остальные записи?