Здравствуйте. Буду очень признателен, если кто-нибудь просветит, как работать с CR3. Насколько я понимаю, там хранится ФИЗИЧЕСКИЙ адрес каталога страниц, если это так, почему тогда следующий код вызывает бсод: Код (Text): #define PDI(Address) ( ((DWORD)(Address)) >> 22 ) #define PTI(Address) ( ( (DWORD)(Address) >> 12 ) & 0x000003FF) ............. IndDir=PDI(AddrTest); IndTbl=PTI(AddrTest); ....... __asm { pushad mov ecx, dword ptr [IndDir] mov edx, dword ptr [IndTbl] mov eax, CR0 and eax, 0EFFFFFFFh mov CR0, eax mov eax, CR3 and eax, 0FFFFF000h lea eax, [eax+4*ecx] mov esi, dword ptr [eax] ;тут бсод and esi, 0FFFFF000h lea esi, [esi+edx*4] mov esi, dword ptr [esi] mov eax, CR0 or eax, 0x80000000 mov CR0, eax mov Tmp, esi popad } Я подозреваю, что просто так недостаточно убрать 31-й бит в CR0, или может я вообще не так все делаю? Буду благодарен за любую помощь.
— сli — Transfer program control to linear addresses that are identity mapped to physical addresses (that is, linear addresses equal physical addresses). — Insure that the GDT and IDT are in identity mapped pages. — Clear the PG bit in the CR0 register. — Move 0H into the CR3 register to flush the TLB
asmfan Подозреваю, что Intel маны. Velheart а зачем тебе отключать страничную трансляцию? может быть можно проще сделать то, что ты хочешь
JAPH Сенкс, боюсь, только что трудно реализуемо... =)) Great Я просто хотел бы научиться подменять физические адреса, не меняя виртуальных, т.е. ставить хуки, например, шаманя в PT и PD, просто вроде везде пишут, что это возможно, а примеров нигде нет.. но это и хорошо, учитывая, что все это затевается в самообразовательных целях, т.к. усваивается лучше, чем копание в уже готовом коде =)) Ну а для этого нужно как-то достать виртуальный адрес для значения в CR3, вроде ДДК говорит,что есть MmGetVirtualForPhysical, которая недокументирована, но судя по WRK, делает то, что нужно (хотя может я ошибаюсь, только что мельком глянул =) ), может есть какие-нибудь известные-классические способы?
#define PTE_BASE 0xC0000000 #define PDE_BASE 0xC0300000 #define PDE_BASE_PAE 0xc0600000 #define MiGetPdeAddress(va) ((MMPTE*)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE)) #define MiGetPteAddress(va) ((MMPTE*)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE)) #define MiGetPdeAddressPae(va) ((PMMPTE_PAE)(PDE_BASE_PAE + ((((ULONG)(va)) >> 21) << 3))) #define MiGetPteAddressPae(va) ((PMMPTE_PAE)(PTE_BASE + ((((ULONG)(va)) >> 12) << 3)))
Я такие дефайны видел, только тогда не понял, и теперь не понимаю для какого они процесса?? Если еще можно предположить, что виртуальный адрес, соответствующий CR3 в любом процессе 0xC0300000, то как быть с PTE_BASE? Ну то есть PTE_BASE же должен определяться из PD,и быть не один, иначе зачем последний? Буду очень признателен за прояснение этого вопроса, а то у меня по этому поводу совсем каша в голове =))
Для любого. В нужном адресном пространстве они ссылаются на таблицы каталогов и страниц, описывающих это самое адресное пространство. Ээ, алё, это виртуальные адреса. Физический адрес каталога страниц можно узнать из Process->DirectoryTableBase, но он обычно не требуется.
как определил? боюсь, что эта инструкция (равно как и все инструкции после записи CR0) не выполняются
Ну про бсод -- загрузил крэш-дамп, windbg сказал, что именно там, причем если я перед этой инструкцией делал cli, то был IRQL_LESS_OR_EQUAL =)), а иначе не было кода вообще.. Извиняюсь, если сильно туплю, но если таблица страниц для процесса одна и в адресном пространстве процесса по виртуальному адресу 0xc0000000, то как мы можем адресовать 4 гб, если мы не используем для трансляции PDE?? Т.е. я неправильно понимаю: каталог страниц для процесса один, а таблиц страниц несколько?? Например код: Код (Text): PVOID newmem=ExAllocatePool(NonPagedPoolMustSucceed, 0x1000); ........... Tmp=*(DWORD*)((BYTE*)DIR_BASE+PDI(newmem)*4); DbgPrint("Mem: %X, PDI: %X, PDE: %X\n",newmem,PDI(newmem), Tmp); Tmp=*(DWORD*)((BYTE*)TBL_BASE+PTI(newmem)*4); DbgPrint("Mem: %X, PTI: %X, PTE: %X\n",newmem,PTI(newmem), Tmp); выводит нули в PDE и PTE...
PAE включен или нет?? Таблиц страниц много, просто они последовательно в виртуальной памяти отображены.
Не понял что имелось в виду. Есть список PDE из каталогов, в каждом каталоге есть список из PTE, которая уже описывает нужную страницу. Соответствующий метод поиска PTE процессором (если он вдруг не оказался в TLB) описан в манах интела. >>если мы не используем для трансляции PDE?? кажется, понял твой вопрос. Ты можешь формально разбирать PDE/PTE, но в винде используются более удобные макросы MiGetPteAddress, которые сразу тебе дают адрес PTE для соотв. виртуального адреса страницы и основаны о том, что PTE идут не абы как, а упорядоченно, и можно вычислить адрес быстрее основываясь на расположении этих самых PTE. Тогда действительно не потребуется тебе анализировать каталоги страниц. Но все равно они присутствуют, т.к. процессор ничего не знает о том, как операционная система располагает в памяти PTE (а они могут идти в совершенно любом порядке - главное, чтобы ссылки правильно были расставлены) и поэтому он просто "тупо" идет по ссылкам - сначала выбирает PDE, потом выбирает PTE из каталога. А винда упорядочивает каталоги просто для удобства. ЗЫ. Ну ко всем моим высказываниям нужно приписать еще PDPE, если включен Physical Address Extension (PAE)
Хех, сенкс всем, кажется разобрался =))) PAE у меня не было (зато был зверь, из-за которого пришлось переустанавливать виндовс =) ),а только что случайно наткнулся на из windbg хелпа =))
Вот блин, действительно PAE включен, я почему-то думал, что нужно проверять boot.ini на ключ /PAE..А то я вроде переписал все правильно, а все равно нули, я тогда посмотрел, что !pte в windbg говорит: Насколько я понял, еще и страницы не 4к, сорри что ввел в заблуждение...