18.2 Использование библиотеки NPCAP для захвата пакетов
18.2 Использование библиотеки NPCAP для захвата пакетов

NPCAP библиотека - этосуществоватьWindowsБиблиотека для захвата и анализа сетевых пакетов на платформе.。этоWinPcapфилиал библиотеки,Зависит отNmapРазвитие команды разработчиков,И вNmapиспользуется в программном обеспечении。иWinPcapТакой же,NPCAPБиблиотека предоставляет некоторыеAPI,Позволяет разработчикам легко захватывать и обрабатывать сетевые пакеты в своих приложениях.。NPCAPДоступ к библиотеке можно получить черезWinPcap APIПрограммирование,Таким образом, существующие приложения WinPcap можно легко перенести в библиотеку NPCAP.

По сравнению с WinPcap,Библиотека NPCAP имеет лучшую производительность и надежность.,Поддерживает новейшие операционные системы и оборудование.。Он также обеспечивает802.11Встроенная поддержка беспроводных сетей,и может пройтиWiresharkПодождите, пока будут использованы инструменты сетевого анализа.。 NPCAPБиблиотека находится вMITОпубликовано по лицензии,Поэтому его можно использовать как в бесплатном, так и в коммерческом программном обеспечении.

Набор инструментов разделен на две части: драйвер и набор инструментов SDK.,При использовании этой библиотеки для перехвата пакетов читателям необходимо самостоятельно установить соответствующую версию драйвера.,Версия, используемая здесь читателями:npcap-1.55.exeПосле загрузки читатели могут нажать «Далее».,Когда установка будет завершена, вы увидите сообщение с подсказкой, как показано ниже;

Когда установка драйвера будет завершена,Читатели могут самостоятельно настроить инструментарий разработки в проекте.,Обычно достаточно удалитьincludeиlibБиблиотеку можно настроить в проект,После настройки, как показано на рисунке ниже, вы можете применить и сохранить ее самостоятельно.

Затем давайте реализуем первую функцию,Перечислить информацию о сетевой карте, которую можно использовать на текущем хосте.,Реализация этой функции во многом зависит отpcap_findalldevs_ex()функция,Эта функция используется для получения списка всех сетевых адаптеров, доступных в текущей системе.

Объявление прототипа функции выглядит следующим образом:

Язык кода:c
копировать
int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth,
                        pcap_if_t **alldevsp, char *errbuf);

Среди них значения параметров следующие:

  • источник: укажите IP-адрес удаленного интерфейса или передайте NULL для локального интерфейса.
  • auth:точкаpcap_rmtauthСтруктура приходит Укажите удаленный IP и имя пользователя.
  • alldevsp: указатель, возвращающий список устройств, доступных на хосте.
  • errbuf: Буфер, используемый для хранения информации об ошибках.

Эта функция позволяет разработчикам получать сведения обо всех сетевых адаптерах через структуру. Позволяет указать фильтр,для соответствия определенным пользователем сетевым адаптерам и свойствам. также,pcap_findalldevs_ex()Также предоставляет структуру для хранения информации об ошибках.,Чтобы предоставить информацию об ошибке в случае сбоя вызова функции.

В противном случае функция возвращает -1, чтобы указать на ошибку;,Возвращаемое значение 0 указывает, что операция прошла успешно.,и вернет все доступные сетевые адаптеры и их данные. Эти сведения включают имя адаптера, описание, MAC-адрес, IP-адрес, маску подсети и т. д.,как читательиспользоватьперечислятьфункция После окончаниянуждатьсясамоходныйвызовpcap_freealldevsфункция Освободите этот указатель, чтобы избежать утечек памяти.。

Ниже приведено объявление прототипа функции pcap_freealldevs:

Язык кода:c
копировать
void pcap_freealldevs(pcap_if_t *alldevs);

в,alldevsПараметр указывает наpcap_if_tУказатель на структуру типа,В структуру этого типа записывается подробная информация обо всех сетевых интерфейсах, доступных на текущем хосте.。pcap_freealldevs() выпустит входящиеpcap_if_tвведите связанный список,И поставьте все элементы удалить.

вызовpcap_freealldevs()функциячаснуждатьсяпрошло, прежде чем войтиpcap_findalldevs()илиpcap_findalldevs_ex()функцияполученныйориентированныйсвязанный списокструктурауказатель какпараметр。

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

Язык кода:c
копировать
#include <iostream>
#include <winsock2.h>
#include <Windows.h>
#include <string>
#include <pcap.h>

#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib, "packet.lib")
#pragma comment(lib, "wpcap.lib")

using namespace std;

// Выходные строки
void PrintLine(int x)
{
  for (size_t i = 0; i < x; i++)
  {
    printf("-");
  }
  printf("\n");
}

