Обмен данными между драйвером и приложением
От: Andrey.Katkov  
Дата: 04.02.08 09:51
Оценка:
Доброго времени суток!

Я столкнулся с проблемой написания фаервола. На данный момент реализован простейший вариант — когда пакеты фильтруются внутри NDIS hook драйвера по правилам установленным из приложения. Но хочется расширить функиональность — реализовать передачу данных из драйвера в приложение, и обработку их там. Погуглив и почитав форумы пришёл к выводу — что реализовывать это надо через объекты "события" и разделяемую память. Попутно самостоятельной реализации — хотелось бы посмотреть работающие примеры, желательно на Си / Си++ и узнать про тонкости который меня ожидают.

--Best Regards,
Andrey Katkov.
Re: Обмен данными между драйвером и приложением
От: sergmann  
Дата: 04.02.08 10:18
Оценка: 2 (1)
Здравствуйте, Andrey.Katkov, Вы писали:

AK>Доброго времени суток!


AK>Попутно самостоятельной реализации — хотелось бы посмотреть работающие примеры, желательно на Си / Си++ и узнать про тонкости который меня ожидают.


Вот отличный пример: http://openvpn.net.
Serg
Re: Обмен данными между драйвером и приложением
От: Unmanaged Россия ICQ 476611995
Дата: 04.02.08 10:30
Оценка: 3 (1)
AK>На данный момент реализован простейший вариант — когда пакеты фильтруются внутри NDIS hook драйвера по правилам установленным из приложения.

hook — это означает банальный перехват обработчиков протоколов и адаптеров или это вы просто ошиблись в терминологии?

AK>Но хочется расширить функиональность — реализовать передачу данных из драйвера в приложение, и обработку их там. Погуглив и почитав форумы пришёл к выводу — что реализовывать это надо через объекты "события" и разделяемую память.


В приложении создать секцию...

CreateFileMapping()
MapViewOfFile()

...далее создать два события...

CreateEvent()

...и передать их драйверу посредством IRP...

DeviceIoControl()

...после этого можно ожидать первое событие...

WaitForSingleObject()

...и дождавшись, обрабатывать данные из разделяемой памяти,
после обработки установить второе событие.

SetEvent()

В драйвере открыть секцию...

ZwOpenSection()
ZwMapViewOfSection()

...затем получить по хендлам соответствующие объекты ядра.

ObReferenceObjectByHandle()

По заполнении буфера устанавливать первое событие...

KeSetEvent()

...и сразу же ждать второго.

KeWaitForSingleObject()

Как-то так всё это происходит, могу ошибаться.
Пусть кто-нибудь дополнит примерами.
STATUS_INVALID_DEVICE_REQUEST
Re: Обмен данными между драйвером и приложением
От: Геннадий Майко США  
Дата: 04.02.08 10:54
Оценка: 2 (1)
Здравствуйте, Andrey.Katkov,

AK> Но хочется расширить функиональность — реализовать передачу данных из драйвера в приложение, и обработку их там. Погуглив и почитав форумы пришёл к выводу — что реализовывать это надо через объекты "события" и разделяемую память. Попутно самостоятельной реализации — хотелось бы посмотреть работающие примеры, желательно на Си / Си++ и узнать про тонкости который меня ожидают.

--
Вот статья на эту тему в последнем выпуске NT Insider: "A Common Topic Explained — Sharing Memory Between Drivers and Applications".

C уважением,
Геннадий Майко.
Re[2]: Обмен данными между драйвером и приложением
От: Andrey.Katkov  
Дата: 04.02.08 13:24
Оценка:
Большое спасибо!
Re[2]: Обмен данными между драйвером и приложением
От: Andrey.Katkov  
Дата: 04.02.08 13:29
Оценка:
Большое спасибо!

Я вполне мог по неопытности ошибиться в терминологии. Сейчас у меня есть драйвер который регистрирует call-back функцию, по возвращаемому значению которой пакет либо отправляется дальше — либо не отправляется...
Re[2]: Обмен данными между драйвером и приложением
От: Andrey.Katkov  
Дата: 04.02.08 13:29
Оценка:
Большое спасибо!
Re: Обмен данными между драйвером и приложением
От: Sergey Storozhevykh Россия  
Дата: 04.02.08 15:55
Оценка: 2 (1)
Здравствуйте, Andrey.Katkov, Вы писали:

AK>Погуглив и почитав форумы пришёл к выводу — что реализовывать это надо через объекты "события" и разделяемую память. Попутно самостоятельной реализации — хотелось бы посмотреть работающие примеры, желательно на Си / Си++ и узнать про тонкости который меня ожидают.


Разделяемая память в этом случае может стать узким местом (ведь к ней нужно синхронизировать доступ, ждать пока придет ответ на предыдущий запрос, прежде чем посылать новый). Так что посмотрите в сторону inverted calls. Поищите здесь в форуме или на osronline, например, описание этого способа.
Re: Обмен данными между драйвером и приложением
От: TarasCo  
Дата: 04.02.08 16:59
Оценка: 2 (1)
http://rsdn.ru/Forum/Default.aspx?mid=653001&flat=0
Автор: TarasCo
Дата: 25.05.04
Да пребудет с тобою сила
Re[2]: Обмен данными между драйвером и приложением
От: Andrey.Katkov  
Дата: 05.02.08 15:55
Оценка:
Попытался реализовать такой подход. BSOD замучали видимо что-то криво сделал. Вот листинг кода.

