Что такое код wddx_packet_end

Содержание

Что такое код wddx_packet_end

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

wddx_packet_end — Ends a WDDX packet with the specified ID

Description string wddx_packet_end ( resource packet_id )

wddx_packet_end() ends the WDDX packet specified by the packet_id and returns the string with the packet.

Пред. Начало След.
wddx_deserialize Уровень выше wddx_packet_start

Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:

Wddx_packet_end

Php функции


Php скрипты


wddx_packet_end

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

wddx_packet_end — Ends a WDDX packet with the specified ID

Description

string wddx_packet_end ( resource packet_id )

wddx_packet_end() ends the WDDX packet specified by the packet_id and returns the string with the packet.

User Contributed Notes

There are no user contributed notes for this page

Packet crafting как он есть

Создание пакетов или packet crafting — это техника, которая позволяет сетевым инженерам или пентестерам исследовать сети, проверять правила фаерволлов и находить уязвимые места.
Делается это обычно вручную, отправляя пакеты на различные устройства в сети.
В качестве цели может быть брандмауэр, системы обнаружения вторжений (IDS), маршрутизаторы и любые другие участники сети.
Создание пакетов вручную не означает, что нужно писать код на каком-либо высокоуровневом языке программирования, можно воспользоваться готовым инструментом, например, Scapy.

Scapy — это один из лучших, если не самый лучший, инструмент для создания пакетов вручную.
Утилита написана с использованием языка Python, автором является Philippe Biondi.
Возможности утилиты практически безграничны — это и сборка пакетов с последующей отправкой их в сеть, и захват пакетов, и чтение их из сохраненного ранее дампа, и исследование сети, и многое другое.
Всё это можно делать как в интерактивном режиме, так и создавая скрипты.
С помощью Scapy можно проводить сканирование, трассировку, исследования, атаки и обнаружение хостов в сети.
Scapy предоставляет среду или даже фреймворк, чем-то похожий на Wireshark, только без красивой графической оболочки.
Утилита разрабатывается под UNIX-подобные операционные системы, но тем не менее, некоторым удается запустить ее и в среде Windows.
Эта утилита так же может взаимодействовать и с другими программами: для наглядного декодирования пакетов можно подключать тот же Wireshark, для рисования графиков — GnuPlot и Vpython.
Для работы потребуется права суперпользователя (root, UID 0), так как это достаточно низкоуровневая утилита и работает напрямую с сетевой картой.
И что важно, для работы с этой утилитой не потребуются глубокие знания программирования на Python.

Приступаем

Официальный сайт проекта — www.secdev.org/projects/scapy
Установку можно провести разными способами, например apt-get install python-scapy, в случае дистрибутивов на основе Debian.
Так же можно просто скачать свежую версию с сайта разработчиков:
# cd /tmp
# wget scapy.net
# unzip scapy-latest.zip
# cd scapy-2.*
# sudo python setup.py install
После этого запуск происходит непосредственно командой scapy.
На экране отобразится примерно так:

Мы видим стандартное приглашение для ввода, все действия будут выполняться в интерактивном режиме.
Выход происходит комбинацией Ctrl+D, либо набрав функцию exit().

Изучаем инструмент

На самом деле Scapy сильно отличается от привычных утилит. Он работает в текстовом режиме, но любое взаимодействие осуществляется не через привычные ключи и параметры командной строки, а через интерпретатор Python’а.
Такой подход вначале может показаться несколько неудобным и непривычным, но со временем и с практикой приходит понимание того, что это было правильным решением, и что это действительно удобно.

Вначале посмотрим на поддерживаемые протоколы, для этого вызовем функцию ls().

Вывалится более 300 разнообразных протоколов, с которыми можно работать, включая прикладные вроде HTTP, транспортные TCP и UDP, сетевого уровня IPv4 и IPv6 и канального уровня Ether (Ethernet).
Важно обращать внимание на регистр: большинство протоколов пишутся в Scapy с заглавными буквами.
Для того чтобы подробно рассмотреть поля определенного протокола, можно вызвать функцую ls() с указанием протокола: ls(TCP)

В результате будут выведены все поля, которые можно модифицировать в процессе создания пакетов. В скобках показаны значения, которые используются по умолчанию, можно заметить, что порт отправителя 20 (это ftp-data) и порт получателя – 80 (это естественно HTTP), так же установлен флаг SYN (flags = 2).

К примеру, если рассмотреть канальный уровень (Ethernet), то тут возможностей будет поменьше:

В дополнение к функции ls(), есть полезная функция lsc(), которая выведет практически весь основной функционал Scapy:

Для того чтобы получить более подробную информацию о каждой функции, можно использовать help(имя_функции), например:

Видим нечто похожее на MAN страницу в Unix системах.
Для выхода можно использовать опять же привычную в Linux клавишу Q.

Мы посмотрели на протоколы и функции, теперь можно перейти к делу — к созданию пакетов.

Крафтим

Можно создавать сразу пакеты высоких уровней (сетевого и прикладного), и Scapy автоматически дополнит низлежащие уровни, а можно вручную собирать, начиная с канального уровня.
Разделяются уровни модели OSI символом прямого слэша (/).
Нужно обратить внимание на то, что Scapy читает пакет от нижнего уровня слева, до более высокого справа. Поначалу это может немного сбивать с толку, но после небольшой практики всё станет вполне привычно.
К слову, в терминологии Scapy сетевой пакет разделяется на слои, и каждый слой представляется как экземпляр объекта.
Собранный пакет в упрощенном виде может выглядеть как:
Ether()/IP()/TCP()/”App Data”
В большинстве случаев используется только уровень L3, предоставляя Scapy возможность самостоятельно заполнять канальный уровень, на основе информации из ОС.
Меняя значения полей каждого протокола мы меняем стандартные значения (их выводит функция ls()).

Теперь создадим какой-нибудь простой пакет.

Всё очень просто: мы указали адрес назначения, порт и вобщем-то нагрузку в виде слова «TEST».
Сам пакет был незамысловато назван packet, мы увидим очень подробно и развернуто наш свежесозданный пакет:
И теперь, выполнив знакомую уже функцию ls(packet):

Уровни в нем разделяются символами «—«.

Вместо того, чтобы создавать пакет за один раз можно создавать его частями:

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

И теперь собираем всё в один пакет:

Видно, что результат получится аналогичный.

Углубляемся в пакеты

Мы уже смотрели на вывод функции ls(), но не всегда нужна такая подробная информация о пакете.
Достаточно просто набрать имя переменной и сразу увидеть краткую сводку:

Так же можно использовать метод summary():

Если же нужно чуть больше информации, то есть метод show():

Кроме того, можно просмотреть любое поле, просто указав его:

Разумеется, это работает только в том случае, если такие поля уникальны в пределах пакета.
Если, например, взять поле flags, которое присутствует как в TCP, так и в IP, тут уже нужно конкретизировать, что мы хотим увидеть. В противном случае Scapy выведет значение первого найденного поля (IP flags в нашем примере).
Конкретизация происходит путем указания протокола в квадратных скобках:

К слову, по умолчанию установленные флаги выводятся в цифровом представлении.
Если все управляющие биты будут включены (установлены в 1), то получим значение равное 255. В нашем случае значение 2 говорит о том, что установлен SYN бит.

Но существует возможность отобразить управляющие биты и в символьном отображении:

Как уже говорилось, в любой момент можно достаточно просто поменять значение любого поля:

А в случае, если поле не является уникальным, то нужно указать протокол:

Вторым способом является использование конструкции payload, которая позволяет перепрыгнуть через один уровень (через L3 в нашем случае):

Здесь мы вначале просматриваем вывод слоев над L3, затем просматриваем значение TCP флагов и устанавливаем для них новое значение.
Кстати, можно даже несколько раз вызвать payload, поднимаясь при этом выше и выше:

Можно еще посмотреть на содержимое пакета в шестнадцатеричном виде, для этого есть функция hexdump():

Разбираемся с адресацией

Scapy и в деле указания адреса получателя так же проявляет большую гибкость.
Масса вариантов — здесь и привычная десятичная форма, и доменное имя и CIDR нотация:

В последнем случае пакет будет отправлен на каждый адрес в подсети.

Множество адресов можно задать, просто разделяя их запятой, не забыв про квадратные скобки:

