Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кулаков В.Г. Методические указания к лабораторн...doc
Скачиваний:
5
Добавлен:
04.05.2019
Размер:
286.72 Кб
Скачать

5.4. Упражнения

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

  1. Создать консольное приложение, ввести, скомпилировать и запустить программу, приведенную в листинге 5.2 (перед началом компиляции в свойствах проекта в разделе Linker/Input в пункте Additional Dependencies добавить библиотеки IPHlpApi.lib и ws2_32.lib). Отображенные в окне программы номера открытых портов нужно запомнить или записать, а затем завершить работу программы нажатием клавиши Enter.

  2. Создать новое консольное приложение, ввести, скомпилировать и запустить программу-сканер, приведенную в листинге 5.1 (перед началом компиляции в свойствах проекта в разделе Linker/Input в пункте Additional Dependencies добавить библиотеку ws2_32.lib). В качестве IP-адреса нужно указать петлевой адрес 127.0.0.1. Начальное и конечное значения диапазона адресов сканируемых портов следует задать таким образом, чтобы в него попадало несколько открытых портов. После окончания сканирования завершить работу программы нажатием клавиши Enter.

  3. Запустить сканер портов повторно, указав IP-адрес соседнего компьютера и тот же диапазон адресов портов, который был задан в предыдущем пункте. После окончания сканирования завершить работу программы нажатием клавиши Enter.

Лабораторная работа №6

6.1. Цель и содержание работы

Целью работы является изучение правил использования сырых сокетов библиотеки Winsock2 для прослушивания сетевого трафика.

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

6.2. Сниффер

Сниффер (sniffer) – это программа, позволяющая просматривать сетевой трафик в пределах данного сегмента сети. Ее возможности основаны на особенностях протокола Ethernet: все устройства используют единую магистраль для обмена данными. Каждое устройство имеет уникальный MAC-адрес длиной 6 байт. В заголовке кадра Ethernet указывается MAC-адрес отправителя и MAC-адрес получателя. Устройства сетевого обмена ретранслируют этот кадр на все устройства в данном сегменте сети. Сетевая плата обычно принимает только пакеты, адрес получателя в которых совпадает с ее адресом, и отсеивает все остальные.

Для создания сниффера необходимо, во-первых, каким-то образом получить доступ к сетевому трафику. Т.к. сетевая плата по умолчанию игнорирует пакеты, не предназначенные для нее, то необходимо перевести ее в состоянии полного прослушивания (promiscuous mode). Для переключения в режим прослушивания используется функция управления режимом ввода-вывода int ioctlsocket(SOCKET s, long cmd, u_long* argp), которая имеет три параметра: дескриптор сокета, код команды и указатель на параметр команды. Код команды для включения прослушивания имеет значение 0x98000001.

Во-вторых, необходимо иметь некий набор правил и фильтров, согласно которым из общего сетевого потока будут выбираться необходимые пакеты. В большинстве случаев нет нужды просматривать все идущие через сеть пакеты – как правило, владелец машины, на которой запущен сниффер, желает просматривать трафик только одного типа или от одного устройства. Для обеспечения доступа к информации, передаваемой в заголовках пакетов, используются сырые (RAW) сокеты: при открытии сокета второй параметр функции socket должен иметь значение SOCK_RAW.

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

Листинг 6.1. Сниффер

#include "stdafx.h"

#include <conio.h>

#include <winsock2.h>

#define MAX_PACKET_SIZE 0x10000

#define SIO_RCVALL 0x98000001

// Буфер для приёма данных

char Buffer[MAX_PACKET_SIZE]; // 64 Kb

//Структура заголовка IP-пакета

typedef struct IPHeader {

UCHAR iph_verlen; // Версия и длина заголовка

UCHAR iph_tos; // Тип сервиса

USHORT iph_length; // Длина пакета

USHORT iph_id; // Идентификатор

USHORT iph_offset; // Флаги и смещения

UCHAR iph_ttl; // Время жизни пакета

UCHAR iph_protocol; // Протокол

USHORT iph_xsum; // Контрольная сумма

ULONG iph_src; // IP-адрес отправителя

ULONG iph_dest; // IP-адрес назначения

} IPHeader;

int main(int argc, _TCHAR* argv[])

{

WSADATA wsadata;

SOCKET s; // Сокет

char name[128]; // Имя хоста (компьютера)

HOSTENT* phe; // Информация о хосте

SOCKADDR_IN sa; // Адрес хоста

IN_ADDR sa1;

unsigned long flag = 1; // Флаг PROMISC

unsigned short lowbyte; // Младший байт размера пакета

unsigned short hibyte; // Старший байт размера пакета

// Инициализация

WSAStartup(MAKEWORD(2,2), &wsadata);

s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);

gethostname(name, sizeof(name));

phe = gethostbyname(name);

ZeroMemory(&sa, sizeof(sa));

sa.sin_family = AF_INET;

sa.sin_addr.s_addr =

((struct in_addr *)phe->h_addr_list[0])->s_addr;

bind(s, (SOCKADDR *)&sa, sizeof(SOCKADDR));

// Включение promiscuous mode.

ioctlsocket(s, SIO_RCVALL, &flag);

// Цикл приёма IP-пакетов (продолжается до тех пор,

// пока не нажата любая клавиша на клавиатуре).

while(!_kbhit())

{

int count;

count = recv(s, Buffer, sizeof(Buffer), 0);

// обработка IP-пакета

if(count >= sizeof(IPHeader))

{

IPHeader* hdr = (IPHeader *)Buffer;

// Преобразуем в понятный вид адрес отправителя.

printf("Packet: From ");

sa1.s_addr = hdr->iph_src; printf(inet_ntoa(sa1));

// Преобразуем в понятный вид адрес получателя.

printf(" To ");

sa1.s_addr = hdr->iph_dest;

printf(inet_ntoa(sa1));

// Определяем протокол (только для TCP и UDP).

printf(" Prot: ");

if(hdr->iph_protocol == IPPROTO_TCP) printf("TCP ");

else

if(hdr->iph_protocol == IPPROTO_UDP)

printf("UDP ");

else printf("??? ");

// Вычисляем размер пакета (меняем байты местами)

lowbyte = hdr->iph_length>>8;

hibyte = hdr->iph_length<<8;

hibyte = hibyte + lowbyte;

printf("Size: %u",hibyte);

// Выводим время жизни пакета.

printf(" TTL: %u\n",hdr->iph_ttl);

}

}

closesocket(s);

WSACleanup();

}