#windows #memory #x86-64 #paging
#Windows #память #x86-64 #подкачка
Вопрос:
Я пытаюсь написать псевдодрайвер ядра (он использует CVE 2018-8120 для получения разрешений ядра, поэтому технически это не драйвер), и я хочу быть максимально безопасным при вводе ring0. Я пишу функцию для чтения и записи MSR-файлов из пользовательского интерфейса, и перед переходом на ring0 я пытаюсь гарантировать, что указатель void, указанный моей функции, может быть записан, я решил, что идеальный способ сделать это — сделать его доступным для записи, если это еще не сделано.
Проблема в том, что единственный известный мне способ сделать это — с помощью VirtualProtect()
и NtAllocateVirtualMemory
, но VirtualProtect()
иногда происходит сбой и вместо этого возвращается ошибка. Я хочу точно знать, где хранятся эти разрешения доступа (в оперативной памяти? в каком-то специальном регистре процессора?) как я могу получить их адрес и как я могу изменить их напрямую?
Комментарии:
1. Вы не можете изменять их напрямую, и вам не нужно этого делать. Если
VirtualProtect()
происходит сбой, на это есть причина, и вы не можете ее обойти. Вы пытаетесь решить Y-часть проблемы XY. Правильное решение — разобраться с X, то есть исправить все, что вы делаете неправильно, в первую очередь, вместо того, чтобы пытаться взломать способ обойти проблему, которую вы создаете.2. @KenWhite это неправда, иначе операционная система не смогла бы этого сделать.
3. Um, no. ОС может делать все, что захочет. Это ответственно. Что еще может делать код, которым он также может управлять.
4. @KenWhite Это то, что я только что сказал… Я не думаю, что вы поняли мой комментарий.
Ответ №1:
Код пользовательского режима никогда не должен пытаться вмешиваться в структуры данных ядра, и любое правильно написанное ядро в любом случае предотвратит это. Лучший способ для кода пользовательского режима гарантировать, что адрес может быть записан, — это записать в него. Если страница еще не была доступна для записи, ошибка страницы приведет к тому, что ядро сделает это так.
Тем не менее, код ядра / не может / полагаться на то, что приложение сделало это, по двум причинам:
1) Даже если приложение выполняет это правильно, страница может быть снова отключена до (или после) входа в кольцо 0.
2) Ядро не должно / никогда / полагаться на код приложения, чтобы делать правильные вещи. Он всегда должен защищать себя.
Комментарии:
1. Кажется, вы упускаете вопрос. Первый абзац был справочной информацией, мой вопрос, на который до сих пор никто не ответил и который имеет объективный ответ, ЗАКЛЮЧАЕТСЯ в том, ГДЕ хранится информация о доступе к страницам. Я не могу принять этот ответ, потому что он не отвечает на этот вопрос. К счастью, я уже нашел страницу, которая содержит эту информацию, как указано в моем ответе на мой собственный вопрос.
Ответ №2:
Информация о разрешениях доступа и данные страницы хранятся в каталоге страниц, таблице страниц, CR0 и CR3.
Дополнительную информацию можно найти здесь: https://wiki.osdev.org/Paging .
Комментарии:
1. Да, это правильно. Но вам лучше сохранить резервные копии вашей файловой системы, если вы начнете возиться с данными ядра. Вы можете повредить память таким образом, что это приведет не только к сбою, но и к повреждению данных на диске, что приведет к повреждению FS. (например, если страница была доступна только для чтения, потому что она доступна для копирования при записи совместно с другим процессом, измените ваши таблицы страниц, чтобы вы могли ее записать, вместо того, чтобы разрешать обработчику ошибок страницы создавать копию физической страницы, прежде чем разрешить вашему процессу записывать копию. Или, что еще хуже, запись ненулевых данных на общесистемную общую нулевую страницу, используемую для отображения COW BSS / анонимных страниц)
2. В вопросе указан x86-64, и этот ответ касается только 32-разрядной подкачки.
3. Также обратите внимание, что CR3 — это физический адрес каталога страниц, но даже в коде ядра включена подкачка страниц, поэтому адреса, которые вы можете использовать, являются виртуальными.