На этом этапе может возникнуть мысль: «А что если нужно задать множество портов?».
И тут Scapy предоставляет широкие возможности, можно указать как диапазон, так и просто перечислить множество:

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

Вначале мы уже привычно создаем пакет, в котором указываем подсеть и диапазон портов.
Затем, используя цикл, создаем список, где переменной «а» присваивается каждый элемент структуры пакета. В Python’е отсутствуют массивы в привычном понимании. Вместо них для хранения объектов используются списки.
Мы используем цикл for, для того чтобы «распаковать» всю структуру и отобразить ее в таком наглядном виде.

Отправляем пакеты в путь

С таким же размахом и широтой происходит и отправка пакетов:

  • функция send() – отправляет пакеты, используя сетевой (L3) уровень, никак не обрабатывая ответы. Используется принцип — отправили и забыли;
  • функция sendp() – отправляет пакеты, используя канальный (L2) уровень, учитываются указанные параметры и заголовки Ethernet кадров. Ответы всё так же не ожидаются и не обрабатываются;
  • функция sr() – является аналогичной send(), исключение составляет то, что она уже ожидает ответные пакеты;
  • функция srp() – отправляет и принимает пакеты, уровень L2
  • функция sr1() – отправляет пакет третьего уровня и забирает только первый ответ, множество ответов не предусматривается;
  • функция srp1() – аналогично sr1(), только уже канальный уровень.

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

Но вместе с тем существует много дополнительных опций, которые могут быть иногда полезны.
Например, timeout – укажет, сколько времени (в секундах) нужно ждать до получения ответного пакета, retry – сколько раз нужно повторно слать пакет, если ответ не был получен и одна из самых полезных опций – это filter, синтаксис которого очень похож на tcpdump.

В качестве наглядного примера отправим пакет в сеть:

Здесь мы используем функцию, которая после отправки ожидает ответ, устанавливаем таймаут 0.1 секунды и фильтруем ответы, которые подпадают под указанное правило.

Как поступать с ответными пакетами?
Можно взять и назначить переменную, которая и будет содержать ответ:

А смотреть уже привычным способом, просто вызывая переменную response.
Видно, что ответ сохранился в двух вариантах – Results и Unanswered, результаты и без ответа, соответственно.
Указывая смещение, можно вывести только необходимую часть ответа:

Или подробную информацию:

Если же пакет был отправлен в сеть без указания переменной (например, просто функцией sr()), то по умолчанию пакет будет числиться за переменной «_» (символ подчеркивания).

Чтобы достать оттуда эти пакеты, можно использовать конструкцию:

При этом разные результаты сохранятся в двух разных переменных (res и unans).

Более подробный вывод достигается опять же путем указания смещения:

Ловим ответные пакеты

Теперь рассмотрим ситуацию, если пакетов в ответ приходит много.

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

Открытые порты будут с флагами SA (SYN/ACK), например:

Мы смотрим именно на пакет по номеру, счет традиционно начинается нуля.

Можно пойти дальше и распаковать этот результат:

Здесь мы извлекли из результата отправленный пакет (под номером 21) и ответ на него.
Но это только один пакет, а как быть, если нужно обработать все пакеты?
В таком случае придется вновь обращаться к циклу for:

Берем и разбиваем каждый элемент списка res на части a и b. Затем обрезаем часть “a”, заливая это всё в список “allsent”.
Аналогично создаем список allrec, только уже оставляем другую часть.
Всё это, конечно, хорошо, но хотелось бы в более удобном виде получить список открытых и закрытых портов.
Еще раз посмотрим на список res, a точнее на элемент res[0], который состоит из двух частей: пакет, который мы отправили res[0][0], и ответ, который получили res[0][1].

В ответе можно обнаружить три части — заголовок IP (res[0][1][0]), заголовок TCP (res[0][1][1]) и собственно сами данные (res[0][1][2]).

Используем цикл for для извлечения каждого элемента res[N] в переменную «а».

Теперь в переменной «a»содержится результат для каждого пакета. Другими словами «а» представляет собой ans[N].
Нам остается только проверить значения a[1][1], которые будут означать res[N][1][1] в заголовке TCP.
Если быть еще более точным, требуется значение 18, которое означает установленные флаги SYN-ACK.

В тех случаях, когда это условие сработает, мы еще выведем порт отправителя из заголовка TCP:

В итоге, получим результат в виде списка открытых портов.
Все вышеозначенные конструкции набираются за один раз, важно так же уделять внимание отступам (обычно это 4 пробела).

Мы только что вручную написали простой сканер портов, не больше и не меньше.

Сниффер и наоборот

В Scapy входит также и небольшой сниффер, за который отвечает функция sniff().
Естественно, с ним можно использовать фильтры (похожие на фильтры tcpdump), за это отвечает параметр filter, так же можно ограничивать количество пакетов с помощью параметра count.
Как всегда вызов help(sniff) выведет вполне подробную информацию по этой функции.
Не следует забывать, что это сильно упрощенный сниффер, и ожидать от него хорошей скорости особо не приходится.
Стандартная комбинация Ctrl+C прервет процесс захвата трафика и выведет результат.
Как и любая неопределенная переменная, результат попадет в «_».
Выполнив метод summary(), можно увидеть статистику по захваченным пакетам:

Вместо захвата трафика из сети, можно прочитать его из заранее сохраненного дампа (pcap файла).

Кроме того, можно и наоборот, записать пойманные пакеты в файл, используя функцию wrpcap():

И завершая тему сниффинга, можно вызвать Wireshark прямо из интерфейса Scapy, для этого можно использовать одноименную функцию wireshark().

Подробно про Wireshark можно в моей предыдущей статье по адресу http://linkmeup.ru/blog/115.html.

Автоматизация

Казалось бы, что уже всё готово, но не тут то было.
При очередной попытке подгрузить ospf модуль:
>>> load_contrib(‘ospf’), получаем всё ту же ошибу «ERROR: No module named contrib.ospf»
Для того, чтобы модуль окончательно заработал, осталось создать скрипт инициализации (пустой файл):
touch /usr/lib/python2.7/dist-packages/scapy/contrib/__init__.py
После этого, уже можно будет создавать пакеты для OSPF.

Создаем трехэтапное TCP-соединение

Для этого нужно будет поймать SYN/ACK ответ, извлечь из него TCP sequence number, увеличить значение на единицу и, собственно, и поместить полученное значение в поле acknowledgement number.
Непростая задача на первый взгляд, но Scapy может справиться и с ней.
Вначале рассмотрим, что нам нужно, для того чтобы всё прошло успешно.

1) Отправить SYN принимающей стороне:

  • собрать заголовок IP, не забыть про адрес отправителя и получателя;
  • собрать TCP заголовок, в котором нужно будет указать TCP порты отправителя и назначения, установить TCP флаги (SYN бит) и сгенерировать ISN (Initial Sequence Number).

2) Поймать ответный пакет:

  • сохранить ответ;
  • извлечь из него TCP sequence number и увеличить это значение на единицу.
Илон Маск рекомендует:  Тег colgroup

3) Создать подтверждение (ACK) на полученный ответный пакет:

  • собрать заголовок IP, содержащий такие же адреса отправителя и получателя, как в случае SYN пакета;
  • собрать TCP заголовок, с такими же номерами портов, как и в SYN сегменте, но уже установить ACK флаг, увеличить значение ISN на единицу и установить acknowledgement в извлеченный и увеличенный, на втором шаге, sequence number.

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

192.168.10.200 1024 > 192.168.10.50 80 flags=SYN seq=12345
192.168.10.50 80 > 192.168.10.200 1024 flags=SYN, ACK seq=9998 ack=12346
192.168.10.200 1024 > 192.168.10.50 80 flags=ACK seq=12346 ack=9999

Что в итоге нужно было сделать.

1) Отправить SYN принимающей стороне:

  • собрать заголовок IP, в котором указать в качестве отправителя 192.168.10.200 и 192.168.10.50 в качестве получателя;
  • собрать TCP заголовок с портом источника (source) 1024 и портом назначения (destination) 80. Так же установить SYN флаг и сгенерировать ISN равный 12345.

2) Поймать ответный пакет:

  • сохранить ответ;
  • извлечь из него TCP sequence number (9998) и увеличить это значение на единицу, получим 9999.

