Добрый день форумчанам! Пишу транслятор адресов, чтобы бегать по PTE-записям и напрямую менять атрибуты страниц. Объявил необходимые структурки по амдшным спекам: https://hastebin.com/uhocilubat.h Читаю CR3, получаю адрес PML4E: Code (C++): #define PFN_TO_PAGE(pfn) (pfn << 12) VIRTUAL_ADDRESS Va = {}; Va.Value = (unsigned long long)&Va; // Найдём самого себя CR3 Cr3 = {} Cr3.Value = __readcr3(); UINT64 pPml4e = PFN_TO_PAGE(Cr3.x64.Bitmap.PML4) + Va.x64.Page4Kb.PageMapLevel4Offset * sizeof(PML4E); // Возвращает NULL: PML4E* Pml4e = MmMapIoSpace(pPml4e, sizeof(PML4E), MmNonCached); MmMapIoSpace возвращает NULL. Физический адрес выглядит нормальным - не вылезает за границы доступной физической памяти (например, pPml4e = 0x3.29e0.0000, физической памяти 16 Гб (0х4.0000.0000)). Но не мапится. MiMapContiguousMemory возвращает STATUS_CONFLICTING_ADDRESSES. Какие могут быть причины? И небольшой смежный вопрос: здесь упоминают, что адреса этих таблиц уже отображены на виртуальные адреса (например, в х32 на 0xC0000000). Где можно посмотреть эти адреса для х64 (понятно, что в иде, только где искать?) и насколько надёжно их хардкодить?
попробуй на меньшем размере. --- Сообщение объединено, Nov 10, 2018 --- начни отсюда https://blogs.msdn.microsoft.com/ntdebugging/2010/06/22/part-3-understanding-pte-non-pae-and-x64/
в отладчике крути маппинг и узришь где вылетает.. 1. можь памяти не хватает. 2. с разрешением на доступ к адресам памяти фигня. 3. можь железку плющит. === --- Сообщение объединено, Nov 11, 2018 --- https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-pte --- Сообщение объединено, Nov 11, 2018 --- https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/allocating-system-space-memory
Ну вот читаем спеки: 40-битный адрес расширяем до 52х-битного, сдвигая на 12 бит. На виртуалке с 4 гигами памяти читаем CR3, получаем, например, 0x119C00000. 40 бит PML4E = 0x119C00. Сдвигаем на 12 бит и получаем тот же 0x119C00000. Но он УЖЕ больше четырёх гигабайт! Это нормально? Он тоже не мапится. С другой стороны, MmMapIoSpace на основной машине (там, где 16 гигов), успешно мапит адреса выше 0x400000000. Что это за память?
HoShiMin, так у тебя в виртуалке не пашет? --- Сообщение объединено, Nov 11, 2018 --- если не работает именно в виртуалке, надо смотреть настройки сией вм-ки… 1. либо настройки. 2. слишком большой кусок пытаешься мапить и элементарно памяти на такое нет. 3. у самой вирты косяки.
Не работает и в виртуалке, и на хосте. Пытаюсь смапить всего 8 байт - размер одной записи, куда уж меньше... И что интересно, почему-то успешно памятся адреса намного выше верхнего возможного адреса физической памяти. Что там за адреса? А CR3 в виртуалке тоже выше верхней границы (это вообще нормально?), но не мапится. Во внутренностях MiMapContiguousMemory чёрт ногу сломит даже с Hex-Rays'ом. Там начинаются сплошные захардкоженные числа. Откуда что берётся - непонятно... Внутри MiReservePtes вообще ад. Ну вот что это? --- Сообщение объединено, Nov 11, 2018 --- Это я к тому, что, возможно, что-то концептуально делаю неправильно. Меня смущает, что CR3 получается выше, чем верхний доступный адрес в оперативке. Как, например, в виртуалке 4 гига, а CR3 залез на 700 мегабайт выше? Это что же получается, граждане?
HoShiMin, Менеджер памяти, вы веть сами решили в него лезть, нет смысла идти назад. > почему-то успешно памятся адреса намного выше верхнего возможного адреса физической памяти. Что там за адреса? Мапяться". физический адрес не равен виртуальному. В механизмы трансляции никогда никто не вмешивается, так что ошибка явно у вас в чём то. > CR3 получается выше, чем верхний доступный адрес в оперативке. А вы уверены что это pdbr, а не есчо что то.
Правильно ли понимаю, что если установлено N байт оперативки, то физическое адресное пространство [0, N - 1] полностью принадлежит ей? Если так, то отображение какой памяти создаётся по физическим адресам, большим, чем N - 1? Но на х64 в cr3 ничего другого и быть не может!
HoShiMin, > Правильно ли понимаю, что если установлено N байт оперативки, то Нет. Память замещается для экономии. Ничего нельзя сказать про её лимиты. Физические механизмы аллокации тёмный лес. > Но на х64 ничего другого и быть не может! Может вы не там поле прочитали, почему то мне кажется именно это важным.
HoShiMin, Тогда если pdbr верен, выполняйте трансляцию. PTE/PDE etc это системный ll уровень, это никогда никто не использует. Следует выяснить почему отображение возвращает ошибку, не вся память может быть отображена. Это хороший путь что бы разобраться в механизмах памяти, но такой путь не приемлем для обычной реализации. Всё кончается на высокоуровневых апи.
Почему-то засомневался, эквивалентны ли MmMapIoSpace и отображение \\.\Device\PhysicalMemory через ZwMapViewOfSection?
HoShiMin, на сколько я помню - скорее всего проблема в том что адрес уже замаплен. Да и вообще так делать нельзя. Для начала возьмите MmAllocateContiguousMemory она даст вам физический адрес. Его отправьте в MmMapIoSpace. Если все работает, значит (очевидно), что дело не в функции, а в том, что вы передаете невалидный физический адрес, либо адрес уже замаплен ) если хотите получить виртуальный из физического - юзайте MmGetVirtualForPhysical
TermoSINteZ, С этим отображением довольно хитрое дело как помню. Бала давно проблема - блок был подкачан, соответственно эти апи фейлили(то самое, занятая память" ?). Дёргалась MmTrim*(), после чего весь рабочий набор системы отгружался и можно было после этого выделить непрерывный физ блок. Там походу какие то не очевидные фичи имеются. Я давно это уже не трогал, по памяти сложно точно сказать. Посмотрите сурки. Кстате это для тс. Так что если есть такие проблемы - сбросте системный WS(это освободит весь рабочий набор ядра - он будет откачан принудительно) через MmTrim..найдите апи, я не помню точно. По идеи это должно сработать. --- Сообщение объединено, Nov 12, 2018 --- MmTrimAllSystemPageableMemory() врк. MmAllocateContiguousMemorySpecifyCache() -> MmEmptyAllWorkingSets(), у меня где то в старых сурках нашёлся такой комент. MmTrimAllSystemPag[e]ableMemory() - выгружает только системную память". Квадратная скобка значит что есть в какой то версии экспортный баг с именами. Может это чем то поможет. --- Сообщение объединено, Nov 12, 2018 --- TermoSINteZ, > Для начала возьмите MmAllocateContiguousMemory она даст вам физический адрес. Судя по коменту выше эта апи именно и выгружает рн для освобождения памяти перед поиском.
Indy_, да именно так и происходит. Просто тс сделал какой-то код не почитав даже рекомендации WDK (MSDN)
TermoSINteZ, Там по этой теме ничего нет. Была подобная проблема, но по описанию решение найти было невозможно. Пришлось реверсить нт, отсюда и баг с именами нашёлся. Забавно ведь - разраб ошибся, допустив опечатку.
Indy_, про почитать - я имел ввиду только то что, в мсдн нигде нет примеров по типу дергаем MmMapIoSpace для любого физ адреса и прочее.