Пытаюсь руками транслировать вирт. адрес в физический(или установить, что он недействителен) для заданного процесса в системе. Что я имею: на входе - PID процессе, по нему получаю адрес EPROCESS, дальше нахожу адрес физический адрес DirBase. А дальше туго :-( Теоретически, я знаю, как происходит трансляция - 10 бит адреса * 4 - смещение от DirBase. Там надо найти PDE, установить, действительна ли страница. Но тут начинаются у меня проблемы - DirBase - физический адрес, а я не могу обратиться по нему, только по виртуальному могу. Кроме того, даже если я обращусь по адресу этому, то дальше мне надо найти адрес первой таблицы страниц, чтобы найти PTE для моего адреса. (Где ?) Если бы все было в контексте текущего процесса, то просто - таблицы страниц проецируются по 0xC000000, каталог по 0xC030000. Может кто объяснит, куда копать? И не совсем по теме - как можно узнать, сколько и адреса всех страниц(виртуальные, для контекста этого процесса), переданных процессу.
lews вообще виртуальные адреса для всех каталогов страниц должны быть известны и не зависить от того, в контексте какого процесса мы работаем поэтому можно просканировать все PTE текущего процесса на предмет наличия физического адреса каталога страниц нужного тебе процесса если найдешь - получишь 2 индекса (PDE и PTE) и сможешь построить виртуальный адрес, если нет тогда можно тупо сделать так Код (Text): PVOID PageDirectoryBase; ... asm { cli mov eax, PageDirectoryBase mov ebx, cr3 mov cr3, eax ... mov cr3, ebx } ... }
Теоретически поможет.. Если работает она, как я понимаю, то я получу проекцию физической странички на виртуальную и смогу с ней работать нормально. Потом я найду нужный мне PDE... по идее, из PDE хитрыми махинациями я могу получить адрес таблицы страниц? И дальше на ней найти нужный мне PTE и по нему найти уже адрес нужной мне страницы с данными. Есть одна проблема - я не понимаю, что это за хитрые махинации, т.е. как отталкиваясь от PDE добраться до таблицы страниц, и как из PTE получить адрес страницы с данными :-(?
Меня смущает тот факт, что для текущего процесса вирт. адрес каталога страниц процеруется по одному и тому же адресу 0xC030000... Каша у меня какая-то в голове По поводу поиска в текущем процессе - каким образом я могу пройтись все PTE? Я ведь не в курсе, сколько страниц выделено процессу, как бы не уйти в БСОД ( А код зашибись, не догадался бы ) Единственное - достаточно спин блокировки, чтобы у меня не получилась ерунда? Если она повысит IRQL до 2, то ниодин пользовательский поток не переключится на процессор в этот момент и CR3 останется нетронутым?
надо бы тебе документацию почитать для начала содержимое PDE & 0xFFFFF000 = физический адрес таблицы страниц содержимое PTE & 0xFFFFF000 = физический адрес страницы вначале проходишь по всем PDE (используя базовый адрес = 0xC0000000) если PDE валиден (бит P = 1), используя базовый адрес = 0xC0300000 находишь нужный PTE в таблице страниц по физическому адресу, который есть в PDE (виртуальный адрес PTE = 0xC0300000 + index * 4096 + offset, где индекс - номер PDE в каталоге страниц, offset - смещение внутри таблицы страниц)
PFN - это физический адрес? Блин. Перечитал Руссиновича/Соломона 10ок раз, чтобы понять, и нигде там не упоминалось, что PFN это физ. адрес( Сидел и гадал, что за прикольная номер фрейма страницы Спасибо за разъяснение! ммм....а не наоборот? PDE с 0xC0300000, а PTE с 0xC0000000 ? rei3er Если не сложно, объясните, пожалуйста, такую штуку (можно смело послать в ман, просто найти интересного не получается :-( ) Валидный PDE/PTE указывает на страницу, которая не сброшена на диск? У Руссиновича так описано, по крайней мере. Если это так, то как я найду, когда мне следует прекратить поиски - ведь таблицы страниц создаются не сразу все, а по мере надобности? И ведь нет смысла проходить по первым 512 PDE, потому что они описывают пользовательское пространство? Спасибо!
Вообще, валидность PDE/PTE понятие относительное. На пристутствие/отсутствие страницы в памяти указывает бит присутствия P -- нулевой бит элемента PTE. В итоге, когда происходит обращение к такой странице, процессор генерирует исключение (#PF) и передает управление ОС. А ОС заглядывает в свои структуры и уже сама решает, отчего это произошло. Если страница действительно была выгружена, то она вернет ее на место. Если страница не была отображена для процесса -- сообщит об исключении обработчику исключений процесса (потока). В итоге, сказать точно, выделена ли страница процессу, только по биту присутствия нельзя -- надо еще знать, что ОС "думает" по поводу отсутствующей страницы. IMHO!
можно узнать карту памяти, перебрав все PDPE/PDE/PTE... а насчет "переданных процессу" - в винде есть какаято шня, называется VAD. Точно не знаю, но вроде надо копать в эту сторону.. подробности у руссиновича
да сформулируй четко, что ты вообще хочешь сделать опять таки, смотря какая у тебя цель а вообще Mika0x65 прав если P сброшен, то есть как минимум 8 вариантов типа PTE (3 USE-бита) исходя из этого обработчик #PF определяет, что делать можно поискать, что означает каждая конкретная комбинация
На данный момент я хочу просто узнать список всех страниц, переданных процессу (и те, что сейчас в страничком файле, и те, что в памяти, и те, что только зарезервированы, но не переданы). Как подсказал Great, копать надо в сторону VAD, и вроде бы, оказался прав, судя по докам, что я нашел к текущему моменту - правда, пока только общие слова, ничего конкретного
Руссинович пишет, что именно исходя из VAD обработчик #PF решает что делать с Page Fault - подгружать страницу, если она выгружена, читать файл, если это проекция секции и т.п. Посмотри сорсы винды, а именно файлик ntos\mm\mmfault.c, кажется так зовется. там находятся обработчики MmAccessFault и прочие
Чего-то у меня не то получается :| Руки надо выпрямлять ) Подскажите, если я что-то не так делаю - на входе ID процесса и какой-то адрес в контексте этого процесса. Я хочу получить данные по этому адресу. Делаю так: первым делом получаю EPROCESS для данного PID - с этим все ок. Дальше, по смещению 0x18 получаю DirBase - с этим тоже ок - проверяю параллельно в windbg. Дальше хочу получить PDE, для этого сначала получаю виртуальный адрес для странички с PDE: Код (Text): dirBase = (unsigned int *) MmMapIoSpace( (PHYSICAL_ADDRESS)RtlConvertLongToLargeInteger(eproc->DirBase), 4096, MmNonCached); DbgPrint("%d", dirBase[address->pdeShift]); Где address экземпляр Код (Text): struct VirtualAddress{ ULONG shift:12; ULONG pteShift:10; ULONG pdeShift:10; }; А его содержимое 0x401000, т.е. pdeShift = 0 И в windbg делаю тоже самое: !dd dirBase И получаю разные результаты(
rei3er код предложенный самый действенный способ, поскольку память в Windows имеет FLAT модель, то все можно промепить используя только средства процессора, только вот беда mov cr3, eax, может уничтожить мепирование твоего кода в память, т.е. следующая инструкция тут же приведет к PageFault.
lews Юзай MmGetVirtualForPhysical(...). Только она если PAE режим включен почему-то не всегда выдает правильный адрес.
PROFi вот именно... как раз в http://www.wasm.ru/forum/viewtopic.php?id=16528 писали что она работает не всегда при PAE.. лучше всетаки, Имхо, самостоятельно маппить себе через MmMapIoSpace все, что нужно.
имхо, нет пространство ядра идентично для каждого процесса (т. е 512 (256) элементов PDE в каталоге страниц каждого процесса должны содержать одинаковые значения) запись в CR3 приведет к сбросу TLB что поначалу снизит производительность, но не более того