3) Создать подтверждение (ACK) на полученный ответный пакет:

  • собрать заголовок IP, в котором указать в качестве отправителя 192.168.10.200 и 192.168.10.50 в качестве получателя;
  • собрать TCP заголовок с такими же портами источника и назначения (1024 и 80 соответственно), установить ACK флаг, увеличить ISN на единицу (12346) и установить acknowledgement в увеличенное значение пойманного seq number (9999).

Начнем собирать пакет:

Здесь уже всё должно быть знакомым: пакет собираем из двух частей, инкапсулируя TCP в IP.

Теперь помня о том, что нам нужно будет перехватить ответ, извлечь оттуда sequence number и увеличить на единицу, делаем:

Происходит следующее – функция sr1 отправляет ранее созданный пакет в сеть, а первый пришедший ответ помещается в переменную SYNACK.
А затем, используя конструкцию SYNACK.seq, извлекаем TCP sequence number, увеличиваем его на единицу и сохраняем в переменной my_ack.

Создаем новый заголовок TCP и называем его ACK. В нем устанавливается другой флаг (A — ACK) и увеличивается значение sequence number.
Кроме того, в качестве acknowledgement указывается переменная my_ack.
Затем собранный пакет выбрасывается в сеть командой send (помним, что это L3 команда, которая даже не слушает, что придет в ответ).
Если всё было сделано правильно, то классическое TCP-соединение состоялось.
Осталось только создать TCP сегмент без каких-либо флагов и тоже отправить в сеть.

Как можно увидеть, мы в очередной раз создали экземпляр TCP заголовка (в этот раз, назвав его PUSH), без флагов и со всеми остальными знакомыми уже значениями.
После этого добавили немного данных, используя переменную data, и отправили в сеть, используя ту же функцию send.
И соответственно от получателя должен будет прийти acknowledgement на этот сегмент.

>>> ip=IP(src=«192.168.10.200»,dst=«192.168.10.50»)
>>> SYN=TCP(sport=1024,dport=80,flags=«S»,seq=12345)
>>> packet=ip/SYN
>>> SYNACK=sr1(packet)
>>> my_ack=SYNACK.seq+1
>>> ACK=TCP(sport=1024,dport=80,flags=«A»,seq=12346,ack=my+ack)
>>>send(ip/ACK)

Но здесь есть и несколько подводных камней.
Если посмотреть на этот обмен в Wireshark, можно увидеть, что до того как ушел наш ACK пакет, внезапно был отправлен RST:

Дело в том, что Scapy работает мимо TCP/IP стека ОС. Это означает то, что ОС не подозревает о том, что Scapy отправляет какие-то пакеты.
Соответственно ОС не будет ожидать появления SYN/ACK пакетов. И, следовательно, соединение будет сразу же сброшено.
Очевидно, что это совсем не тот результат, который нам нужен.
Одним из решений такой проблемы будет использование функционала пакетного фильтра, в частности iptables, который сможет блокировать исходящие RST пакеты.
Например, таким образом:
# iptables -A OUTPUT -p tcp -d 192.168.10.50 -s 192.168.10.200 —dport 80 —tcp-flags RST RST -j DROP
Выполнение такой конструкции приведет к тому, что все исходящие пакеты с адресом назначения 192.168.10.50 и с адресом отправителя 192.168.10.200 на 80-й порт, с установленным RST флагом, будут отбрасываться.
Пакеты будут все так же генерироваться силами ОС, но они просто не будут вылетать за ее пределы.
В итоге уже ничего не будет мешать Scapy делать полноценную TCP-сессию:

Продолжаем исследования

Используя Scapy, можно находить хосты в сети, среди указанного множества адресов:

В этом случае мы используем протокол ICMP и применяем знакомый прием по разделению полученных ответов.

По умолчанию, установлен 8-й тип для ICMP, это и есть классический эхо-запрос.

Углубляясь в тему ИБ, попробуем определить версию ОС используя Scapy и nmap.

Итак, рассмотрим что было сделано.
Вначале был подключен внешний модуль, в данном случае nmap.
Затем проверяем, что у нас есть файл (nmap-os-fingerprints) с отпечатками различных ОС.
И запускаем непосредственно определение удаленной операционной системы, за это отвечает функция nmap_fp, где в качестве параметров помимо самой цели, можно еще указать открытый (oport) и закрытый (cport) порты.
Правильно указанные порты помогут сильно улучшить точность определения ОС.

Визуализируем пакеты

Все время мы смотрели на текстовый вывод, местами была псевдографика, но Scapy умеет и выводить некоторые результаты в графическом виде.
Посмотрим, что нам предлагается.
Самое простое — это метод conversations():

При его выполнении, запустится окно ImageMagick, в котором отрисуется схема нашего обмена пакетами, не ахти красиво, но достаточно наглядно.
Это способ, вероятно, лучше всего подойдет, для визуализации дампов с трафиком.

Второй способ заключается в построении 2D графиков, с последующим экспортом их в pdf-файл.

За это уже отвечает функция pdfdump().
Результаты выглядят примерно так:

В данном случае уже вполне неплохо.
Кроме того, функция graph() опять откроет окно ImageMagick, но уже с детальной прорисовкой:

Здесь мы видим результат трассировки, с подробным отображением автономных систем и прочей визуализацией.

И, завершая тему визуализации, а вместе с ней и статью, посмотрим на 3D отображения трассы.
Для этого потребуется VPython и команда trace3D().

Здесь отображена трасса из предыдущего графика.

Но иногда бывают и такие варианты:

В этом примере была проведена трассировка сразу нескольких целей, с использованием нескольких (80, 443) tcp портов.
Левый клик на любом объекте приведет к появлению IP-адреса над ним, а левый клик с зажатой клавишей CTRL – к отображению более подробной информации — портам, как в этом случае.

Эпилог

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

В процессе написания статьи использовались материалы Института SANS и официальная документация проекта.

Курс по основам компьютерных сетей на базе оборудования Cisco. Этот курс поможет вам подготовиться к экзаменам CCENT/CCNA, так как за его основу взят курс Cisco ICND1.

9.3 Структура, формат и назначение DHCP пакетов (сообщений): DHCPDISCOVER, DHCPOFFER, DHCPREQUEST и DHCPACK

Привет, посетитель сайта ZametkiNaPolyah.ru! Продолжаем изучать основы работы компьютерных сетей. Продолжаем разбираться с протоколом DHCP в рамках подготовки к CCNA. В протоколе DHCP для сетевого инженера нет ничего сложного, вы в этом убедитесь сразу после того, как мы с вам разберемся со структурой DHCP-пакетов и увидим как сервер и клиент отправляют другу другу сообщения, в этой записи мы разберем четыре самых часто используемых DHCP-сообщения: DHCPDISCOVER, DHCPOFFER, DHCPREQUEST и DHCPACK.

Перед началом я хотел бы вам напомнить, что ознакомиться с опубликованными материалами первой части курса можно по ссылке: «Основы взаимодействия в компьютерных сетях».

9.3.1 Введение

Здесь мы рассмотрим структуру DHCP пакета и поговорим о их назначении DHCP-сообщений. В частности будут рассмотрены такие виды DHCP сообщений как: DHCPDISCOVER, DHCPOFFER, DHCPREQUEST и DHCPACK. Дам небольшое пояснение по поводу того, что я буду подразумевать под словом DHCP-пакет, а что под DHCP-сообщением. Под первым я буду понимать физическую сущность со строгой структурой, а под вторым я буду понимать логический смысл, который несет в себе физическая сущность, пакет всего один, а сообщений много и они разные.

9.3.2 Общая структура DHCP пакета, назначение его полей и их размер

Мы довольно наглядно рассмотрели процесс получения IP-адреса по DHCP в Cisco Packet Tracer, но хотелось бы понимать то, как устроены пакеты DHCP, которыми обменивается клиент и сервер. Тут у меня для вас две новости:

  1. Начну с хорошей. При обмене различными сообщениями и клиент, и сервер используют пакеты с одинаковой структурой, а это означает, что поля в различных DHCP-сообщениях имеют одинаковые названия и одинаковый размер, за исключением поля Options, о котором мы говорили, в записи про DHCP протокол, но в них указываются разные значения.
  2. Вторая новость не то что бы плохая, но всё же. Различного рода сообщений в DHCP много и не со всеми вы будете сталкиваться и не все вам будут нужны, но если столкнетесь, то придется почитать RFC, чтобы понять, как это должно работать, а потом заглянуть в дамп, чтобы увидеть, как это работает по факту.