Приложение:
HANDLE g_hEventPacketResived;
...
g_hEventPacketResived = CreateEvent(NULL,
    FALSE,
    FALSE,
    NULL);
g_hEventPacketForward = CreateEvent(NULL,
    FALSE,
    FALSE,
    NULL);
...
HANDLE* HandleArray[] = {&g_hEventPacketResived, &g_hEventPacketForward, &g_hEventPacketDrop};

if(ipFltDrv.WriteIo(START_IP_HOOK, HandleArray, sizeof(HandleArray)) != DRV_ERROR_IO)


В драйвере в Dispatch вот такой код

PKEVENT g_hEventPacketResived = NULL;
PKEVENT g_hEventPacketForward = NULL;
...
ntStatus = ObReferenceObjectByHandle(*(((HANDLE**)ioBuffer)[0]), 
          0,
          *ExEventObjectType,
          UserMode,
          &g_hEventPacketResived,
          NULL);
...
ntStatus = ObReferenceObjectByHandle(*(((HANDLE**)ioBuffer)[1]), 
          0,
          *ExEventObjectType,
          UserMode,
          &g_hEventPacketForward,
          NULL);
...


регистрируется call-back функция. А в ней такой код:
PVOID HandleArray[2];
  NTSTATUS ntStatus;

  LARGE_INTEGER liTimeOut = {1E+10,1E+10};

  // начальная инициализация
  ntStatus = STATUS_WAIT_0;
  HandleArray[0] = g_hEventPacketForward;
  HandleArray[1] = g_hEventPacketDrop;

  // помещаю параметры в разделяемую память

  // сообщаю приложению о том что пора обрабатывать информацию
  KeSetEvent(g_hEventPacketResived, 
    0,
    FALSE);
  
  // жду ответа приложения
  /*ntStatus = KeWaitForMultipleObjects(2,
    HandleArray,
    WaitAny,
    Executive,
    KernelMode,
    FALSE,
    &liTimeOut,
    NULL);*/

  ntStatus = KeWaitForSingleObject(&g_hEventPacketForward,
    Executive,
    KernelMode,
    FALSE,
    &liTimeOut);


Событие g_hEventPacketResived устанавливается, а на ожидании одного события или события на выбор — BSOD.
Re[3]: Обмен данными между драйвером и приложением
От: Unmanaged Россия ICQ 476611995
Дата: 05.02.08 16:39
Оценка:
AK>Событие g_hEventPacketResived устанавливается, а на ожидании одного события или события на выбор — BSOD.

По-первых, давайте договоримся, что все упоминания о BSoD'ах вы будете сопровождать анализом crash-дампа (команда "analyze -v" в WinDbg), ибо гадание "где что могло упасть" мне лично не очень нравится.

Во-вторых, попробуйте почитать документацию по KeWaitForSingleObject() более внимательно, в частности про время ожидания и уровни IRQL, — может быть где-то здесь ошибка?
STATUS_INVALID_DEVICE_REQUEST
Re: Обмен данными между драйвером и приложением
От: Denwer Россия  
Дата: 05.02.08 17:27
Оценка:
Здравствуйте, Andrey.Katkov, Вы писали:

Добавлю свои пять копеек, я бы сделал через события, но данные передавал бы через IRP. Так проще сделать многопоточное приложение. А вообще если траффик пойдет через юзер моде, то жди тормозов на гигабитной сетке, даже если ничего с данными делать не будешь, а просто пробросишь через юзер моде.
Re: Обмен данными между драйвером и приложением
От: skyguard  
Дата: 15.02.08 16:50
Оценка:
Здравствуйте, Andrey.Katkov, Вы писали:

AK>пакеты фильтруются внутри NDIS hook драйвера по правилам установленным из приложения

Это можно сделать на уровне NDIS.

AK> Но хочется расширить функиональность — реализовать передачу данных из драйвера в приложение, и обработку их там.

А вот этого, к сожалению, не получится. NDIS работает на DISPATCH_LEVEL и организовать ожидание принятого решения там не получится.
Re: Обмен данными между драйвером и приложением
От: Pzz Россия https://github.com/alexpevzner
Дата: 17.02.08 21:30
Оценка:
Здравствуйте, Andrey.Katkov, Вы писали:

AK>Я столкнулся с проблемой написания фаервола. На данный момент реализован простейший вариант — когда пакеты фильтруются внутри NDIS hook драйвера по правилам установленным из приложения. Но хочется расширить функиональность — реализовать передачу данных из драйвера в приложение, и обработку их там. Погуглив и почитав форумы пришёл к выводу — что реализовывать это надо через объекты "события" и разделяемую память.


На мой взгляд, возиться с памятью, разделяемой между драйвером и user space, имеет смысл только если речь идет о быстрой пересылке больших объемов данных. Что в данном случае явно не так.

Самый простой и прямолинейный способ наладить общение с драйвером — создать в драйвере управляющий device object (NdisMRegisterDeivce() для NDIS'овский драйверов), открыть устройство из user space, и общаться с драйвером посредством ReadFile/WriteFile/DeviceIoControl.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.