А>На последней строке Вин7 32 крешится. Что сделал не так?
В контексте какого процесса зовётся ZwMapViewOfSection() и в каком контексте потом происходит обращение к памяти? Если, например, проецируешь в контексте вызывающего процесса, а читать потом пытаешься в потоке ядра, — получишь падение, естественно.
x64>В контексте какого процесса зовётся ZwMapViewOfSection() и в каком контексте потом происходит обращение к памяти? Если, например, проецируешь в контексте вызывающего процесса, а читать потом пытаешься в потоке ядра, — получишь падение, естественно.
В драйвере есть функция, которая вызывается периодически, когда надо прочитать кадр. При первом ее вызове я вызываю
status = ZwMapViewOfSection(m_SectionHandle, ZwCurrentProcess(),
Теперь в драйвере пробую почитать данный с приложения, используя m_pAddrMap
m_pAddrMap — usermode адрес и валидный только в контексте процеса, где была вызвана ZwMapViewOfSection, если обратиться по этому адресу в контексте другого процесса естественно KMODE_EXCEPTION_NOT_HANDLED(STATUS_ACCESS_VIOLATION)
Короче, слушай внимательно. Про контексты и адресные пространства тебе уже объяснили. Далее, если тебе реально необходим доступ к проекции в любом контексте, то для решения проблемы варианта у тебя два: 1. [попроще] создать проекцию через ZwMapViewOfSection(), а при каждом обращении к памяти аттачиться к а.п. исходного процесса через KeStackAttachProcess(), однако доступ к такой памяти можно будет выполнять только на IRQL <= APC_LEVEL, или 2. [посложнее] сразу спроецировать память процесса в верхние адреса, которые "всегда доступны" в ядре, т.к. общие для всех процессов, это делается вызовами MmAllocateMdl(), MmProbeAndLockPages() и MmGetSystemAddressForMdlSafe(), — плюс в том, что память будет зафиксирована в физической памяти и к ней можно будет обращаться в прямом смысле отовсюду, включая повышенный IRQL, однако минус в том, что придётся тем или иным способом следить за уничтожением процесса, чтобы вовремя разблокировать страницы и удалить проекцию, иначе получишь сюрпризы типа такого.
x64>Да, но зачем же недокументированное предлагать при наличии правильной альтернативы (MmGetSystemAddressForMdlSafe)?
Ну хотя бы потому, что юзермодный код может подкозлить пока там драйвер чухается — а именно отмапить адреса которые драйвер получил от ZwMapViewOfSection и подсунуть что-нить свое. А с точки зрения драйвера весь юзермод населен козлами. Исключая юзермод, имеющий включенную Administrators группу в токене — он тоже населен козлами, но этим можно доверять.
Как много веселых ребят, и все делают велосипед...
x64>Короче, слушай внимательно. Про контексты и адресные пространства тебе уже объяснили. Далее, если тебе реально необходим доступ к проекции в любом контексте, то для решения проблемы варианта у тебя два: 1. [попроще] создать проекцию через ZwMapViewOfSection(), а при каждом обращении к памяти аттачиться к а.п. исходного процесса через KeStackAttachProcess(), однако доступ к такой памяти можно будет выполнять только на IRQL <= APC_LEVEL, или 2. о[/url].
что-то не выходит, взял первый вариант.
1. В конструкторе главного процесса запускаю поток
status = PsCreateSystemThread(
&hThread,
THREAD_ALL_ACCESS,
NULL, NULL, NULL,
Thread_proc, NULL);
2. в Thread_proc() подключаюсь к памяти приложения
V>> if ( KeGetCurrentIrql() <= 2) x64>Во-первых, не 2, а DISPATCH_LEVEL. x64>Во-вторых, какой ещё DISPATCH_LEVEL?! x64>Максимум, APC_LEVEL здесь можно, я ж писал.
я смотрел по логу, функция вызывается с Irql == 2 (DISPATCH),
т.е в APC_LEVEL вообще я попасть не могу?
V>теперь при APC_LEVEL в эту ветку вообще не попадаю.
Разумеется, ты ж из таймера это делаешь (функция KiProcessTimerDpcTable в стеке), они на DISPATCH_LEVEL выполняются. Итого тебе: читать про DPC/таймеры в документации и думать, как перепроектировать драйвер (если возможно), потому что если будешь делать по варианту 2
, то работать-то оно будет, но нужно будет ещё синхронизацию правильную навесить, т.е. нельзя будет завершить процесс, страницы которого проецируешь, пока выполняется DPC/таймер. Вкратце, в момент завершения процесса (как ловить — тут есть варианты) ждать, пока не закончится работа с памятью (можно сам таймер ждать, можно событие, ...) и затем только отпускать процесс в вечный путь. Зачем это нужно — процесс может быть убит в любой момент, ты не контролируешь это.
O>>...весь юзермод населен козлами. x64>Иногда твоё образное мышление доставляет =)))
Профессиональная деформация секурити разработчика. Добавлю что если уж юзать ZwMap* и аттачиться к процессу — то лучше это городить в системном процессе — KeStackAttachProcess( PsInitialSystemProcess().. ) и вперед...
Как много веселых ребят, и все делают велосипед...
O>Добавлю что если уж юзать ZwMap* и аттачиться к процессу — то лучше это городить в системном процессе — KeStackAttachProcess( PsInitialSystemProcess().. ) и вперед...
Так ему ж память с процессом шарить надобно.
Предлагаешь а.п. ядра проецировать в процесс, что ли?
O>>Добавлю что если уж юзать ZwMap* и аттачиться к процессу — то лучше это городить в системном процессе — KeStackAttachProcess( PsInitialSystemProcess().. ) и вперед... x64>Так ему ж память с процессом шарить надобно.
Ну процесс у него создает секцию сам (CreateFileMapping'ом) и сам же отображает себе в АП, а драйаер открывает по имени ту же секцию и отображает в АП системного процесса во избежание несчастных случаев. Все шарится и в тоже время все безопасно как Contex Classic. Вообще секция — это конечно не самый лучший и уж точно не самый простой способ обмениваться данными с драйверами, но раз уж ТС хочет именно так.. Может у него есть какие нить свои скрытые мотивы.
x64>Предлагаешь а.п. ядра проецировать в процесс, что ли?
Ась?
Как много веселых ребят, и все делают велосипед...