На рисунке ниже вы можете увидеть структуру DHCP-пакета, там показаны поля DHCP пакета и их размер.

9.3.1 Структура DHCP-пакета, поля и их размер

Сама по себе картинка нам еще ничего не дает, кроме названия полей в DHCP-пакета, также мы видим, что пакет разбивается на строки (иначе, машинные слова), каждая строка 32-а бита. Крайний левый бит в слове имеет нулевой порядковый номер, а крайний правый бит 31-ый. Размер всех полей в битах кратен числу 8.

Давайте теперь поговорим более подробно о каждом поле DHCP пакета. Для их описания я подготовил таблицу.

Поле Описание Длина (в байтах)
opcode (op) Самое первое поле указывает нам на тип DHCP-сообщения. Если в этом поле вы видите значение 0×01, то это говорит нам о том, что сообщение является запросом от клиента к серверу. Такое сообщение еще иногда называется BOOTREQUEST. Если же в поле opCode записано значение 0×02, то это означает, что оно являет ответом DHCP-сервера или BOOTREPLY. 1
Hardware Type (htype) Тип адреса на канальном уровне. DHCP может работать поверх различных протоколов на канальном уровне, чтобы устройства понимали, что крутится на L2, нужно это поле. У этого поля есть список допустимых значений (смотрите RFC 1700), случайное значение здесь появиться не должно. Для протокола Ethernet и его MAC-адресов используется значение 0×01. 1
Hardware Length (hlen) Длина аппаратного адреса в байтах. Для протокола Ethernet и, соответственно, мак-адресов, указывается значение 0×06. 1
Hops Количество промежуточных маршрутизаторов, которые находятся на пути между клиентом и сервером. Сейчас нам это поле пока не интересно, с ним мы поработаем, когда будем разбираться с DHCP Relay Agent. DHCP-клиенты всегда в это поле записывают значение 0×00. 1
Transaction ID (xid) Когда клиент начинает процесс получения IP-адреса, он генерирует значение для этого поля, чтобы сервер не дай бог не перепутал конкретный процесс этого клиента с другим процессом. 4
Seconds Elapsed (secs) Время в секундах с момента начала процесса получения IP-адреса, это время обычно никого не интересует и обычно в нем стоят нули: 0×0000. 2
Flags Поле для флагов или специальных параметров протокола DHCP. 2
Client IP Address (ciaddr) Поле, в котором указывается IP-адрес клиента. Клиент заполняет его только в том случае, если у него уже есть IP-адрес и он может ответить на ARP-запрос. Такая ситуация возможно в том случае, если клиент хочет продлить время аренды IP-адреса. 4
Your ID Address (yiaddr) В это поле DHCP-сервер вписывает IP-адрес, который хочет предложить клиенту. 4
Server IP Address (siaddr) IP-адрес сервера. Сервер указывает свой IP-адрес, когда делает DHCPOFFER. 4
Gateway IP Address (giaddress) Если используется схема с DHCP Relay Agent, то в этом поле передается его IP-адрес. 4
Client Hardware Address (chaddr) Если на канальном уровне используется протокол Ethernet, то в это поле записывается MAC-адрес клиента. 16
Server Host Name (sname) Если у сервера есть доменное имя/имя хоста, то он может сообщить его в этом поле, поле не является обязательным. 64
Boot File (file) Это поле также не является обязательным и служит указателем для бездисковых рабочих станций о том, как называется файл на сервере, которые следует использовать для загрузки. 128
Options Поле опций, в котором передается львиная доля полезной информации для динамической конфигурации хоста. Про опции мы уже говорили, здесь останавливаться не будем. Переменная

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

9.3.3 Сообщение DHCPDISCOVER или как клиент ищет DHCP сервер?

Начнем мы с сообщения DHCPDISCOVER, как вы помните, это сообщение использует клиент для поиска DHCP-серверов в своей канальной среде. Чтобы не быть голословными, будем смотреть на примере дампа из Wireshark. Для начала посмотрим на то, как клиент инкапсулирует сообщение DHCPDISCOVER.

9.3.2 Как инкапсулируется и передается по сети сообщение DHCPDISCOVER

Всё самое важное подсвечено красным цветом. Мы видим, что в качестве мак-адреса источника клиент подставил свой мак-адрес, а вот мак-адрес сервера он не знает, поэтому использует широковещательный мак-адрес. Даже если клиент будет знать IP-адрес DHCP-сервера, ему это не поможет, ведь для того, чтобы обратиться к серверу по протоколу IP, клиент должен сделать ARP-запрос, а как он это сделает, если у него еще нет IP-адреса?

В заголовке IP-пакета в качестве адреса источника клиент использовал 0.0.0.0, а IP-адрес назначения опять широковещательный – 255.255.255.255. DHCP упаковывается на транспортном уровне в UDP, поскольку сообщение DHSPDISCOVER генерирует клиент, он в качестве порта источника использует значение 68, а в качестве порта назначения 67. Ну и наконец мы видим, что Wireshark смог определить, что это сообщение DHCPDISCOVER. Попробуем определить и мы.

9.3.3 Формат сообщения DHCPDISCOVER

Для этого заглянем внутрь DHCP-пакета и проанализируем значения его полей. В самом верху мы видим тип сообщения Boot Request (это поле opcode), значение 1 говорит нам о том, что это клиент что-то посылает серверу. Следующих два поля сообщают нам, что на канальном уровне используется Ethernet и указана длина аппаратного адреса. Поле Hops имеет значение 0, а значит клиент считает, что он находится с сервером в одной канальной среде. Когда клиент начал общение с сервером, он сгенерировал уникальный Transaction ID, по которому можно будет отличить этот процесс получения IP-адреса от какого-нибудь другого. Поле Second Elapsed никому не интересно, тут обычно стоит 0.

Флаги – отдельная тема, сейчас мы их пропустим. У клиента еще нет и не было IP-адреса, клиент не знает IP-адрес сервера, клиент ничего не знает по DHCP Relay Agent, клиент сам себе не может выдать IP-адрес, поэтом следующих четыре поля имеют значения 0.0.0.0. В поле Client MAC Address клиент сообщает свой мак-адрес серверу. А вот поле Client Hardware Address Padding различается для машин с Windows и Linux, сейчас вы видите значение для Windows, это поле мы обсудим позже.

Далее клиент сообщает серверу о том, что ему не нужно сообщать hostname сервера и не надо давать ссылку на Boot-файл. Ну а поле Magic Cookie сообщает о том, что начались DHCP опции и нам нужно обратить внимание на следующий рисунок.

9.3.4 DHCP опции, которые передает клиент серверу в сообщение DHCPDISCOVER

Во-первых, стоит сразу отметить, что количество опции, да и сами опции, которые будут в сообщение DHCPDISCOVER зависят от настроек клиента. Первая опция имеет код 53, так клиент сообщает всем в сети, что данное сообщение является сообщением DHCPDISCOVER. Опция с кодом 61 используется клиентом, чтобы сообщить свой мак-адрес. В опции с кодом 50 клиент сообщает, что хотел бы получить от сервера IP-адрес 192.168.0.100. Опция с кодом 12 используется клиентом, чтобы сообщить свой hostname.

Опция с кодом 60 служит для того, чтобы клиент мог рассказать серверу о том, кто является разработчиком программного обеспечения DHCP-клиента, и какая версия ПО используется, опираясь на эту опцию сервер может понять с какими опциями умеет работать клиент. DHCP опция с кодом 55 служит для того, чтобы клиент мог запросить у сервера необходимые на его взгляд параметры, при этом не факт, что сервер сможет сообщить клиенту все указанные параметры.

Список опций завершает опция с кодом 255, так сервер поймет, что опций больше не будет и само DHCP-сообщение закончилось.

9.3.4 Сообщение DHCPOFFER или как сервер предлагает клиенту IP-адрес?

Перейдем к сообщение DHCPOFFER, которым сервер отвечает на запрос DHCPDISCOVER от клиента, тут самый первый вопрос, который у вас должен возникнуть: а как сервер отправляет сообщение DHCPOFFER – broadcast или unicast. Правильным будет ответ: сервер может передавать сообщение DHCPOFFER как широковещательно, так и адресно, вот что написано в RFC протокола DHCP.

Если поле giaddr в сообщении DHCP от клиента отлично от 0, сервер передает все отклики на сообщения в порт DHCP server транслятору BOOTP, адрес которого указан в поле giaddr. Если giaddr = 0, а поле ciaddr отлично от нуля, сервер передает сообщения DHCPOFFER и DHCPACK по индивидуальному адресу ciaddr. Если giaddr = 0, ciaddr = 0 и установлен флаг broadcast, сервер передает сообщения DHCPOFFER и DHCPACK по широковещательному адресу 0xffffffff. Если флаг broadcast не установлен, а giaddr и ciaddr имеют значение 0, сервер передает сообщения DHCPOFFER и DHCPACK по индивидуальному аппаратному адресу клиента и yiaddr. Во всех случаях, когда giaddr = 0, сервер отправляет сообщения DHCPNAK по широковещательному адресу 0xffffffff.

9.3.5 DHCPOFFER — сообщение, которое отправляет сервер в ответ на DHCPDISCOVER

Илон Маск рекомендует:  Как внести изменения в код vcl

Если посмотреть на дамп протокола IP, то можно будет увидеть, что сервер не просто направил клиенту DHCPOFFER юникастом, но и более того, в поле IP-адрес назначения был подставлен IP-адрес, который был запрошен клиентом в сообщение DHCPDISCOVER. Главным образом такое поведение DHCP-сервера связано с тем, какие флаги были получены им от клиента.
Обратите внимание, что в сообщение DHCPOFFER сервер еще не использует предлагаемый IP-адрес в поле Client IP Address, там еще находятся унылые нули. В поле Your IP Address сервер предлагает клиенту тот IP-адрес, который он у него запросил, естественно, перед тем как его предложить, сервер убедился в том, что этот адрес свободен. Как видим, сообщение DHCPOFFER по своему содержимому не сильно отличается от DHCPDISCOVER, теперь давайте посмотрим на опции, которые сервер предложил клиенту.

9.3.6 DHCP опции в сообщение DHCPOFFER

Во-первых, опции в сообщение DHCPOFFER, как и в любых других сообщениях, начинаются с Magic Cookie, а заканчиваются 255 опцией. Во-вторых, сервер не знал всех опций, которые у него попросил клиент, поэтому выдал то, что смог. После Magic Cookie сервер сообщает, что этот пакет несете в себе сообщение DHCPOFFER. Следующим шагом он сообщает клиенту свой идентификатор. А вот опция с кодом 51 несет в себе очень важную информацию о времени аренды IP-адреса, об этом времени у нас будет отдельный разговор.

Еще из полезного сервер предложил в качестве опций клиенту IP-адрес шлюза по умолчанию, маску подсети и адрес DNS-сервера.

9.3.5 Сообщение DHCPREQUEST или как клиент делает запрос на получение IP-адреса?

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

ПРИМЕЧАНИЕ: здесь мы пропускаем все проверки на занятость/свободность IP-адреса, это мы обсудили при прошлом разговоре и сейчас считаем, что они есть и в результате этих проверок IP-адрес свободен.

Давайте посмотрим, как выглядит сообщение DHCPREQUEST в дампе Wireshark.

9.3.7 Сообщение DHCPREQUEST или как клиент делает запрос на получение IP-адреса

Сразу бросается в глаза то, что DHCPREQUEST отправляется не адресно, а широковещательно, тут дело в том, что клиент должен сообщить всем серверам о том, какой адрес он хочет получить и с каким сервером он хочет продолжать взаимодействие. Все поля сверху, за исключением поля Message Type, имеют точно такие же значения, как и в сообщение DHCPDISCOVER, а вот поля опций изменились, давайте на них и посмотрим.

Работа с WDDX в РНР

Привет всем моим читателям!

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

Но что это такое,- спросите вы.

WDDX был разработан совместными усилиями разработчиков компании Alliery в 1998 году. И призвана она в сей мир для того лишь, чтобы унифицировать информацию, и перевести её в один, доступный всем платформам формат- XML. И сказать честно у них это получилось. Впервые технологию WDDX разработчики Alliery внедрили в свою же платформу, а именно ColdFusion. С течением времени данный формат данных набрал популярности среди разработчиков современного веба (хотя не так сильно, как хотелось бы). Данная технология была внедрена в большинство языков для веб-программирования. Так модули для поддержки WDDX доступны для Perl, PHP, Python, ColdFusion и многих других.Сегодня мы поговорим об очень важной технологии не только для мира Веб, но и для программирования в целом. А поговорим мы сегодня про универсальность данных и межплатформенный обмен информации. Как вы уже, наверное, поняли, для этого мы будем использовать технологии WDDX.

Ну, поскольку данная статья посвящена именно WDDX для платформы РНР, то о РНР сейчас и пойдёт речь.

В РНР данная технология интегрирована по умолчанию, и доступна во всех версиях начиная с 3.x.

По большому счёту технология WDDX не такая уж и масштабная, и заключается в нескольких банальных этапах обработки данных.

* Данные
* Сериализация и трансформация в WDDX код
* Сериализирование данные
* Десериализация и трансформация в ассоциативный массив
* Данные

Как видите, с данных всё началось, и данными всё окончилось. Теперь давайте поговорим подробнее о каждом из этапов.

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

В данный момент WDDX поддерживает большинство из доступных на разных платформах типов данных (числа, строки, структуры, массивы).

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

Что ж давайте по порядку. Сначала мы объявляем разного рода переменные, для того чтобы сериализировать их в WDDX формат. После этого мы создаём «стартовый» пакет WDDX.

Кстати, вы можете оставить некоторый произвольный комментарий в качестве параметра функции wddx_packet_start(). Данный текст будет добавлен в специальный XML-тег с индификатором .

В целом он не носит никакой практической пользы, кроме того, что поясняет предназначение данных в данном WDDX пакете.

После того как мы создали пакет, у нас есть возможность добавлять в него новые данные. Для этого мы вызываем функцию wddx_add_vars. Которая первым аргументом принимает идентификатор пакета, а после n-е количество аргументов строкового типа, которые будут носить название переменных в среде РНР. Эта же функция производит процесс сериализации данных.

Теперь мы просто вызываем функцию wddx_packet_end, которой передаём ресурс пакета, и возвращённый результат присваиваем переменной $serialized_data. Теперь у нас есть готовый WDDX код, который можно отображать.

Для его отображения мы применяем к нему функцию htmlspecialchars, так как браузер не будет корректно отображать «теговые» данные.

Вот, как видите ничего архисложно (как бы сказал дедушка Ленин) в этом нет.

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

А очень просто, для этого есть процедура десериализации. Десериализация это как раз процесс обратный сериализации, а именно перевод данных на ту или иную платформу, в виде ассоциативного массива, где индексом будет название переменной, а значением её содержимое. Для десериализации в РНР служит функция wddx_deserialize или её прототип wddx_unserialize, дело в том, что функция wddx_unserialize доступна лишь в поздних версиях языка РНР, и потому мы в данной статье будем использовать функцию wddx_deserialize.

Что ж, давайте и это протестируем, для наглядности:

Вот, как видите, всё успешно работает.

Сначала мы удаляем переменные (не забудьте — это не обязательно), а после вызываем функцию wddx_deserialize и передаём ей сериализированые данные в качестве аргумента, и результат её выполнения присваиваем переменной $deserialized_data. Но нам ведь не нужен массив, и поэтому нам нужно перевести его в формат обычных переменных. Для этого мы делаем простейший перебор и вспоминая тонкости РНР присваиваем переменно, именем которой будет значение переменной $k, значение переменной $v, так мы полностью восстанавливаем все переменные.

Как видите, процесс работы с технологией WDDX довольно прост, однако для полного усвоения материала, мы создадим небольшой проект, в соответствии, с которым мы сначала сформируем WDDX-совместимые данные в среде ColdFusion с данные, скажем, биржи акций, далее нашей задачей будет перевести данные в среду РНР, для дальнейшей их обработки.

Packet crafting как он есть

Создание пакетов или packet crafting — это техника, которая позволяет сетевым инженерам или пентестерам исследовать сети, проверять правила фаерволлов и находить уязвимые места.
Делается это обычно вручную, отправляя пакеты на различные устройства в сети.
В качестве цели может быть брандмауэр, системы обнаружения вторжений (IDS), маршрутизаторы и любые другие участники сети.
Создание пакетов вручную не означает, что нужно писать код на каком-либо высокоуровневом языке программирования, можно воспользоваться готовым инструментом, например, Scapy.

Scapy — это один из лучших, если не самый лучший, инструмент для создания пакетов вручную.
Утилита написана с использованием языка Python, автором является Philippe Biondi.
Возможности утилиты практически безграничны — это и сборка пакетов с последующей отправкой их в сеть, и захват пакетов, и чтение их из сохраненного ранее дампа, и исследование сети, и многое другое.
Всё это можно делать как в интерактивном режиме, так и создавая скрипты.
С помощью Scapy можно проводить сканирование, трассировку, исследования, атаки и обнаружение хостов в сети.
Scapy предоставляет среду или даже фреймворк, чем-то похожий на Wireshark, только без красивой графической оболочки.
Утилита разрабатывается под UNIX-подобные операционные системы, но тем не менее, некоторым удается запустить ее и в среде Windows.
Эта утилита так же может взаимодействовать и с другими программами: для наглядного декодирования пакетов можно подключать тот же Wireshark, для рисования графиков — GnuPlot и Vpython.
Для работы потребуется права суперпользователя (root, UID 0), так как это достаточно низкоуровневая утилита и работает напрямую с сетевой картой.
И что важно, для работы с этой утилитой не потребуются глубокие знания программирования на Python.

Приступаем

Официальный сайт проекта — www.secdev.org/projects/scapy
Установку можно провести разными способами, например apt-get install python-scapy, в случае дистрибутивов на основе Debian.
Так же можно просто скачать свежую версию с сайта разработчиков:
# cd /tmp
# wget scapy.net
# unzip scapy-latest.zip
# cd scapy-2.*
# sudo python setup.py install
После этого запуск происходит непосредственно командой scapy.
На экране отобразится примерно так:

Мы видим стандартное приглашение для ввода, все действия будут выполняться в интерактивном режиме.
Выход происходит комбинацией Ctrl+D, либо набрав функцию exit().

Изучаем инструмент

На самом деле Scapy сильно отличается от привычных утилит. Он работает в текстовом режиме, но любое взаимодействие осуществляется не через привычные ключи и параметры командной строки, а через интерпретатор Python’а.
Такой подход вначале может показаться несколько неудобным и непривычным, но со временем и с практикой приходит понимание того, что это было правильным решением, и что это действительно удобно.

Вначале посмотрим на поддерживаемые протоколы, для этого вызовем функцию ls().

Вывалится более 300 разнообразных протоколов, с которыми можно работать, включая прикладные вроде HTTP, транспортные TCP и UDP, сетевого уровня IPv4 и IPv6 и канального уровня Ether (Ethernet).
Важно обращать внимание на регистр: большинство протоколов пишутся в Scapy с заглавными буквами.
Для того чтобы подробно рассмотреть поля определенного протокола, можно вызвать функцую ls() с указанием протокола: ls(TCP)

В результате будут выведены все поля, которые можно модифицировать в процессе создания пакетов. В скобках показаны значения, которые используются по умолчанию, можно заметить, что порт отправителя 20 (это ftp-data) и порт получателя – 80 (это естественно HTTP), так же установлен флаг SYN (flags = 2).

К примеру, если рассмотреть канальный уровень (Ethernet), то тут возможностей будет поменьше:

В дополнение к функции ls(), есть полезная функция lsc(), которая выведет практически весь основной функционал Scapy:

Для того чтобы получить более подробную информацию о каждой функции, можно использовать help(имя_функции), например:

Видим нечто похожее на MAN страницу в Unix системах.
Для выхода можно использовать опять же привычную в Linux клавишу Q.

Мы посмотрели на протоколы и функции, теперь можно перейти к делу — к созданию пакетов.

Крафтим

Можно создавать сразу пакеты высоких уровней (сетевого и прикладного), и Scapy автоматически дополнит низлежащие уровни, а можно вручную собирать, начиная с канального уровня.
Разделяются уровни модели OSI символом прямого слэша (/).
Нужно обратить внимание на то, что Scapy читает пакет от нижнего уровня слева, до более высокого справа. Поначалу это может немного сбивать с толку, но после небольшой практики всё станет вполне привычно.
К слову, в терминологии Scapy сетевой пакет разделяется на слои, и каждый слой представляется как экземпляр объекта.
Собранный пакет в упрощенном виде может выглядеть как:
Ether()/IP()/TCP()/”App Data”
В большинстве случаев используется только уровень L3, предоставляя Scapy возможность самостоятельно заполнять канальный уровень, на основе информации из ОС.
Меняя значения полей каждого протокола мы меняем стандартные значения (их выводит функция ls()).

Теперь создадим какой-нибудь простой пакет.

Всё очень просто: мы указали адрес назначения, порт и вобщем-то нагрузку в виде слова «TEST».
Сам пакет был незамысловато назван packet, мы увидим очень подробно и развернуто наш свежесозданный пакет:
И теперь, выполнив знакомую уже функцию ls(packet):

Уровни в нем разделяются символами «—«.

Вместо того, чтобы создавать пакет за один раз можно создавать его частями:

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

И теперь собираем всё в один пакет:

Видно, что результат получится аналогичный.

Углубляемся в пакеты

Мы уже смотрели на вывод функции ls(), но не всегда нужна такая подробная информация о пакете.
Достаточно просто набрать имя переменной и сразу увидеть краткую сводку:

Так же можно использовать метод summary():

Если же нужно чуть больше информации, то есть метод show():

Кроме того, можно просмотреть любое поле, просто указав его:

Разумеется, это работает только в том случае, если такие поля уникальны в пределах пакета.
Если, например, взять поле flags, которое присутствует как в TCP, так и в IP, тут уже нужно конкретизировать, что мы хотим увидеть. В противном случае Scapy выведет значение первого найденного поля (IP flags в нашем примере).
Конкретизация происходит путем указания протокола в квадратных скобках:

К слову, по умолчанию установленные флаги выводятся в цифровом представлении.
Если все управляющие биты будут включены (установлены в 1), то получим значение равное 255. В нашем случае значение 2 говорит о том, что установлен SYN бит.

Но существует возможность отобразить управляющие биты и в символьном отображении:

Как уже говорилось, в любой момент можно достаточно просто поменять значение любого поля:

А в случае, если поле не является уникальным, то нужно указать протокол:

Вторым способом является использование конструкции payload, которая позволяет перепрыгнуть через один уровень (через L3 в нашем случае):

Здесь мы вначале просматриваем вывод слоев над L3, затем просматриваем значение TCP флагов и устанавливаем для них новое значение.
Кстати, можно даже несколько раз вызвать payload, поднимаясь при этом выше и выше:

Можно еще посмотреть на содержимое пакета в шестнадцатеричном виде, для этого есть функция hexdump():

Разбираемся с адресацией

Scapy и в деле указания адреса получателя так же проявляет большую гибкость.
Масса вариантов — здесь и привычная десятичная форма, и доменное имя и CIDR нотация:

В последнем случае пакет будет отправлен на каждый адрес в подсети.

Множество адресов можно задать, просто разделяя их запятой, не забыв про квадратные скобки:

На этом этапе может возникнуть мысль: «А что если нужно задать множество портов?».
И тут Scapy предоставляет широкие возможности, можно указать как диапазон, так и просто перечислить множество:

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

Илон Маск рекомендует:  Что такое код msql_connect

Вначале мы уже привычно создаем пакет, в котором указываем подсеть и диапазон портов.
Затем, используя цикл, создаем список, где переменной «а» присваивается каждый элемент структуры пакета. В Python’е отсутствуют массивы в привычном понимании. Вместо них для хранения объектов используются списки.
Мы используем цикл for, для того чтобы «распаковать» всю структуру и отобразить ее в таком наглядном виде.

Отправляем пакеты в путь

С таким же размахом и широтой происходит и отправка пакетов:

  • функция send() – отправляет пакеты, используя сетевой (L3) уровень, никак не обрабатывая ответы. Используется принцип — отправили и забыли;
  • функция sendp() – отправляет пакеты, используя канальный (L2) уровень, учитываются указанные параметры и заголовки Ethernet кадров. Ответы всё так же не ожидаются и не обрабатываются;
  • функция sr() – является аналогичной send(), исключение составляет то, что она уже ожидает ответные пакеты;
  • функция srp() – отправляет и принимает пакеты, уровень L2
  • функция sr1() – отправляет пакет третьего уровня и забирает только первый ответ, множество ответов не предусматривается;
  • функция srp1() – аналогично sr1(), только уже канальный уровень.

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

