Отслеживание завершения процесса в драйвере

Тема в разделе "WASM.NT.KERNEL", создана пользователем vasalvit, 5 дек 2008.

  1. vasalvit

    vasalvit New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2008
    Сообщения:
    53
    Здравствуйте.

    Я пишу драйвер (уже почти написан) и интерфейсную DLL-ку. Управляющая программа будет общаться с драйвером посредством DLL.

    Драйвер написан таким образом, что общаться он должен только с одной программой. На управляющую программу я влиять не могу, поэтому делаю так:
    1. управляющая программа посылает команду LOGIN (через DeviceIOControl)
    2. драйвер запоминает ID-шник этого процесса
    ?. при получении остальных команд драйвер проверяет ID процесса и игнорирует другие процессы
    3. при закрытии приложение посылает команду LOGOFF
    4. драйвер сбрасывает ID процесса и готов к работе с другими программами

    Но если программа закрылась и не послала LOGOFF (например пользователь её убил, или она рухнула ...) драйвер остаётся заблокированным.

    Возникла такая идея - в драйвере отследить завершение процесса и сбросить запомненный ID.

    Как отследить завершение процесса ?
     
  2. Folk Acid

    Folk Acid New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2005
    Сообщения:
    432
    Адрес:
    Ukraine
    IO_COMPLETION_ROUTINE ?
     
  3. steelfactor

    steelfactor New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    501
    Можно поэкспериментировать с перехватом NtTerminateProcess
     
  4. vasalvit

    vasalvit New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2008
    Сообщения:
    53
    Сходил на обед, подумал над задачей...

    В режиме пользователя я бы передал HANDLE процесса в WaitForSingleObject и ждал бы, пока не сработает Wait.

    Нашёл в DDK функцию KeWaitForSingleObject, но в качестве объекта она принимает только 'event, mutex, semaphore, thread, or timer' :dntknw: Получается что такой способ не прокатит, или я не прав ?
     
  5. VENOM4X

    VENOM4X New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    29
    Попробуй проще - сделай список ID процессов, которые передавали драйверу команду LOGIN и, в дальнейшем, если какой-либо процесс посылает команду дрову - проверять, входит ли он в этот список. В этом случае проблема с завершением процесса отпадает.
    Или ещё вариант, чуть более сложный. Пусть прога (DLLшка) шифрует передаваемые через DeviceIoControl данные при помощи своего ID. А драйвер - пусть расшифровывает эти данные по ID текущего процесса и проверяет правильность расшифровки по какой-то метке в начале данных, ну в общем идея понятна.

    А насчёт KeWaitForSingleObject - кто тебе мешает ждать главный поток процесса? Ты же сам написал 'event, mutex, semaphore, thread, or timer'
     
  6. Folk Acid

    Folk Acid New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2005
    Сообщения:
    432
    Адрес:
    Ukraine
    vasalvit
    Зачем? Разве нельзя в процессе открыть драйвер и повиснуть на ReadFile/WriteFile, а в драйвере в обработчике обрабатывать закрытие хендла по факту завершения процесса?
     
  7. vasalvit

    vasalvit New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2008
    Сообщения:
    53
    По поводу списка ID-шников - не подойдёт. Хочется что бы при завершении процесса драйвер освобождал ресурсы и выгружался.

    А вот про главный поток процесса - я не подумал :) Спасибо :) Буду копать в эту сторону :)
     
  8. Folk Acid

    Folk Acid New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2005
    Сообщения:
    432
    Адрес:
    Ukraine
    VENOM4X
    Ждать в ring0? Изящно ли?
     
  9. vasalvit

    vasalvit New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2008
    Сообщения:
    53
    Не получится. Я пишу драйвер и DLL-ку. Интерфейс DLL-ки уже определён :dntknw:
     
  10. vasalvit

    vasalvit New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2008
    Сообщения:
    53
    Ну это же будет в отдельном потоке. И он [почти] всегда будет спать.
     
  11. VENOM4X

    VENOM4X New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    29
    Да, конечно нужно ждать в отдельном потоке. ИМХО - самый правильный вариант. Два остальных я написал только потому, что сам сначала не заметил, что можно ждать потоки.
     
  12. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    KeWaitForSingleObject() без проблем может работать с объектами процессов и потоков (EPROCESS и ETHREAD соответственно), так что если у тебя только один процесс одновременно может открыть твой девайс, тогда это решение предпочтительнее. Если несколько процессов одновременно могут держать хендл твоего девайса, тогда можно слегка модифицировать этот способ: создать по одному системному потоку на управляющий процесс и в каждом ждать на объекте EPROCESS этого процесса. При этом, разумеется, в IRP_MJ_CREATE девайса нужно запихнуть ID процесса в список и создать поток. В любом случае удаление процесса из списка и очистка всех необходимых ресурсов у тебя будет в двух местах - в IRP_MJ_CLOSE и в системном потоке сразу после удачного ожидания (не забудь синхронизацию, например, мутекс). При этом бегать по списку придётся только в случае IRP_MJ_CLOSE, ибо в поток можно передать указатель на LIST_ENTRY в качестве контекста.
     
  13. MegaZu

    MegaZu New Member

    Публикаций:
    0
    Регистрация:
    22 июл 2005
    Сообщения:
    290
    А что PsSetCreateProcessNotifyRoutine уже не гламурно ?

    PsSetCreateProcessNotifyRoutine (ProcessNotify, FALSE);

    void ProcessNotify (IN HANDLE ParentId, IN HANDLE ProcessId,IN BOOLEAN Create)
    {
    if (Create == FALSE && ProcessId == myId)
    myId = INVALID_HADLE_VALUE;
    }

    ?
     
  14. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    PsSetCreateProcessNotifyRoutine() - это крайний случай, т.к. их всего может быть установлено 8 штук в системе. Может получится ситуация, когда девятому драйверу не удастся установить нотификатор, что не есть хорошо. Поэтому если есть возможность обойтись без PsSetCreateProcessNotifyRoutine() - лучше использовать эту возможность.
     
  15. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    vasalvit
    скажу тебе секрет:
    kernel32!WaitForSingleObject -> ntdll!ZwWaitForSingleObject -> nt!NtWaitForSingleObject -> nt!KeWaitForSingleObject

    так что на всём, на чем может ждать юзермодная функция, может ждать и Ke***.
    Объект E/KPROCESS Всегда начинается с DISPATCHER_HEADER (по сути тоже самое что и KEVENT, грубо говоря, объект KPROCESS содержит в начале объект KEVENT. только вот тип у него в поле Type не евент, а процесс). Она переходит в сигнальное состояние при завершении процесса. Поэтому никаких проблем.

    при LOGON: создаешь отдельный поток (PsCreateSystemThread), референсишь себе объект "процесс" (PsLookupProcessByProcessId), ждёшь на нем (KeWaitForSingleObject) без тайм-аута, после этого (значит процесс уже умер) делаешь g_ControlProcessId=0 и ObDereferenceObject(Process) только надо не забыть после завершения KeWaitForSingleObject прочекать, а не приаттачен твой драйвер уже к другому процессу, а то будет грустно.
    в потоке в локальную переменную придется сохранить ID перед ожиданием и сравнить с глобальным ID после ожидания прежде чем делать LOGOFF
     
  16. DriversDeveloper

    DriversDeveloper Виктор Фисюк

    Публикаций:
    0
    Регистрация:
    15 мар 2008
    Сообщения:
    6
    Адрес:
    Kiev, Ukraine
    Завершение процесса, который открывает объект устройства драйвера, можно отследить по IRP типа IRP_MJ_CLEANUP. Не зависимо от того, закрылось ли приложение нормально и вызвало CloseHandle или же завершилось аварийно и не закрыло дескриптор устройства, драйвер получит IRP_MJ_CLEANUP.
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Может проще будет похукать **TerminateProcess() и пт. ?
     
  18. Dian

    Dian Member

    Публикаций:
    0
    Регистрация:
    19 июн 2008
    Сообщения:
    222
    Чтобы юзать IoControl, нужно открывать. Тогда при срубе процесса прийдет IRP_MJ_CLOSE.