// Перечислить текущие сетевые карты
int enumAdapters()
{
  pcap_if_t *allAdapters;    // Сохраните все устройства сетевых карт.
  pcap_if_t *ptr;            // указатель для обхода
  int index = 0;
  char errbuf[PCAP_ERRBUF_SIZE];

  /* Получить список локальных машин и устройств */
  if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &allAdapters, errbuf) != -1)
  {
    PrintLine(100);
    printf("индекс \t Имя сетевой карты \n");
    PrintLine(100);

    /* Распечатать список информации о сетевой карте */
    for (ptr = allAdapters; ptr != NULL; ptr = ptr->next)
    {
      ++index;
      if (ptr->description)
      {
        printf("[ %d ] \t [ %s ] \n", index - 1, ptr->description);
      }
    }
  }

  /* Список устройств больше не нужен, освободите его */
  pcap_freealldevs(allAdapters);
  return index;
}
int main(int argc, char* argv[])
{
  enumAdapters();
  system("pause");
  return 0;
}

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

Как только номер сетевой карты станет доступен, считыватели смогут захватывать пакеты и анализировать конкретный номер.,Реализация функции захвата пакетов зависит отpcap_open()функция,Эта функция используется для открытия указанного сетевого адаптера и начала перехвата сетевых пакетов.,Объявление прототипа функции выглядит следующим образом:

Язык кода:c
копировать
pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, 
     struct pcap_rmtauth *auth, char *errbuf);

Смысл его параметров следующий:

  • source:Имя сетевого интерфейса, который нужно открытьилисохранятьсуществоватьpcap_open_live()Имя, полученное от。
  • snaplen: установите размер перехваченных пакетов.
  • флаги: установите режим перехвата пакетов.,существоватьpromiscuousрежим контроллераили НетpromiscuousСнимать в режиме。
  • read_timeout: установите тайм-аут функции блокирующего чтения в миллисекундах.
  • auth:точкаpcap_rmtauthструктура,Укажите удаленный IP и имя пользователя.
  • errbuf: Буфер, используемый для хранения информации об ошибках.

Долженфункциявозвращатьсяточкаpcap_tуказатель типа,Этот тип структуры обеспечивает интерфейс для связи с сетевым адаптером.,Может использоваться для захвата пакетов, отключения сетевых адаптеров и других операций.,читательсуществоватьвызовpcap_open()функциячас,Необходимо указать имя сетевого адаптера для открытияsource,Если вам нужно установить его в смешанный режим,Нужно установитьflagsПараметрыPCAP_OPENFLAG_PROMISCUOUS,такжеsnaplenПараметр, используемый для установки размера перехваченных пакетов.,read_timeoutпараметр Используется для установки блокировки чтения.функция的超часчас间,authПараметры используются для указания удаленногоIPи имя пользователя,errbufПараметры, используемые для хранения информации об ошибках。нравитьсяфрукты Долженфункциявозвращаться空,Это означает, что указанный сетевой адаптер не был успешно открыт.

другойнуждатьсяосторожныйфункциядаpcap_next_ex()Долженфункция Используется для чтения следующего сетевого пакета с указанного открытого сетевого адаптера.,Обычно этофункциянуждаться Сотрудничатьpcap_open()используются вместе,Его прототип заявляет:

Язык кода:c
копировать
int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data);

Значения параметров следующие:

  • p:ориентированныйpcap_tУказатель на структуру типа,Представляет открытый сетевой адаптер.
  • pkt_header:точкаориентированныйpcap_pkthdrуказатель типа,Этот тип структуры содержит метаданные о текущем пакете.,Например, временная метка, Длина. пакета、Интерфейс сетевого адаптера и т. д., где были перехвачены пакеты.
  • pkt_data: указатель на захваченный пакет.

Он возвращает одно из следующих трех возвращаемых значений:

  • 1: Пакет успешно захвачен.,pkt_headerиpkt_dataноориентированный Сопутствующая информация;
  • 0: в течение указанного времени пакеты не были перехвачены;
  • -1: произошла ошибка,Вызывает сбой при чтении пакетов от сетевого адаптера.。此час可以существоватьerrbufНайдите информацию об ошибке в параметрах。

использоватьpcap_next_ex()функциячас,нуждатьсяпоставлятьточкаpcap_tУказатель на структуру типаpИспользуется для определения того, с какого сетевого адаптера читать пакеты.。В случае успеха при чтении пакета,но Воля包的元数据存储существоватьпереходныйpcap_pkthdrв указателе,Воляориентированный Хранилище указателей для захваченных пакетовсуществоватьpkt_dataв указателе。нравитьсяфруктысуществовать指定的час间内未捕获到任何数据包,Функция возвращает 0. Если при чтении пакета возникает какая-либо ошибка,Функция возвращает -1,И вerrbufПодробности об ошибке указаны в параметрах.。