Но вместе с тем существует много дополнительных опций, которые могут быть иногда полезны.
Например, timeout – укажет, сколько времени (в секундах) нужно ждать до получения ответного пакета, retry – сколько раз нужно повторно слать пакет, если ответ не был получен и одна из самых полезных опций – это filter, синтаксис которого очень похож на tcpdump.

В качестве наглядного примера отправим пакет в сеть:

Здесь мы используем функцию, которая после отправки ожидает ответ, устанавливаем таймаут 0.1 секунды и фильтруем ответы, которые подпадают под указанное правило.

Как поступать с ответными пакетами?
Можно взять и назначить переменную, которая и будет содержать ответ:

А смотреть уже привычным способом, просто вызывая переменную response.
Видно, что ответ сохранился в двух вариантах – Results и Unanswered, результаты и без ответа, соответственно.
Указывая смещение, можно вывести только необходимую часть ответа:

Или подробную информацию:

Если же пакет был отправлен в сеть без указания переменной (например, просто функцией sr()), то по умолчанию пакет будет числиться за переменной «_» (символ подчеркивания).

Чтобы достать оттуда эти пакеты, можно использовать конструкцию:

При этом разные результаты сохранятся в двух разных переменных (res и unans).

Более подробный вывод достигается опять же путем указания смещения:

Ловим ответные пакеты

Теперь рассмотрим ситуацию, если пакетов в ответ приходит много.

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

Открытые порты будут с флагами SA (SYN/ACK), например:

Мы смотрим именно на пакет по номеру, счет традиционно начинается нуля.

Можно пойти дальше и распаковать этот результат:

Здесь мы извлекли из результата отправленный пакет (под номером 21) и ответ на него.
Но это только один пакет, а как быть, если нужно обработать все пакеты?
В таком случае придется вновь обращаться к циклу for:

Берем и разбиваем каждый элемент списка res на части a и b. Затем обрезаем часть “a”, заливая это всё в список “allsent”.
Аналогично создаем список allrec, только уже оставляем другую часть.
Всё это, конечно, хорошо, но хотелось бы в более удобном виде получить список открытых и закрытых портов.
Еще раз посмотрим на список res, a точнее на элемент res[0], который состоит из двух частей: пакет, который мы отправили res[0][0], и ответ, который получили res[0][1].

В ответе можно обнаружить три части — заголовок IP (res[0][1][0]), заголовок TCP (res[0][1][1]) и собственно сами данные (res[0][1][2]).

Используем цикл for для извлечения каждого элемента res[N] в переменную «а».

Теперь в переменной «a»содержится результат для каждого пакета. Другими словами «а» представляет собой ans[N].
Нам остается только проверить значения a[1][1], которые будут означать res[N][1][1] в заголовке TCP.
Если быть еще более точным, требуется значение 18, которое означает установленные флаги SYN-ACK.

В тех случаях, когда это условие сработает, мы еще выведем порт отправителя из заголовка TCP:

В итоге, получим результат в виде списка открытых портов.
Все вышеозначенные конструкции набираются за один раз, важно так же уделять внимание отступам (обычно это 4 пробела).

Мы только что вручную написали простой сканер портов, не больше и не меньше.

Сниффер и наоборот

В Scapy входит также и небольшой сниффер, за который отвечает функция sniff().
Естественно, с ним можно использовать фильтры (похожие на фильтры tcpdump), за это отвечает параметр filter, так же можно ограничивать количество пакетов с помощью параметра count.
Как всегда вызов help(sniff) выведет вполне подробную информацию по этой функции.
Не следует забывать, что это сильно упрощенный сниффер, и ожидать от него хорошей скорости особо не приходится.
Стандартная комбинация Ctrl+C прервет процесс захвата трафика и выведет результат.
Как и любая неопределенная переменная, результат попадет в «_».
Выполнив метод summary(), можно увидеть статистику по захваченным пакетам:

Вместо захвата трафика из сети, можно прочитать его из заранее сохраненного дампа (pcap файла).

Кроме того, можно и наоборот, записать пойманные пакеты в файл, используя функцию wrpcap():

И завершая тему сниффинга, можно вызвать Wireshark прямо из интерфейса Scapy, для этого можно использовать одноименную функцию wireshark().

Подробно про Wireshark можно в моей предыдущей статье по адресу http://linkmeup.ru/blog/115.html.

Автоматизация

Казалось бы, что уже всё готово, но не тут то было.
При очередной попытке подгрузить ospf модуль:
>>> load_contrib(‘ospf’), получаем всё ту же ошибу «ERROR: No module named contrib.ospf»
Для того, чтобы модуль окончательно заработал, осталось создать скрипт инициализации (пустой файл):
touch /usr/lib/python2.7/dist-packages/scapy/contrib/__init__.py
После этого, уже можно будет создавать пакеты для OSPF.

Создаем трехэтапное TCP-соединение

Для этого нужно будет поймать SYN/ACK ответ, извлечь из него TCP sequence number, увеличить значение на единицу и, собственно, и поместить полученное значение в поле acknowledgement number.
Непростая задача на первый взгляд, но Scapy может справиться и с ней.
Вначале рассмотрим, что нам нужно, для того чтобы всё прошло успешно.

1) Отправить SYN принимающей стороне:

  • собрать заголовок IP, не забыть про адрес отправителя и получателя;
  • собрать TCP заголовок, в котором нужно будет указать TCP порты отправителя и назначения, установить TCP флаги (SYN бит) и сгенерировать ISN (Initial Sequence Number).

2) Поймать ответный пакет:

  • сохранить ответ;
  • извлечь из него TCP sequence number и увеличить это значение на единицу.

3) Создать подтверждение (ACK) на полученный ответный пакет:

  • собрать заголовок IP, содержащий такие же адреса отправителя и получателя, как в случае SYN пакета;
  • собрать TCP заголовок, с такими же номерами портов, как и в SYN сегменте, но уже установить ACK флаг, увеличить значение ISN на единицу и установить acknowledgement в извлеченный и увеличенный, на втором шаге, sequence number.

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

192.168.10.200 1024 > 192.168.10.50 80 flags=SYN seq=12345
192.168.10.50 80 > 192.168.10.200 1024 flags=SYN, ACK seq=9998 ack=12346
192.168.10.200 1024 > 192.168.10.50 80 flags=ACK seq=12346 ack=9999

Что в итоге нужно было сделать.

1) Отправить SYN принимающей стороне:

  • собрать заголовок IP, в котором указать в качестве отправителя 192.168.10.200 и 192.168.10.50 в качестве получателя;
  • собрать TCP заголовок с портом источника (source) 1024 и портом назначения (destination) 80. Так же установить SYN флаг и сгенерировать ISN равный 12345.

2) Поймать ответный пакет:

  • сохранить ответ;
  • извлечь из него TCP sequence number (9998) и увеличить это значение на единицу, получим 9999.

3) Создать подтверждение (ACK) на полученный ответный пакет:

  • собрать заголовок IP, в котором указать в качестве отправителя 192.168.10.200 и 192.168.10.50 в качестве получателя;
  • собрать TCP заголовок с такими же портами источника и назначения (1024 и 80 соответственно), установить ACK флаг, увеличить ISN на единицу (12346) и установить acknowledgement в увеличенное значение пойманного seq number (9999).

Начнем собирать пакет:

Здесь уже всё должно быть знакомым: пакет собираем из двух частей, инкапсулируя TCP в IP.

Теперь помня о том, что нам нужно будет перехватить ответ, извлечь оттуда sequence number и увеличить на единицу, делаем:

Происходит следующее – функция sr1 отправляет ранее созданный пакет в сеть, а первый пришедший ответ помещается в переменную SYNACK.
А затем, используя конструкцию SYNACK.seq, извлекаем TCP sequence number, увеличиваем его на единицу и сохраняем в переменной my_ack.

Создаем новый заголовок TCP и называем его ACK. В нем устанавливается другой флаг (A — ACK) и увеличивается значение sequence number.
Кроме того, в качестве acknowledgement указывается переменная my_ack.
Затем собранный пакет выбрасывается в сеть командой send (помним, что это L3 команда, которая даже не слушает, что придет в ответ).
Если всё было сделано правильно, то классическое TCP-соединение состоялось.
Осталось только создать TCP сегмент без каких-либо флагов и тоже отправить в сеть.

Как можно увидеть, мы в очередной раз создали экземпляр TCP заголовка (в этот раз, назвав его PUSH), без флагов и со всеми остальными знакомыми уже значениями.
После этого добавили немного данных, используя переменную data, и отправили в сеть, используя ту же функцию send.
И соответственно от получателя должен будет прийти acknowledgement на этот сегмент.

>>> ip=IP(src=«192.168.10.200»,dst=«192.168.10.50»)
>>> SYN=TCP(sport=1024,dport=80,flags=«S»,seq=12345)
>>> packet=ip/SYN
>>> SYNACK=sr1(packet)
>>> my_ack=SYNACK.seq+1
>>> ACK=TCP(sport=1024,dport=80,flags=«A»,seq=12346,ack=my+ack)
>>>send(ip/ACK)

Но здесь есть и несколько подводных камней.
Если посмотреть на этот обмен в Wireshark, можно увидеть, что до того как ушел наш ACK пакет, внезапно был отправлен RST:

Дело в том, что Scapy работает мимо TCP/IP стека ОС. Это означает то, что ОС не подозревает о том, что Scapy отправляет какие-то пакеты.
Соответственно ОС не будет ожидать появления SYN/ACK пакетов. И, следовательно, соединение будет сразу же сброшено.
Очевидно, что это совсем не тот результат, который нам нужен.
Одним из решений такой проблемы будет использование функционала пакетного фильтра, в частности iptables, который сможет блокировать исходящие RST пакеты.
Например, таким образом:
# iptables -A OUTPUT -p tcp -d 192.168.10.50 -s 192.168.10.200 —dport 80 —tcp-flags RST RST -j DROP
Выполнение такой конструкции приведет к тому, что все исходящие пакеты с адресом назначения 192.168.10.50 и с адресом отправителя 192.168.10.200 на 80-й порт, с установленным RST флагом, будут отбрасываться.
Пакеты будут все так же генерироваться силами ОС, но они просто не будут вылетать за ее пределы.
В итоге уже ничего не будет мешать Scapy делать полноценную TCP-сессию:

Продолжаем исследования

Используя Scapy, можно находить хосты в сети, среди указанного множества адресов:

В этом случае мы используем протокол ICMP и применяем знакомый прием по разделению полученных ответов.

По умолчанию, установлен 8-й тип для ICMP, это и есть классический эхо-запрос.

Углубляясь в тему ИБ, попробуем определить версию ОС используя Scapy и nmap.

Итак, рассмотрим что было сделано.
Вначале был подключен внешний модуль, в данном случае nmap.
Затем проверяем, что у нас есть файл (nmap-os-fingerprints) с отпечатками различных ОС.
И запускаем непосредственно определение удаленной операционной системы, за это отвечает функция nmap_fp, где в качестве параметров помимо самой цели, можно еще указать открытый (oport) и закрытый (cport) порты.
Правильно указанные порты помогут сильно улучшить точность определения ОС.

Визуализируем пакеты

Все время мы смотрели на текстовый вывод, местами была псевдографика, но Scapy умеет и выводить некоторые результаты в графическом виде.
Посмотрим, что нам предлагается.
Самое простое — это метод conversations():

При его выполнении, запустится окно ImageMagick, в котором отрисуется схема нашего обмена пакетами, не ахти красиво, но достаточно наглядно.
Это способ, вероятно, лучше всего подойдет, для визуализации дампов с трафиком.

Второй способ заключается в построении 2D графиков, с последующим экспортом их в pdf-файл.

За это уже отвечает функция pdfdump().
Результаты выглядят примерно так:

В данном случае уже вполне неплохо.
Кроме того, функция graph() опять откроет окно ImageMagick, но уже с детальной прорисовкой:

Здесь мы видим результат трассировки, с подробным отображением автономных систем и прочей визуализацией.

И, завершая тему визуализации, а вместе с ней и статью, посмотрим на 3D отображения трассы.
Для этого потребуется VPython и команда trace3D().

Здесь отображена трасса из предыдущего графика.

Но иногда бывают и такие варианты:

В этом примере была проведена трассировка сразу нескольких целей, с использованием нескольких (80, 443) tcp портов.
Левый клик на любом объекте приведет к появлению IP-адреса над ним, а левый клик с зажатой клавишей CTRL – к отображению более подробной информации — портам, как в этом случае.

Эпилог

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

В процессе написания статьи использовались материалы Института SANS и официальная документация проекта.

Что такое Sequence и Acknowledgment Number в TCP-заголовке?

Sequence Number — порядковый номер: 32 бита
Порядковый номер первого октета данных в сегменте при отсутствии флага SYN. Если в сегменте присутствует бит SYN, поле номера содержит значение начального порядкового номера (ISN), а первый октет данных имеет номер ISN+1.
Acknowledgment Number — номер подтверждения: 32 бита
Если бит ACK установлен, это поле содержит значение следующего порядкового номера, который отправитель сегмента ожидает получить. После организации соединения это значение передается всегда.

  • Вопрос задан более трёх лет назад
  • 10442 просмотра

В случае SYN каким образом заполняется первый октет? Как понимать «первый октет данных имеет номер ISN+1». Просто записывается ISN+1, а дальше все остальное?

Нет. В поле Sequence Number записывается номер, соответствующий первому октету TCP-сегмента. Для самого первого октета данных это будет ISN+1.

В случае SYN-ACK, что имеется в виду под значением следующего порядкового номера, который отправитель сегмента ожидает получить? Как его рассчитать?

Функции WDDX

Эти функции предназначены для работы с WDDX.

Чтобы использовать WDDX, вам необходимо установить библиотеку expat (которая поставляется с Аpache 1.3.7 или новее) и рекомпилировать PHP с опциями —with-xml и —enable-wddx.

Примечание: Если вы хотите сериализовать не-ASCII символы, вы должны предварительно установить соответствующую локализацию (см. setlocale()).

Все функции, сериализующие переменные, используют первый элемент массива для определения того, сериализован ли массив в массив или в структуру. Если первый элемент имеет строковой ключ, то он сериализуется в структуру, иначе — в массив.
Пример 1. Сериализация отдельного значения

На выходе этот пример даст:
PHP to WDDX packet example

Пример 2. Использование инкремекнтных пакетов

= 3.1415926 ;
$packet_id = wddx_packet_start ( «PHP» );
wddx_add_vars ( $packet_id , «pi» );

/* Предположим, $cities пришла из БД */
$cities = array( «Austin» , «Novato» , «Seattle» );
wddx_add_vars ( $packet_id , «cities» );

$packet = wddx_packet_end ( $packet_id );
print $packet ;
?>

wddx_add_vars — добавляет переменные в пакет WDDX со специфицированным ID
wddx_deserialize — десериализует WDDX-пакет
wddx_packet_end — заканчиает WDDX-пакет со специфицированным ID
wddx_packet_start — стартует новый WDDX-пакет со структурой в нём
wddx_serialize_value — сериализует отдельное значение в WDDX-пакет
wddx_serialize_vars — сериализует переменную в WDDX-пакет

Что такое код wddx_packet_end

(PHP 3>= 3.0.7, PHP 4)

wddx_packet_end — заканчивает WDDX-пакет со специфицированным ID.

Описание

string wddx_packet_end (int packet_id)

wddx_packet_end() заканчивает WDDX-пакет packet_id и возвращает string с пакетом.


Назад Оглавление Вперёд
wddx_deserialize Вверх wddx_packet_start

© 2006-2012 Веб-мастер Борисов Виктор Александрович

need to create wddx packet with complex structure in PHP

I’m trying to get this structure in PHP.

My code in PHP is

I can generate the simple structure, but I cannot generate the containers with structure inside. I’ve tried to generate a packet, and passing the value of the packet to other packet. No results.

2 Answers 2

you can check the following piece of code for your reference:

Create your containers as associative arrays, like so:

Not the answer you’re looking for? Browse other questions tagged php wddx or ask your own question.

Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

site design / logo © 2020 Stack Exchange Inc; user contributions licensed under cc by-sa 4.0 with attribution required. rev 2020.11.12.35412

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL