Здравствуйте, Геннадий Майко, Вы писали:
PVA>>Введем следующие обозначения: PVA>>E — внешний вызов функции PVA>>O — наш обработчик PVA>>P — тот, что мы подменили PVA>>N — тот, кто подменил нас
PVA>>E1 -> N1 -> O1 -> P -> O2 -> N2 -> E2
PVA>>После unload мы должны получить следующее: PVA>>E1 -> P -> E2
PVA>>Допустим, что EP (entry point) мы восстановили, но управление находится в точке N1, получим bsod PVA>>в остальных случаях операция должна завершится успешно, при условии что в N2 нет повторного вызова O. ГМ>-- ГМ>А что будет, если управление находится в O1 (или в P, или в O2) и драйвер тоже уже выгружен?
Если управление находится в O1, то следуя scoped guard драйвер не может быть выгружен вплоть до снятия блокировки по завершению O2.
Заметьте, что Unhook и Unload могут быть разнесены во времени (увиливаю от bsod)
PVA>>Не могли бы вы подробней описать проблему, связанную с многопроцессорностью? ГМ>-- ГМ>Честно говоря, я даже не рассматривал варианты с несколькими хуками на одну функцию, я постарался показать проблему с деинсталляцией только одного хука. Я это сделал, возражая на выделенную последовательность действия (см. вверху).
Не имеет значение количество хуков до нас, равно как и после нас — последние мы все-равно отключим.
ГМ>Мы не имеем права выгружать драйвер до тех пор, пока выполняется наша hook-функция, т.е. тогда, когда самая последняя команда нашего обработчика О уже выполнилась. Затем этот факт нужно сообщить нашей процедуре unload драйвера. Выделенная последовательность комманд, по моему, этого не гарантирует.
Для этого я там ввел понятие диспетчера, который отмониторит момент разрешения выгрузки со стороны хука
Кстати, такой диспетчер решает и проблему с разблокировкой на многопроцессорной машине с необходимостью. выполнить ret после выгрузки.
ГМ>Я не утверждаю, что этого сделать нельзя, я просто говорю, что это не тривиальная задача.
Да я и не спорю, просто интересно рассмотреть подходы при необходимости воспользоваться этими самыми хуками.
newbie
Re[8]: Что такое хорошо и что такое плохо (фильтр против хук
Здравствуйте, PVA,
PVA>>>Введем следующие обозначения: PVA>>>E — внешний вызов функции PVA>>>O — наш обработчик PVA>>>P — тот, что мы подменили PVA>>>N — тот, кто подменил нас
PVA>>>E1 -> N1 -> O1 -> P -> O2 -> N2 -> E2
PVA>>>После unload мы должны получить следующее: PVA>>>E1 -> P -> E2
PVA>>>Допустим, что EP (entry point) мы восстановили, но управление находится в точке N1, получим bsod PVA>>>в остальных случаях операция должна завершится успешно, при условии что в N2 нет повторного вызова O. ГМ>>-- ГМ>>А что будет, если управление находится в O1 (или в P, или в O2) и драйвер тоже уже выгружен? PVA>Если управление находится в O1, то следуя scoped guard драйвер не может быть выгружен вплоть до снятия блокировки по завершению O2. PVA>Заметьте, что Unhook и Unload могут быть разнесены во времени (увиливаю от bsod)
--
Да, понимаю. Точнее говоря, снижаете его вероятность
ГМ>>Честно говоря, я даже не рассматривал варианты с несколькими хуками на одну функцию, я постарался показать проблему с деинсталляцией только одного хука. Я это сделал, возражая на выделенную последовательность действия (см. вверху). PVA>Не имеет значение количество хуков до нас, равно как и после нас — последние мы все-равно отключим.
--
Верно. И это уже плохо.
ГМ>>Мы не имеем права выгружать драйвер до тех пор, пока выполняется наша hook-функция, т.е. тогда, когда самая последняя команда нашего обработчика О уже выполнилась. Затем этот факт нужно сообщить нашей процедуре unload драйвера. Выделенная последовательность комманд, по моему, этого не гарантирует. PVA>Для этого я там ввел понятие диспетчера, который отмониторит момент разрешения выгрузки со стороны хука PVA>Кстати, такой диспетчер решает и проблему с разблокировкой на многопроцессорной машине с необходимостью. выполнить ret после выгрузки.
--
Я что-то не заметил диспечера в Вашем исходном сообщении. Или плохо смотрел?
Я думаю, что без чего-то внешнего здесь не обойтись. Это внешнее должно отслеживать окончание работы hook-функции и сообщать об этом процедуре unload. Например, свой маленький отладчик, точнее отбработчик debug exceptions.
С уважением,
Геннадий Майко.
Re[7]: Что такое хорошо и что такое плохо (фильтр против хук
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>я расматриваю случай, когда устанавливается синхронизирующий элемент и затем, после него, будет — ну скажем Ваш jmp. После установки элемента и до исполнения jmp, unload функция может закончиться, так как она уже дождалась установки своего элемента. Драйвер уже выгружен. А команду jmp выполнить еще надо. Вот в чем проблема.
Предположим, что сигналим вызовом некоторго API:
call SignalCanUnload
ret; драйвер выгружен - BSOD
меняем на:
jmp SignalCanUnload
GN>>И "опасный" код не обязательно размещать в выгружаемом модуле. ГМ>-- ГМ>2. Согласен с Вами. Но тогда мы не выгружаем наш драйвер, правильно?
Именно для возможности выгрузки модуля можно скопировать (небольшой) опасный участок в другое место. Этот код, безусловно, так и останется потом болтаться в памяти, но его можно разместить и без аллокации. Решение не слишком чистое, но и так падчится ядро, какая уже разница, 5 байт или 20
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: Что такое хорошо и что такое плохо (фильтр против хук
--
Если конвенции возврата SignalCanUnload совпадают с конвенцией возврата из хука и этот SignalCanUnload не порушит регистры, то да, так, наверное, можно.
Еще нужно иметь гарантию, что SignalCanUnload не будет "трогать" синхронизационный элемент после того, как его установит.
Или, на всякий случай, нужно обеспечить "жизнь" этому элементу даже после выгрузки дайвера, примерно так, как Вы предлагаете ниже.
GN>>>И "опасный" код не обязательно размещать в выгружаемом модуле. ГМ>>-- ГМ>>2. Согласен с Вами. Но тогда мы не выгружаем наш драйвер, правильно?
GN>Именно для возможности выгрузки модуля можно скопировать (небольшой) опасный участок в другое место. Этот код, безусловно, так и останется потом болтаться в памяти, но его можно разместить и без аллокации. Решение не слишком чистое, но и так падчится ядро, какая уже разница, 5 байт или 20
--
И опять соглашусь с Вами. И добавлю, что подобных вариантов может быть несколько — от неинициализации указателя на Unload вообще до маркировки частей невыгружаемого драйвера как pageable/non pageable.
С уважением,
Геннадий Майко.
Re[2]: Что такое хорошо и что такое плохо (фильтр против хук
Здравствуйте, onyx2, Вы писали:
O>ИМХО: Но если использовать хуки, так как это делает М. Руссинович (см. исходники regmon), думаю проблем не будет.
А вот мнение автора:
// NOTE: We can't unhook if someone else has hooked on top of us. Note that the
// unhook code below still has a window of vulnerability where someone can hook between
// our test and unhook.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[4]: Что такое хорошо и что такое плохо (фильтр против хук
Здравствуйте, onyx2,
SS>>В последних версиях regmon используются registry callbacks (см. CmRegisterCallback).
O>А у вас есть исходники одной из последних версий regmon?
В 4.35 (общедоступная версия исходников) используется CmRegisterCallback.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth