Пишем свой промежуточный драйвер. Часть 1

    Здравствуйте, уважаемые хабраюзеры!
    Интересовались ли Вы когда-нибудь как работает снифер и что он из себя представляет? Или как Ваш любимый фаервол защищает Вас от троянов и прочей гадости на сетевом уровне? Да и вообще, как он работает? Я уверен, что Вы задавали себе такого рода вопросы, но все же, если нет, то я от части Вам про это расскажу. Начиная с этой статьи мы будем постепенно осваивать написание своего сниферо-подобного драйвера. Сегодня мы рассмотрим некоторые общие положения, которые нам будут необходимы для понимая всего того, что будет происходить в последующих статьях. Перед прочтением этой статьи, дабы у Вас началась складываться более или менее ясная картина, я рекомендую Вам прочтение прошлого топика Краткий обзор драйверов спецификации NDIS

    Всем кому это интересно прошу под кат.

    Сразу скажу, что статья ориентирована на пользовотелей, которые слабо знакомы с данной темой, поэтому буду стараться излагать подробно некотрые вещи. Ну что ж, приступим.

    Что нам потребуется и с чего начать?


    На многих форумах очень часто можно увидеть вопросы такого садержания: «Я начинающий программист, хочу писать драйвера, но не знаю как. С чего мне начать?» Поэтому, пытаясь описывать все последовательно я счел нужным рассказать что нам потребуется.

    Если вы решили заняться написанием драйверов, будь то обычные драйвера или будь они сетевыми Вам обязательно потребуется скачать WDK-Windows Driver Kits (он же NT DDK). Установив это добро на свою рабочую лошадку Вы станете вооружены для написания своего драйвера. Вместе с WDK идет своя документация, заголовочники, либы и примеры (они то нам и потребуются, став скелетом нашего будующего дрйвера). Работая в Visual Studio вы также можете скачать плагин для VS под названием Visual DDK. Это интеграционное средство поможет Вам в написании (и сборке) драйверов непосредственно из Visual Studio. Здесь Вы сможете ознакомиться с кратким хелпом по использованию этого средства. Хочу подчеркнуть, что установка Visual DDK для работы с драйверами из студии вовсе не обязательна, вы можете писать и собирать свои драйверы в VS и без этого средства! Это всего лишь плагин.

    Мы будем рассматривать пример промежуточного драйвера из WDK и модифицируем его. Почему именно промежуточный? Тем, кто ознакомился с предыдущей статьёй или просто сведом в спецификации NDIS известно, что промежуточный сетевой драйвер объединяет в себе поведение как драйверов протоколов так и минипорт-драйверов, являясь прослойкой между ними. Таким образом на этом примере можно охватить хотя бы частично все типы драйверов NDIS.

    Итак, скелетом нашего драйвера будет драйвер Passthru из WDK. Установив WDK Вы сможете найти его исходники в каталоге \src\network\ndis\passthru. Подробнее об этом исходнике можно узнать тут.Что делает этот драйвер? Пока ничего, он просто есть и все. Что будет делать наш драйвер? Он будет выполнять роль снифера, принимая и отправляя пакеты, получая о них информацию и возможно блокируя или изменяя ее. Для начала мы добавим в него некоторый функционал, напишем клиентскую программу, через котрую мы будем общаться с нашим драйвером, но это будет только в следующих статьях, а пока изучим немного теории.

    Немного теории


    Как Вы наверняка знаете, аналогом функции main в драйверах я вляется функция DriverEntry, у промежуточного дрйвера есть ряд дел, котрые он должен сделать, прежде чем начать функционировать. А сделать в DriverEntry он должен следующее:
    • зарегистрировать себя в NDIS (с помощью функции NdisMInitializeWrapper);
    • зарегистрировать свой «вид сверху» — виртуальный адаптер (с помощью функции NdisIMRegisterLayeredMiniport);
    • зарегистрировать свой «вид снизу» (виртуальный протокол) (с помощью функции NdisRegisterProtocol);
    • сообщить в NDIS, что «вид сверху» и «вид снизу» есть разные виды одного и того же драйвера (с помощью функции NdisIMAssociateMiniport).

    Вот и все. Помните в прошлой статье я писал про систему коллбэков у драйверов минипорта и протокола? Так вот, выполняя эти 4 действия промежуточный драйвер именно здесь регистрирует свои callback-функции. Если Вы раньше имели дело с драйверами минипорта и/или протокола, то Вы заметите, что функция NdisIMRegisterLayeredMiniport очень похожа на функцию NdisMRegisterMiniport (вызывается в случае регистрации не виртуального адаптера), а при создании как вируального так и не виртуального протокола вообще вызывается одна и та же функция NdisRegisterProtocol. Изначально Вы заполняете поля структур NDIS_PROTOCOL_CHARACTERISTICS и NDIS_MINIPORT_CHARACTERISTICS (здесь и записываются имена используемых коллбэков), а затем передаете их как параметры соответствующим функциям.

    Теперь давайте поговорим немного о сниферах.

    Немного о сниферах, совсем немного


    Снифер — это драйвер, перехватывающий и, возможно, модифицирующий сетевой трафик локального компьютера или всех компьютеров текущего сегмента сети. Я уврен все Вы знаете что это такое и хотя бы раз в жизни пользовались им или хотя бы просто видели. Давайте рассмотрим возможные схемы построения снифера:
    1. Снифер есть промежуточный драйвер, который втыкается во все имеющиеся привязки (bindings) протоколов к адаптерам. Это на самом деле самый простой способ из всех возможных. У каждого способа помимо приемуществ есть свои недостатки:
      • чтобы новые привязки заработали, надо перезапустить все сетевые адаптеры, имеющиеся в системе;
      • если в системе более одного сетевого адаптера, сниферу приходится либо ограничивать перехват только одной подсетью, либо запрещать маршрутизацию, либо создавать не один виртуальный адаптер, а много;
      • при каждом появлении в системе нового адаптера, протокола или промежуточного драйвера надо перенастраивать привязки протоколов к адаптерам. Если этого не сделать, снифер в лучшем случае перестанет перехватывать часть трафика, а в худшем, случае вообще обрушит систему;
      • если процессор тормозной, памяти мало, а сетевой канал очень быстрый, замедление работы системы промежуточным драйвером может стать критичным.

    2. Снифер есть драйвер-фильтр. Что под этим подразумевается? А подразумевается следующее: мы как бы присоединяемся к некоторому интесесующему нас устройству (у каждого драйвера есть свое устройство), например, на \Device\Тcр (это устройство драйвера-протокола tcpip.sys), и после этого каждое IRP, направленное на данное устройство, сначала направляется в наш драйвер. Опять же недостатки:
      • драйвер-фильтр может перехватывать только те информационные потоки, которые реализуются через IRP, т.е. только информационные потоки между драйверами протоколов и их клиентами;
      • драйвер-фильтр должен загружаться раньше всех kernel-mode клиентов интересующего нас устройства, иначе часть трафика будет идти мимо;
      • драйвер-фильтр сильно замедляет работу системы;
      • очень трудно нормально отладить драйвер-фильтр (об отладке мы поговрим в последующих статьях). Может возникнуть много самых разнообразных глюков.

    3. Снифер есть драйвер протокола, который привязывается ко всем имеющимся в системе адаптерам. Так перехватывают входящий трафик почти все сниферы, включая WinPCAP и Microsoft Network Monitor (исходящий трафик перехватывается по схеме 5). Способ почти идеален.
    4. Снифер есть обычный драйвер, функции которого вызываются из NDIS по мере необходимости. Так работает встроенный пакетный фильтр Windows XP. Больше никто так работать не может, поскольку поддержка такого драйвера должна быть изначально заложена в NDIS программистами Microsoft.
    5. Снифер есть обычный драйвер, который просто нагло патчит структуры NDIS, в которых записаны адреса коллбэков NDIS-драйверов. В результате при вызове любого перехваченного коллбэка любого NDIS-драйвера снифер получает управление. Так работают почти все пакетные фильтры сторонних производителей (OutPost например). Недостаток только один – это не очень надежно.

    Мини заключение

    Ну что ж, вот это примерно все базовые сведения, которые нам будут нужны для написания своего промежуточного драйвера. В следующей статье мы приступим непостредственно к написанию кода, поговорим об IRP. Далее мы также рассмотрим вопросы установки и отладки драйверов. Я очень надеюсь, что данная тема Вам интересна и коль это будет так, то с удовольствием буду Вам её освещать.
    Спасибо Вам за внимание.
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 13
    • +5
      15 лет назад мы вешали на прерывания резидента, который отправляемые на принтер точки заменял на «раком», а запятые на «боком». Училка по информатике была в экстазе.
      • 0
        И не стыдно вам было издеваться над женщиной?)))
        • 0
          Стыдно. Но весело.
          • 0
            согласен) Сами тоже чем только не маялись на уроках инфы, чтобы только напакостиь и довести училку) было весело))
            • +2
              Да цели напакостить особо не было даже, просто интересно было сделать. Интернетов не было, всё из книжек, которые еще добыть нужно было. Или из debug.com (и .com тут совсем не домен :-) ).
              • 0
                А сам домен захватили какие-то сквоттеры. Засранцы, блин.
            • +8
              Стыдно раком Но весело раком
      • +1
        Небольшие замечания. Перечислены не все способы фильтрации/перехвата трафика
        6. Windows Filtering Platform. Самый гибкий способ, позволяющий производить прослушивание/фильтрацию трафика на множестве уровней сетевого стека, но при этом требующий внимания ко множеству деталей.
        7. Lightweight NDIS Filters. Простейший способ, допускающий прослушивание/фильтрацию пакетов.
        8. ETW (Microsoft-Windows-NDIS-PacketCapture). В частности команда «netsh trace start capture=yes» включает сниффинг пакетов. Самый простой способ: не требует дополнительных драйверов вообще, но работает только в Windows 7

        Замечание насчет TDI фильтров: они просто не работают на современных версиях Windows (начиная с Vista). То есть они то нормально встраиваются в стек \Device\Tcp, например, и какие то legacy TDI-клиенты наверное все еще будут использовать TDI для общения с сетью, но вся винда (в том числе afd.sys, который используется WinSock-ом) использует WSK. По моему опыту, TDI фильтры систему не замедляют, встроиться в стек довольно легко, но вот количество нюансов, которые нужно понимать действительно слишком высоко.
        • 0
          Спасибо большое за конструктивное замечание.
        • 0
          За статью большое спасибо. Было бы круто еще почитать и о драйверах файловой системы.
          • 0
            На здоровье. Я думаю закончим с NDIS и переберемся на освещение и этой темы. Хотя наверное порядок освещения тем стоило бы поменять, но уж как получилось))
          • 0
            Очень хотелось бы почитать о драйверах NDIS Miniport, изменяющих данные пакетов.

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