Почему? Код же находится выше 2гб, почему на него будут влиять изменение cr3? Меня давно интересует такой вопрос - 0x401000 - Это виртуальный адрес, справедливый для какого-то процесса. Если я набираю !pte 0x401000, то для какого процесса он мне выдаст pte? PAE меня пока не интересует, так что можно было бы.. но опять я криворукий =( Я эту функцию пробовал самой первой до того, как задал тут вопрос. Делал так Код (Text): dirBase = (unsigned int *) MmGetVirtualForPhysical( RtlConvertLongToLargeInteger(eproc->DirBase) ); Получал виртуальный адрес, но при попытке обратться по нему получал бсод(
rei3er имхо, нет Ихмо да... пространство ядра идентично для каждого процесса (т. е 512 (256) элементов PDE в каталоге страниц каждого процесса должны содержать одинаковые значения) Ет-то хорошо, вот только как добраться до директорий зная только CR3, тобишь физический адрес, а вот перевести его в виртуальный с PAE уже не так то просто. Т.е. Чтобы было понятно Поменять то мы CR3 можем, но вот только та новая таблица на которую он будет указывать ДОЛЖНА СОДЕРЖАТЬ СТАРЫЕ ЗАПИСИ, иначе мы в ауте. КОРОЧЕ при грамотно спроектированной системе со включеной Page Address Extension менять CR3 невозможно. (вот если PAE будет выключен, то есть способ поиска логического CR3).
lews Что-такое eproc->DirBase. Вот код который работает без РАЕ Код (Text): ; PAE режим должен быть отключен mov eax,cr3 xor al,al and ah,0FCh push eax push L 0 push eax call MmGetVirtualForPhysical push eax call dmes3 db "STEALTH: CR3 = %.8X логический и %.8X физический",0 dmes3: call DbgPrint pop eax pop eax pop eax
так а я что написал? наш код выполняется в режиме ядра если предположить, что устанавливаемое значение CR3 валидно (взято у реально существующего процесса), то все будет нормально а не содержать старые записи каталог страниц с адресом, который мы устанавливаем в CR3, просто не может иначе как при переключении контекста на процесс с данным CR3 он сможет работать с нашим кодом (который априорно должен быть доступен всем процессам)
Код (Text): struct _EPROCESS{ UCHAR shift[0x18]; unsigned int DirBase; }; _EPROCESS *eproc; PsGetProcessByProcessId(int pid, (PEPROCESS *)&eproc);
lews Пытаюсь руками транслировать вирт. адрес в физический(или установить, что он недействителен) для заданного процесса в системе Вот уж этот СИ блин Но примерно так Код (Text): ULONG sizeSearch = 0xFFFFF000; while (sizeSearch) { if (MmIsAddressValid(pAddress)) // суть минимальная единица выделения памяти - страница /// Тут заносим этот адрес в наш массив валидных адресов { } //if (MmIsAddressValid(pAddress)) pAddress += pageSize; sizeSearch -= 0x1000; } //while Поскольку шаг одна страница, то это работает быстро
После долгих мучений остановился на варианте с подменой Cr3 - адреса прекрасно процессором транслируются, без всяких мучений Однако есть одно но... Перед подменой регистра я хватаю спин-блокировку..а она. как известно, повышает IRQL до уровня DPC. Это как раз то, что мне надо - никакой пользовательский поток не сможет переключиться на процессор и не сменится CR3. Однако есть но - я ведь прохожусь потом по всем таблицам страниц...а они в страничной памяти, ну и в итоге БСОД ) Собственно вопрос - достаточно ли будет повысить IRQL только до уровня APC? Или есть другие варианты?
lews KeAttachProcess ( PRKPROCESS pAttachedProcess); Тебя спасет, ибо делает то же что и ты Да pAttachedProcess - процесс нужно подбирать тот который подходт к поставленной задаче.