Как стать автором
Обновить
999.35
OTUS
Цифровые навыки от ведущих экспертов

Сетевая подсистема в ОС

Время на прочтение7 мин
Количество просмотров15K

Для будущих студентов курса «Сетевой инженер» и всех интересующихся подготовили полезную статью.

Также приглашаем на открытый вебинар по теме «NAT — не Firewall». Участники вебинара вместе с экспертом рассмотрят NAT и его использование, почему NAT != firewall, а также различные виды конфигураций для разных ситуаций.


В данной статье будет проведено исследование сетевой подсистемы ОС Windows и Linux, а также предложен план изучения подсистем операционной системы. Основная задача исследования - понять, из чего состоит сетевая подсистема; какие поддерживает протоколы из коробки; какие дополнительные механизмы использует в своей работе.

Disclamer: Статья описывает данные, которые с точки зрения автора помогут понять, как работают операционные системы с моделью TCP/IP, и не претендует на полноту.

Инструментарий и метод исследования

Для исследования операционной системы будем использовать следующие инструменты:

  • Операционная система Linux:

    • git;

    • Visual Studio Code;

  • Операционная система Windows:

    • strings.exe;

    • radare2;

    • hxD Editor;

    • Python;

    • Process Explorer.

Инструменты подобраны таким образом, чтобы можно было охватить максимальное количество форматов файлов, которые можно обнаружить в ОС. Для исходного же кода главный инструмент - редактор, который позволяет удобно переходить от исходника к исходнику для разбора кода.

В нашем исследовании будем руководствоваться двумя правилами:

  1. Используем всю информацию из документации операционных систем;

  2. Проверяем правдивость описанных данных. Для структур данных:

    • В ОС Windows исследуем соответствующие функционалу dll, sys файлы;

    • В ОС Linux исследуем исходные коды и отдельные ветки ядра;

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

Проблемы при исследовании ОС Linux

Основной функционал подсистемы целиком находится в ядре. К счастью, исходный код доступен в сети. Исследование исходного кода таких больших проектов всегда довольно сложная задача. На её сложность может влиять несколько факторов:

  1. Субъективные:

    • у каждого исследователя разный уровень экспертизы в области языка программирования, который используется в исходном коде;

    • у каждого исследователя есть свой собственных подход на интерпретацию полученной информации.

  2. Объективные:

    • ограниченности исследования по времени;

    • объем исходного кода;

    • принятые правила кодирования проекта.

Как минимизировать количество действий исследователя, чтобы получить как можно больше полезной и интересной информации? Огромную роль играет правильно настроенное рабочее место. В нашем случае верную настройку определяет набор инструментов, который мы описали в разделе "Инструментарий и метод исследования". Также можно применить небольшой лайфхак и не рассматривать каждую строку исходников ядра, а рассматривать только высокоуровневые элементы. Это сэкономит время на изучение языка программирования и даст возможность разобраться, что к чему. Попробуем применить эту тактику на практике.

Сетевая подсистема Linux

Начнем наше исследование с вот такой интересной картинки:

Картинка представляет собой структуру директорий исходного кода ядра ОС Linux. На ней видно, что сетевая подсистема вовсе не самая большая часть операционной системы. По правде говоря, можно собрать ядро и без этой части. Сегодня это вариант только для embeded систем, в общем случае без сети представить Linux сложно.

Код, который относится к сетевой подсистеме, находится в директории "net". Посмотрим, из чего он состоит.

Исходный код собран по выполняемым задачам. За базовыми элементами можно обратиться в директорию core:

На картинке выделены названия файлов, которые описывают основные структуры для работы с сетью. Это создание сокетов, хранение пересылаемых данных и работа с фильтрующей подсистемой bfp. Именно этот код переиспользуется для остальной части сетевой подсистемы.

Оставшиеся файлы в директории "net" описывают работу ядра с различными протоколами. Интересным моментом здесь является то, что фильтрующая подсистема имеет какие-то файлы только в некоторых протоколах и подсистемах:

Прямоугольниками выделены те протоколы и подсистемы, которые содержат файлы netfilter. Как видно из картинки, механизм фильтрации трафика работает не со всеми протоколами. Также интересно то, что он присутствует не только в протоколах, но и в более высокоуровневой абстракции - bridge. Теперь понятно, почему bridge от Linux можно настроить настолько гибко и контролировать пересылаемые данные.

Что в итоге? Всего по 4м картинкам структуры исходных кодов ядра мы уже обладаем информацией о том, какие поддерживаются протоколы в ядре Linux, какие механизмы интегрированы в протоколы для контроля и фильтрации и где найти базовые элементы, которые позволяют использовать сеть. Попробуем найти эту информацию и в ОС Windows.

ОС Windows: сетевая подсистема

Изучить сетевую подсистему этой ОС так же просто, как в ОС Linux, не получится. Самый большой камень преткновения - закрытый исходный код. Однако давайте попытаемся восстановить информацию о том, как работает сетевая подсистема в рамках этой ОС. В качестве целей будем использовать то, что нашли в Linux:

  • Где располагается код для создания и работы с сокетами;

  • Какой механизм используется для фильтрации;

  • Как имплементированы протоколы.

    Сетевая подсистема, согласно документации построена по принципу модели OSI. И также приводится описание того, за счет каких технологий и типов файлов реализуется работа отдельных уровней модели.