Когда читатели поймут функции двух вышеупомянутых ключевых функций, они смогут реализовать функцию динамического захвата пакетов.,следующеекодвMonitorAdapterфункциянода抓包的实现,Эта функция требует передачи двух параметров.,параметр1Это сетевая карта, которая должна перехватывать пакеты.серийный номер,Здесь мы используем цифру 7,Второй параметр указывает тип пакета данных, который необходимо декодировать.,Здесь мы можем пройтиetherи т. д. для распаковки,Конечно, в этой функции еще не реализована функция анализа пакетов данных.,Реализация этих функций нуждается в дальнейшем совершенствовании.

Язык кода:c
копировать
#include <iostream>
#include <winsock2.h>
#include <Windows.h>
#include <string>
#include <pcap.h>

#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib, "packet.lib")
#pragma comment(lib, "wpcap.lib")

using namespace std;

// Выберите сетевую карту и разберите пакеты по разным параметрам.
void MonitorAdapter(int nChoose, char *Type)
{
  pcap_if_t *adapters;
  char errbuf[PCAP_ERRBUF_SIZE];

  if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &adapters, errbuf) != -1)
  {
    // Найти указанную сетевую карту
    for (int x = 0; x < nChoose - 1; ++x)
      adapters = adapters->next;

    // PCAP_OPENFLAG_PROMISCUOUS = Сетевая карта переведена в беспорядочный режим
    // 1000 => 1000 миллисекунд. Если данные не могут быть прочитаны, тайм-аут будет возвращен напрямую.
    pcap_t * handle = pcap_open(adapters->name, 65534, 1, PCAP_OPENFLAG_PROMISCUOUS, 0, 0);

    if (adapters == NULL)
      return;

    // printf("Начните слушать: % \n", adapters->description);
    pcap_pkthdr *Packet_Header;    // заголовок пакета
    const u_char * Packet_Data;    // сами данные
    int retValue;
    while ((retValue = pcap_next_ex(handle, &Packet_Header, &Packet_Data)) >= 0)
    {
      if (retValue == 0)
        continue;

      // printf("Продолжительность прослушивания: %d \n", Packet_Header->len);
      if (strcmp(Type, "ether") == 0)
      {
        PrintEtherHeader(Packet_Data);
      }
      if (strcmp(Type, "ip") == 0)
      {
        PrintIPHeader(Packet_Data);
      }
      if (strcmp(Type, "tcp") == 0)
      {
        PrintTCPHeader(Packet_Data);
      }
      if (strcmp(Type, "udp") == 0)
      {
        PrintUDPHeader(Packet_Data);
      }
      if (strcmp(Type, "icmp") == 0)
      {
        PrintICMPHeader(Packet_Data);
      }
      if (strcmp(Type, "http") == 0)
      {
        PrintHttpHeader(Packet_Data);
      }
      if (strcmp(Type, "arp") == 0)
      {
        PrintArpHeader(Packet_Data);
      }
    }
  }
}

int main(int argc, char* argv[])
{
  MonitorAdapter(7,"ether");
  system("pause");
  return 0;
}

Когда читатель имеет вышеизложенноекодрамка,Затем следующим шагом будет его последовательная реализация.PrintEtherHeader,PrintIPHeader,PrintTCPHeader,PrintUDPHeader,PrintICMPHeader,PrintHttpHeader,PrintArpHeaderждатьфункция,Этифункция Получить исходный пакетPacket_Dataтип,И конвертировать его в пакет данных соответствующего формата и выводить пользователю,Далее мы последовательно реализуем эти функции.

Декодирование пакетов уровня Ethernet

Пакеты Ethernet — это формат пакетов данных, отправляемых через Ethernet. Обычно он включает заголовок Ethernet и часть данных Ethernet. Вот введение в его различные части:

  • Заголовок Ethernet: включает MAC-адрес назначения, MAC-адрес источника и поля типа/длины. MAC-адрес назначения и MAC-адрес источника представляют собой 6-байтовые двоичные числа, которые представляют пункт назначения и источник пакета соответственно. Поле Тип/Длина используется для указания длины части данных или для указания используемого протокола сетевого уровня. Если поле «Тип/Длина» равно 1500 или меньше, оно указывает длину части данных, в противном случае оно указывает тип используемого протокола;
  • Раздел данных Ethernet: включает все заголовки и данные сетевых протоколов верхнего уровня. Длина части данных Ethernet обычно превышает 46 байт, а максимальная длина составляет 1500 байт.

Пакеты Ethernet обычно используются для связи в локальных сетях. Отправляйте пакеты на все устройства в этой сети, используя кадры Ethernet в качестве формата пакета. Затем целевое устройство получает и обрабатывает эти кадры на основе целевого MAC-адреса, а другие устройства игнорируют эти кадры. В пакете Ethernet MAC-адрес назначения относится к уникальному MAC-адресу устройства, на которое пакет предназначен для отправки, а MAC-адрес источника относится к MAC-адресу устройства, отправляющего сообщение.

Язык кода:c
копировать
// Декодирование пакетов канала передачи данных Уровень канала передачи данных — это второй уровень, и во время декодирования необходимо инкапсулировать только один уровень заголовка Ethernet. пакета Вот и все.
#define hcons(A) (((WORD)(A)&0xFF00)>>8) | (((WORD)(A)&0x00FF)<<8)

void PrintEtherHeader(const u_char * packetData)
{
  typedef struct ether_header
  {
    u_char ether_dhost[6];    // адрес назначения
    u_char ether_shost[6];    // Исходный адрес
    u_short ether_type;       // Тип Ethernet
  } ether_header;

  struct ether_header * eth_protocol;
  eth_protocol = (struct ether_header *)packetData;

  u_short ether_type = ntohs(eth_protocol->ether_type);  // Тип Ethernet
  u_char *ether_src = eth_protocol->ether_shost;         // Необработанный MAC-адрес Ethernet
  u_char *ether_dst = eth_protocol->ether_dhost;         // MAC-адрес назначения Ethernet

  printf("Введите: 0x%x \t", ether_type);
  printf("Исходный MAC-адрес: %02X:%02X:%02X:%02X:%02X:%02X \t",
    ether_src[0], ether_src[1], ether_src[2], ether_src[3], ether_src[4], ether_src[5]);
  printf("MAC-адрес назначения: %02X:%02X:%02X:%02X:%02X:%02X \n",
    ether_dst[0], ether_dst[1], ether_dst[2], ether_dst[3], ether_dst[4], ether_dst[5]);
}

Поскольку Ethernet является слишком низкоуровневым, мы можем получить только некоторую базовую информацию о сетевой карте, анализируя Ethernet, как показано на рисунке ниже;

Декодирование пакетов IP-уровня

Пакеты данных IP (Интернет-протокол) представляют собой третий уровень стека протоколов TCP/IP (Протокол управления передачей/Интернет-протокол). Обычно он состоит из двух частей: IP-заголовка и части данных.

Заголовки IP обычно включают следующее:

  • Номер версии: указывает номер версии используемого IP-протокола.
  • Длина заголовка: указывает длину всего IP-заголовка. Длины в протоколе TCP/IP считаются в байтах.
  • Общая длина: указывает длину всего IP-пакета, включая заголовок и часть полезной нагрузки.
  • TTL: время жизни, используется для ограничения количества раз, когда маршрутизатор пересылает пакет.
  • Протокол: указывает тип протокола, используемый верхним уровнем.
  • IP-адрес источника: IP-адрес устройства, отправившего пакет.
  • IP-адрес назначения: IP-адрес устройства, которому был отправлен этот пакет.
  • Часть данных — это фактические данные, передаваемые в протоколе верхнего уровня.

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

При получении IP-пакета сетевое устройство сначала проверяет IP-адрес назначения в заголовке пакета, затем использует таблицу маршрутизации, чтобы найти следующий узел (следующий переход), необходимый для передачи пакета, и доставляет пакет этому узлу. Если маршрутизатор не может доставить пакет следующему узлу, пакет будет отброшен. Каждый узел проверяет значение TTL пакета и уменьшает его на единицу. Если значение TTL становится равным 0, пакет отбрасывается, чтобы предотвратить его зацикливание в сети.

Язык кода:c
копировать
// Декодирование IP-пакетов, уровень IP находится ниже уровня канала передачи данных, При декодировании требуется значение смещения +14. Пропустите уровень канала передачи данных.
void PrintIPHeader(const u_char * packetData)
{
  typedef struct ip_header
  {
    char version : 4;
    char headerlength : 4;
    char cTOS;
    unsigned short totla_length;
    unsigned short identification;
    unsigned short flags_offset;
    char time_to_live;
    char Protocol;
    unsigned short check_sum;
    unsigned int SrcAddr;
    unsigned int DstAddr;
  }ip_header;

  struct ip_header *ip_protocol;

  // +14 Пропустить уровень канала передачи данных
  ip_protocol = (struct ip_header *)(packetData + 14);
  SOCKADDR_IN Src_Addr, Dst_Addr = { 0 };

  u_short check_sum = ntohs(ip_protocol->check_sum);
  int ttl = ip_protocol->time_to_live;
  int proto = ip_protocol->Protocol;

  Src_Addr.sin_addr.s_addr = ip_protocol->SrcAddr;
  Dst_Addr.sin_addr.s_addr = ip_protocol->DstAddr;

  printf("Исходный адрес: %15s --> ", inet_ntoa(Src_Addr.sin_addr));
  printf("адрес назначения: %15s --> ", inet_ntoa(Dst_Addr.sin_addr));

  printf("Контрольная сумма: %5X --> TTL: %4d --> Тип соглашения: ", check_sum, ttl);
  switch (ip_protocol->Protocol)
  {
  case 1: printf("ICMP \n"); break;
  case 2: printf("IGMP \n"); break;
  case 6: printf("TCP \n");  break;
  case 17: printf("UDP \n"); break;
  case 89: printf("OSPF \n"); break;
  default: printf("None \n"); break;
  }
}

Анализ пакетов уровня IP может быть более сложным.,потому чтоIPВ верхней части соглашения может содержатьсяICMP,IGMP,TCP,UDP,OSPFОжидание соглашения,После запуска программы читатели увидят конкретную информацию, как показано на рисунке ниже;

Декодирование пакетов уровня TCP

Пакет уровня TCP (протокол управления передачей) — это четвертый уровень в стеке протоколов TCP/IP (протокол управления передачей/протокол Интернета). Он состоит из двух частей: TCP-заголовка и части данных.

Заголовки TCP обычно включают следующее:

  • Номер исходного порта: указывает номер порта приложения, отправившего пакет.
  • Номер порта назначения: указывает номер порта приложения, которое получает пакет данных.
  • Порядковый номер: используется для упорядочивания нескольких пакетов, чтобы гарантировать, что они доходят до принимающего приложения в правильном порядке.
  • Номер подтверждения: используется для подтверждения того, что получатель успешно получил порядковый номер или последний успешно полученный пакет данных.
  • Флаги ACK и SYN: это биты флагов в заголовке TCP, которые управляют установлением и закрытием TCP-соединений.
  • Размер окна: используется для управления скоростью отправки потоков данных и предотвращения отправки слишком большого количества пакетов данных, вызывающих перегрузку сети.
  • Контрольная сумма: используется для проверки того, были ли заголовок TCP и части данных повреждены или подделаны.
  • Часть данных — это данные приложения, передаваемые на уровень TCP прикладной программой верхнего уровня.

TCP — это протокол, ориентированный на соединение, поэтому перед отправкой данных TCP сначала устанавливает соединение между отправителем и получателем. Процесс установления соединения включает в себя трехэтапный процесс установления связи, при котором клиент инициирует запрос на соединение, сервер отправляет обратно подтверждение, а клиент отправляет подтверждение еще раз. После завершения соединения протокол TCP контролирует порядок передачи и достоверность пакетов данных (например, сообщений подтверждения и повторной передачи сообщений ACK) на основе номера подтверждения и порядкового номера для обеспечения эффективных услуг передачи данных.

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

Язык кода:c
копировать
//Декодируем TCP-пакеты,Нужно сначала добавить14Пропустить уровень канала передачи данных, Затем добавьте 20, чтобы пропустить уровень IP.
void PrintTCPHeader(const unsigned char * packetData)
{
  typedef struct tcp_header
  {
    short SourPort;                 // Номер исходного порта 16 бит
    short DestPort;                 // Номер порта назначения 16 бит.
    unsigned int SequNum;           // Серийный номер 32бит.
    unsigned int AcknowledgeNum;    // Номер подтверждения 32бит
    unsigned char reserved : 4, offset : 4; // зарезервированное смещение

    unsigned char  flags;               // логотип 

    short WindowSize;               // Размер окна 16бит.
    short CheckSum;                 // Контрольная сумма 16 бит
    short surgentPointer;           // Срочное смещение данных 16 бит
  }tcp_header;

  struct tcp_header *tcp_protocol;
  // +14 Пропустить уровень канала передачи данных +20 Пропустить уровень IP
  tcp_protocol = (struct tcp_header *)(packetData + 14 + 20);

  u_short sport = ntohs(tcp_protocol->SourPort);
  u_short dport = ntohs(tcp_protocol->DestPort);
  int window = tcp_protocol->WindowSize;
  int flags = tcp_protocol->flags;

  printf("Исходный порт: %6d --> Порт назначения: %6d --> Размер окна: %7d --> логотип: (%d)",
    sport, dport, window, flags);

  if (flags & 0x08) printf("PSH Передача данных\n");
  else if (flags & 0x10) printf("ACK Ответ\n");
  else if (flags & 0x02) printf("SYN Установить соединение\n");
  else if (flags & 0x20) printf("URG \n");
  else if (flags & 0x01) printf("FIN Закройте соединение\n");
  else if (flags & 0x04) printf("RST Сброс соединения\n");
  else printf("None Неизвестно\n");
}

Анализ TCP также более сложен.,Это связано с тем, что протокол TCP имеет несколько значений состояния.,нравитьсяPSH、ACK、SYN、URG、FINиRSTЭтоTCPИспользуется в сегменте сообщениялоготипдругая информацияилистатуслоготип Кусочек。ЭтиTCPлоготип Кусочекзначениеследующее:

  • PSH (Push): этот флаг указывает, что принимающее приложение должно немедленно прочитать данные из буфера приема. Обычно используется, когда отправителю необходимо как можно быстрее отправить все данные получателю.
  • ACK (Подтверждение): Этот флаг указывает на ответ. Используется для подтверждения того, что другие TCP-пакеты были успешно получены. После установки TCP-соединения во всех сегментах TCP должен быть установлен флаг ACK.
  • SYN (синхронный): этот флаг используется для установки TCP-соединения. Указывает на запрос на установление соединения, а порядковый номер начинается со случайного числа ISN. Конец, отправляющий сообщение SYN, перейдет в состояние SYN_SENT.
  • URG (Срочно): этот флаг указывает, что указатель срочности действителен. Он используется для информирования принимающей стороны о том, что в этом сегменте сообщения есть срочные данные, и экстренные данные должны быть немедленно доставлены на прикладной уровень принимающей стороны.
  • FIN (Готово): этот флаг используется для завершения TCP-соединения. Конец с установленным флагом FIN указывает на то, что все данные отправлены и требуется разорвать соединение.
  • RST (Сброс): этот флаг используется для сброса TCP-соединения. Когда попытка TCP-соединения не удалась или закрытый сокет получает данные, отправляется пакет с флагом RST.

Установка и использование этих битов флага может помочь TCP надежно взаимодействовать между уровнем приложений и сетевым уровнем, гарантируя, что передача данных, а также установление и закрытие соединения могут быть выполнены правильно. Наш инструмент также может анализировать эти различные состояния битов флага, как показано ниже. показано на рисунке;

Декодирование пакетов уровня UDP

Пакет уровня UDP (протокол пользовательских дейтаграмм) — это четвертый уровень в стеке протоколов TCP/IP (протокол управления передачей/Интернет-протокол). Он проще, чем TCP, и не гарантирует местонахождение и достоверность пакетов данных, а также не устанавливает и не поддерживает соединение. Пакеты UDP содержат только заголовок UDP и части данных.

Заголовок UDP включает в себя следующее:

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

Преимуществами протокола UDP являются небольшие накладные расходы на передачу, высокая скорость и низкая задержка, поскольку он не выполняет проверку ошибок при высокой нагрузке, а также не устанавливает и не поддерживает соединение. Но это также означает, что передача пакетов данных ненадежна и целостность и правильность передачи данных не гарантируется. Если пакет UDP получен неправильно, попытка повторно отправить потерянный пакет предприниматься не будет. UDP часто используется для приложений, которым требуется быстрота, простота и низкая задержка, например онлайн-игры, потоковое видео и аудио и т. д.

Язык кода:c
копировать
// Уровень UDP точно такой же, как уровень TCP, за исключением небольшой разницы в определении и распаковке структуры.
void PrintUDPHeader(const unsigned char * packetData)
{
  typedef struct udp_header
  {
    uint32_t sport;   // исходный порт
    uint32_t dport;   // целевой порт
    uint8_t zero;     // Зарезервированный бит
    uint8_t proto;    // идентификатор протокола
    uint16_t datalen; // Длина данных UDP
  }udp_header;

  struct udp_header *udp_protocol;
  // +14 Пропустить уровень канала передачи данных +20 Пропустить уровень IP
  udp_protocol = (struct udp_header *)(packetData + 14 + 20);

  u_short sport = ntohs(udp_protocol->sport);
  u_short dport = ntohs(udp_protocol->dport);
  u_short datalen = ntohs(udp_protocol->datalen);

  printf("Исходный порт: %5d --> Порт назначения: %5d --> размер: %5d \n", sport, dport, datalen);
}

Анализ протокола UDP становится очень простым. Поскольку UDP является протоколом без сохранения состояния, можно получить только порт источника и порт назначения. Результат анализа показан на рисунке ниже.

Декодирование пакетов уровня ICMP

Пакеты уровня ICMP (Протокол управляющих сообщений Интернета) являются третьим уровнем в стеке протоколов TCP/IP. Это протокол управления, используемый для отчетов об ошибках и запроса состояния сети в сетевых коммуникациях. Пакеты ICMP обычно не несут никаких данных приложения или полезной нагрузки.

Пакеты ICMP обычно включают в себя следующие типы управляющей информации:

  • Эхо-запрос/ответ: используется для тестирования сетевого подключения, например команды ping (12/0).
  • Пункт назначения недоступен: этот тип ICMP-пакета используется для доставки отправителю сообщений, которые недоступны пункту назначения (3/0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6). , 3/7, 3/8, 3/9, 3/10)
  • Перенаправление: используется для информирования отправителя о необходимости использования нового маршрутизатора для отправки данных (5/0, 5/1, 5/2).
  • Превышено время: используется для сообщения отправителю о том, что пункт назначения не может быть достигнут на основе значения TTL, что указывает на то, что количество прыжков превышает максимальный предел (11/0, 11/1).
  • Проблема с параметром: используется для сообщения отправителю о том, что сервер пересылки не может обработать определенные поля в IP-пакете (12/0).

Пакеты ICMP также используются для других целей, таких как обнаружение прослушивателя многоадресной рассылки (MLD) и протокол обнаружения соседей (NDP), которые используются в многоадресной рассылке и сетевых соединениях IPv6.

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

Язык кода:c
копировать
//Декодируем ICMP-пакеты,существовать解包дануждатьсятакой женуждаться Пропустить уровень канала передачи данныхиIPслой, Затем выполните анализ по номеру типа ICMP, Обычно используемый номер типа — `type 8`Он представляет собой временную метку отправки и получения пакетов.
void PrintICMPHeader(const unsigned char * packetData)
{
  typedef struct icmp_header {
    uint8_t type;        // Тип ICMP
    uint8_t code;        // код
    uint16_t checksum;   // Контрольная сумма
    uint16_t identification; // логотип
    uint16_t sequence;       // серийный номер
    uint32_t init_time;      // Временная метка начала
    uint16_t recv_time;      // принять временную метку
    uint16_t send_time;      // Временная метка передачи
  }icmp_header;

  struct icmp_header *icmp_protocol;

  // +14 Пропустить уровень канала передачи данных +20 Пропустить уровень IP
  icmp_protocol = (struct icmp_header *)(packetData + 14 + 20);

  int type = icmp_protocol->type;
  int init_time = icmp_protocol->init_time;
  int send_time = icmp_protocol->send_time;
  int recv_time = icmp_protocol->recv_time;
  if (type == 8)
  {
    printf("Временная метка начала: %d --> Временная метка передачи: %d --> Получить временную метку: %d направление: ",
      init_time, send_time, recv_time);

    switch (type)
    {
    case 0: printf("Эхо-ответное сообщение \n"); break;
    case 8: printf("Сообщение эхо-запроса \n"); break;
    default:break;
    }
  }
}

Анализ протокола ICMP также очень прост. При перехвате пакетов мы можем получить только некоторую базовую информацию, такую ​​​​как метка времени отправки, метка времени передачи, метка времени получения и направление сообщения. Здесь есть два направления: 0 представляет эхо-ответ. в то время как 8 представляет эхо-запрос. Конкретные выходные данные следующие:

Декодировать пакеты уровня HTTP

Пакет уровня HTTP (протокол передачи гипертекста) — это седьмой уровень в стеке протоколов TCP/IP. Он в основном используется для передачи данных между клиентом и сервером в веб-приложениях. HTTP-пакеты обычно состоят из двух частей: HTTP-заголовка и части данных.

Заголовки HTTP обычно включают следующее:

  • Строка запроса: используется для описания запроса, инициированного клиентом.
  • Строка ответа: используется для описания ответа, возвращаемого сервером.
  • Поле заголовка: используется для добавления к запросу или ответу дополнительной информации метаданных, такой как номер версии HTTP, дата, тип контента и т. д.
  • Файл cookie: используется для сохранения информации о состоянии между клиентом и сервером.
  • Cache-Control: используется для управления поведением кэширования между клиентом и сервером.
  • Часть данных — это данные приложения, содержащиеся в HTTP-запросе или ответе.

Протокол HTTP работает следующим образом: клиент отправляет HTTP-запрос на сервер, а сервер возвращает результат запроса через HTTP-ответ. HTTP-запросы обычно используют методы HTTP, такие как GET, POST, PUT, DELETE и т. д., для управления типом и поведением операций HTTP. Ответы HTTP обычно содержат коды состояния HTTP, например 200, 404, 500 и т. д., чтобы указать состояние результатов запроса клиента.

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

Язык кода:c
копировать
// Декодируем HTTP-пакет,нуждаться Пропустить уровень канала передачи данных, Уровень IP и уровень TCP, Наконец, вы можете получить заголовок протокола HTTP-пакета.
void PrintHttpHeader(const unsigned char * packetData)
{
  typedef struct tcp_port
  {
    unsigned short sport;
    unsigned short dport;
  }tcp_port;

  typedef struct http_header
  {
    char url[512];
  }http_header;

  struct tcp_port *tcp_protocol;
  struct http_header *http_protocol;

  tcp_protocol = (struct tcp_port *)(packetData + 14 + 20);
  int tcp_sport = ntohs(tcp_protocol->sport);
  int tcp_dport = ntohs(tcp_protocol->dport);

  if (tcp_sport == 80 || tcp_dport == 80)
  {
    // +14 Пропустить MAC-уровень +20 Пропустить уровень IP +20 Пропустить уровень TCP
    http_protocol = (struct http_header *)(packetData + 14 + 20 + 20);
    printf("%s \n", http_protocol->url);
  }
}

Протокол HTTP также можно проанализировать, но поскольку протокол HTTP используется редко, этот код можно только продемонстрировать. В реальном бою обычно используется HTTPS. Ниже приведен пакет данных, перехваченный во время доступа по HTTP;

Декодирование пакетов уровня ARP

Пакеты уровня ARP (протокола разрешения адресов) являются вторым уровнем в стеке протоколов TCP/IP. Протокол ARP в основном используется для сопоставления адресов сетевого уровня (например, IP-адресов) с адресами канального уровня (например, MAC-адресами).

Пакеты ARP обычно включают в себя следующее:

  • Запрос или ответ ARP: запрос ARP используется для получения MAC-адреса, связанного с IP-адресом, а ответ ARP используется для предоставления целевого MAC-адреса.
  • MAC-адрес отправителя: MAC-адрес устройства, отправляющего запрос или ответ ARP.
  • IP-адрес отправителя: IP-адрес устройства, отправляющего запрос или ответ ARP.
  • MAC-адрес цели: MAC-адрес целевого устройства.
  • IP-адрес цели: IP-адрес целевого устройства.

Рабочий процесс протокола ARP выглядит следующим образом:

  • Хост-отправитель отправляет запрос ARP, содержащий целевой IP-адрес.
  • Все устройства в сети получают этот запрос ARP.
  • Если IP-адрес устройства совпадает с целевым IP-адресом в запросе ARP, устройство ответит ответом ARP, включая его собственный MAC-адрес.
  • Хост-отправитель использует MAC-адрес в ответе для связи с устройством.

Основная задача протокола ARP — реализовать сопоставление адресов в локальной сети, что в основном включает в себя определение MAC-адреса какого устройства связан с конкретным IP-адресом и ответ на запросы сопоставления, которые преобразуют IP-адреса в соответствующие MAC-адреса. ARP обычно используется в сетях Ethernet и Wi-Fi для обеспечения связи устройств внутри локальной сети.

Язык кода:c
копировать
// Декодировать ARP-пакеты
void PrintArpHeader(const unsigned char * packetData)
{
  typedef struct arp_header
  {
    uint16_t arp_hardware_type;
    uint16_t arp_protocol_type;
    uint8_t arp_hardware_length;
    uint8_t arp_protocol_length;
    uint16_t arp_operation_code;
    uint8_t arp_source_ethernet_address[6];
    uint8_t arp_source_ip_address[4];
    uint8_t arp_destination_ethernet_address[6];
    uint8_t arp_destination_ip_address[4];
  }arp_header;

  struct arp_header *arp_protocol;

  arp_protocol = (struct arp_header *)(packetData + 14);

  u_short hardware_type = ntohs(arp_protocol->arp_hardware_type);
  u_short protocol_type = ntohs(arp_protocol->arp_protocol_type);
  int arp_hardware_length = arp_protocol->arp_hardware_length;
  int arp_protocol_length = arp_protocol->arp_protocol_length;
  u_short operation_code = ntohs(arp_protocol->arp_operation_code);

  // Определите, является ли это пакетом запроса ARP.
  if (arp_hardware_length == 6 && arp_protocol_length == 4)
  {
    printf("Исходный MAC-адрес: ");
    for (int x = 0; x < 6; x++)
      printf("%x:", arp_protocol->arp_source_ethernet_address[x]);
    printf(" --> ");

    printf("MAC-адрес назначения: ");
    for (int x = 0; x < 6; x++)
      printf("%x:", arp_protocol->arp_destination_ethernet_address[x]);
    printf(" --> ");

    switch (operation_code)
    {
    case 1: printf("ARP просить \n"); break;
    case 2: printf("ARP отвечать \n"); break;
    case 3: printf("RARP просить \n"); break;
    case 4: printf("RARP отвечать \n"); break;
    default: break;
    }
  }
}

Также возможен анализ протокола ARP.,Протокол ARP также имеет несколько состояний.,в целом1-2представлятьпроситьиотвечать,3-4представлятьRARPобеспечить регресспроситьиотвечать,Из-за короткого периода срабатывания протокола ARP считыватели редко могут захватывать данные этого типа.,Как показано на рисунке ниже, считыватель фиксирует полный статус протокола ARP;

Автор статьи: Ван Жуй

Ссылка на эту статью: https://www.lyshark.com/post/526b8a6.html

Заявление об авторских правах: если не указано иное, все статьи в этом блоге лицензируются по лицензии BY-NC-SA. При перепечатке просьба указывать источник!

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.