Имплементация модели OSI в операционной системе начинается со строго определенных уровней. В данном случае всё начинается на уровне "Канальном" и заканчивается на уровне "Транспортном". Имплементация на каждом уровне своя:

  • Канальный уровень - состоит из MAC и LLC, соответственно и частей имплементации должно быть две:

    • MAC - miniportdriver это драйвер, который контролирует сетевой интерфейс;

    • LLC - protocol driver - драйвер, который используется для обработки данных от сетевых устройств;

  • Уровень сети - protocol driver - драйвер, который используется для обработки данных от сетевых устройств;

  • Уровень транспорта - protocol (transport) driver;

Вот и выявилось коренное отличие Windows от Linux - вся логика работы сетевой подсистемы разбита на множество элементов. Каждое устройство, каждый протокол и абстракция имплементированы не в ядре, а в модуле ядра - драйвере, который может быть загружен ядром по запросу. Что это значит для нас? У нас нет исходного кода данных драйверов, а значит мы не можем использовать подход, который использовали при изучении ОС Linux.

Как же быть? При разработке эксплойтов исследователи в качестве отправной точки для восстановления структур внутри ядра Windows используют проект с открытым исходным кодом - ReactOS. Попробуем сделать тоже самое. Давайте найдем части подсистемы и затем спроецируем найденную информацию на реальную ОС Windows.

На экране ниже приведен снимок директории с основными драйверами для сетевой подсистемы:

Попробуем найти такие же файлы в реальной ОС. Заглянем в директорию "%Windows%". В качестве исследуемой системы возьмем Windows 7.

Часть файлов действительно имеет названия файлов, которые присутствуют в реальной ОС.

Один из способов проверки функционала уже скомпилированного приложения - прочитать используемые им строки. Можем для этого воспользоваться утилитой strings.exe для tcpip.sys:

Похоже, что данные по работе с сетевой подсистемой можно обнаружить именно в этом драйвере. Поищем функции, которые позволяют фильтровать трафик. Как их идентифицировать?

В операционной системе Windows за всё время её существования было 2 технических спецификаций на основании которых создавались драйвера для сетевого взаимодействия: TDI и WinSock. И все эти спецификации использовали отдельный драйвер для того чтобы можно было собирать весь функционал - NDIS. Значит большая часть функций сконцентрирована в этих драйверах:

  • netio.sys

  • tcpip.sys

  • tdi.sys

  • ndis.sys

Но в них все равно нет функций, которые бы могли фильтровать трафик. Почему так? Дело в том, что до Windows 7 фильтрация трафика как такового была имплементирована в отдельных драйверах, которые настраивались за счет интерфейса Windows. Начиная с Windows 7 была реализована так называемая Windows Filtering Platform, которая определила часть драйверов в специальную категорию, которая и призвана фильтровать трафик.

Часть этих фильтров можно найти по обычному поиску в директориях ОС:

 Get-ChildItem "C:\WINDOWS\System32" FWPKCLNT.SYS -Recurse | Select-Object FullName
 Get-ChildItem "C:\WINDOWS\System32" wfplwf.sys -Recurse | Select-Object FullName

Используем утилиту strings.exe на файлы FWPKCLNT.SYS и wfplwf.sys:

Выше представлена часть строк, которые обнаружились в файле FWPKCLNT.sys, файл wfplwf.sys содержал только названия функций. Почему тогда они здесь вместе? Дело в том, что в импортах wfplwf.sys есть функция, которая берется из файла FWPKCLNT.sys:

В итоге:

  1. Имплементация всех объектов и механизмов в ядре для работы с протоколами - файлы из директории %Windows%\System32\Drivers. Основные из них - netio.sys, ndis.sys, tdi.sys.

  2. Фильтрацией занимаются драйвера WFP: FWPKCLNT.sys, wfplwf.sys.

  3. Имплементируются через отдельные одноименные файлы, например: tcpip.sys

В ОС Linux мы не задумывались о том как приложения получают доступ к структурам ядра и работают с сетью. Там более-менее всё очевидно и только один шаг до функций, но для Windows всё работает по принципу Callback`ов. Поэтому скорее всего будет несколько оберток для взаимодействия. Попробуем найти эти файлы.

Для поиска файлов, которые используются в качестве обертки-библиотеки, можно использовать следующий метод. Для этого создадим мини приложение, которое будет работать с сокетами, принимать и отправлять данные. Исходный код приложения:

import socket

HOST = '127.0.0.1'  
PORT = 10000        

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

Запускаем файл в ОС, если не возникло никаких ошибок, то необходимо параллельно запустить инструмент Process Explorer. С помощью этого инструмента мы подсмотрим, чем занимается поток, пока ждет соединения. На картинке ниже отображены все описанные действия:

Слева изображен стек вызовов функций, которые задействованы в процедуре настройки сокета и перевода его в состояние bind. Этот набор файлов - mswinsock.dll (Win Sock 2 Service) и WS2_32.dll(Windows Socket 2). Данные библиотеки используются для того, чтобы предоставить приложениям функции по работе с сокетами в ОС Windows.

Стоит отметить, что последовательность функций, которые вызываются для работы сокета в ОС, не виден в Process Explorer`е. Если нужно восстановить и эти данные, то нужно использовать отладчик ядра.

Таким образом, проводить исследование подсистем любых ОС и их механизмов можно с исходным кодом и без — достаточно выбрать необходимый набор инструментов, а также доступные методы, источники знаний.


Узнать подробнее о курсе «Сетевой инженер».

Зарегистрироваться на открытый вебинар по теме «NAT — не Firewall».

Теги:
Хабы:
Всего голосов 16: ↑9 и ↓7+5
Комментарии3

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS