• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

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

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Статья Анализатор трафика

  • Автор темы S-haman
  • Дата начала
Здроавствуйте мне необходимо написать прогармму для анализа локального траффика, это сниффер(для получения пакетов) и потом анализ этих пакетов. Я почитал много литературы и узнал что лутчше это делать с помощью библиотеки/драйвера libpcap, а для виндовса winpcap, скачал эту библиотеку/драйвер установил, паралельно нашел как с этой библиотекой работать , начал исать программу и при подключении файла <pcap.h> компилятор выдает ошибку что неможет найти этого файла. Подскажите что я делаю не правильно.

P.S. Использую компилятор BCB 6
 
S

S-haman

ReindeeR
спасибо за функцию у меня небыло про такую функцию написано )).
в этой функции не понятно только одно как сами данные получить, тоесть в третем параметре там где "pcap_handle callback" я вызываю функцию которая имеет три параметра:
Код:
u_char *param, const pcap_pkthdr *header, const u_char *pkt_data
второй параметр это заголовок я сравнивал полученные данные с wireshark правильно определило но вот другие два параметра возвращяют пустые строки, как с ними работать? второй параметр это структура с ним безпроблем работается а те это просто строки, которые всегда пустые. Подскажите как с ними работать
 
R

ReindeeR

pcap_loop()
принимает четыре параметра.
1-дескриптор открытой сессии.
2-кол-во пакетов,-1 означает что хавает все до ошибки.
3-функция обработчик пакета.
4-используется для передачи еще каких-нить данных,если ничего не надо,то NULL
ну тут впринципе все понятно,самое главное,это функция,которая обрабатывает пакеты.
В данном случае функция-обработчик не любая попавшаяся,а заранее определенная.
Код:
void packHandler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
ну это и так все ясно было.
Если не забыли,то в pcap_loop() в четвертом параметре можно чето передать.
Так вот,первый аргумент у функции-обработчика как раз и принимает то,что было передано в четвертом параметре
pcap_loop().Соответственно если передан NULL,то и не придет ничего,ради интереса можете убедиться
и послать строку,а в обработчике вывести ее на экран :)
Второй параметр,структура ,на всякий случай,выглядит она так
Код:
struct pcap_pkthdr {
struct timeval ts; 
bpf_u_int32 caplen; 
bpf_u_int32 len;  
};
Третий параметр,буфер,в который помещается сам принятый пакет.
Вот его как раз и надо мучать.Определяете все структуры заголовков.
Если совсем разбирать пакет,то это примерно в таком порядке будет выглядеть:
ETHERNET
ARP
IP
TCP/UDP или чего у вас там будет.

Ну вот вроде все пока что.
зы.
ко мне на "Вы" не надо,маленький я еще для этого :)

Надо еще с синтаксисом выражений для фильтра разобраться,все руки не доходят :unsure:
 
S

S-haman

ReindeeR пример хороший но одно но, третий параметр в котором хранятся данные он пустой он возвращяет пустую строку. В некоторых программах я увидел следующий пример как они получают данные они обявляют структуру в которой описываютатрибуты пакета потом присваивают переменно полученныее данные конвертированыфе в эту структуру и работают с этой структурой пример
Код:
struct sniff_ip 
{
#if BYTE_ORDER == LITTLE_ENDIAN
u_int ip_hl:4, /* header length */
ip_v:4; /* version */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_int ip_v:4, /* version */
ip_hl:4; /* header length */
#endif /* not _IP_VHL */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
struct sniff_ip *sip; 
sip = (struct sniff_ip*)(packet); //packet з параметр функции pcap_handle
после чего обращяясь к элементам sip работают с элементами пакета, но здесь только заголовочные фрагменты пакета
если packet не ковертирвоать в структуру то он равен концу строки тоесть '\0'
Как можно просто из этой переменной получить пакет в обычном виде:
Код:
00 18 f3 5b f4 b9 00 e0 4e 09 c3 d4 08 00 45 00
00 28 d2 c1 40 00 80 06 cd dc ac 0a 01 0f ac 0a
01 0e 1f 90 06 aa f7 ca f6 92 e6 42 ce 47 50 10
fb b4 90 cb 00 00 00 00 00 00 00 00
или подобном
 
R

ReindeeR

ну а я о чем говорил? :)
Третий параметр,буфер,в который помещается сам принятый пакет.
Вот его как раз и надо мучать.Определяете все структуры заголовков.
Если совсем разбирать пакет,то это примерно в таком порядке будет выглядеть:
ETHERNET
ARP
IP
TCP/UDP или чего у вас там будет.
вот структуры.
заголовок ethernet
Код:
#define ETH_ALEN 6 /* Octets in one ethernet addr */
struct ethhdr
{
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned short h_proto; /* packet type ID field */
};
arp
Код:
struct arphdr
{
unsigned short ar_hrd;		/* format of hardware address	*/
unsigned short ar_pro;		/* format of protocol address	*/
unsigned char	 ar_hln;		/* length of hardware address	*/
unsigned char	 ar_pln;		/* length of protocol address	*/
unsigned short ar_op;			/* ARP opcode (command)		*/
unsigned char	 ar_sha[ETH_ALEN];	/* sender hardware address	*/
unsigned char	 ar_sip[4];		/* sender IP address		*/
unsigned char	 ar_tha[ETH_ALEN];	/* target hardware address	*/
unsigned char	 ar_tip[4];		/* target IP address		*/
};
IP
Код:
struct iphdr{
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
__u16 tot_len;
__u16 id;
__u16 frag_off;
__u8 ttl;
__u8 protocol;
__u16 check;
__u32 saddr;
__u32 daddr;
/*The options start here. */
};
TCP
Код:
struct tcphdr {
__u16 source;
__u16 dest;
__u32 seq;
__u32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u16 window;
__u16 check;
__u16 urg_ptr;
};

под себя тут можно подделать если что,брал из никсов.
 
S

S-haman

ReindeeR, а есть ли какой нибудь способ получить данные из той переменной не используя структуры, примеры со структурами хорошие, но в виндовсе нету для них хидеров. Есть ли какойто способ получить пакет целиком?

P.S. Или хотябы по какому закону заполняются элементы этих структур, те что описаны элементы совпадают по названиям с названиями в программе wireshark, но когда я пробую добавть те что мне надо выводитсмя полня ерунда
 
R

ReindeeR

Хм,тут от винды не зависит,просто я знаю где в никсах эти структуры объявлены.
Я тоже виндой пользуюсь,структуры приходиться самому объявлять.
Больше разницы нет.Пакеты-то везде одинаковые.
По какому закону?я не совсем понял,если честно,но щас попробую на примере объяснить.
Сначала объявляешь структуры.
Код:
#define ETH_ALEN 6 /* Octets in one ethernet addr */
struct ethhdr
{
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned short h_proto; /* packet type ID field */
};
pcap_loop() и все что до этого опущу,начну с обработчика.
Код:
void packetHandler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
struct ethhdr ethernetHeader;
memcpy((char*) &ethernetHeader,pkt_data,sizeof(struct ethhdr));	//В ethernetHeader у нас теперь находиться заголовок eth. пакета.
printf("=====ETH. заголовок=====");
printf("destination eth addr: %s",ethernetHeader.h_dest);
printf("source ether addr: %s",ethernetHeader.h_source);
printf("packet type ID field: %s",ethernetHeader.h_proto);
}
Продолжение следует... :)
Просто окошко маленькое писать неудобно))

Предварительно конечно лучше вытащить информацию о пакете
из pcap_pkthdr для наглядности так сказать))

Ну вот таким образом мы разобрали Ethernet заголовок пакета.
Далее за ним следует ARP или IP заголовок.
указывается это в поле h_proto
проверяем
Код:
if((ntohs(eth.h_proto) == ETH_P_ARP) || 
(ntohs(eth.h_proto) == ETH_P_RARP)) {
//разбираем ARP заголовок.
}
if(ntohs(eth.h_proto) == ETH_P_IP)
{
//разбираем IP заголовок
}
Продолжение следует))


Разбираем заголовок ARP пакета.
Структура ARP заголовка.
Код:
struct arphdr
{
unsigned short ar_hrd;		/* format of hardware address	*/
unsigned short ar_pro;		/* format of protocol address	*/
unsigned char	 ar_hln;		/* length of hardware address	*/
unsigned char	 ar_pln;		/* length of protocol address	*/
unsigned short ar_op;			/* ARP opcode (command)		*/
unsigned char	 ar_sha[ETH_ALEN];	/* sender hardware address	*/
unsigned char	 ar_sip[4];		/* sender IP address		*/
unsigned char	 ar_tha[ETH_ALEN];	/* target hardware address	*/
unsigned char	 ar_tip[4];		/* target IP address		*/
};
Продолжение функции обработчика пакетов.
Все это делать там,где h_proto==ETH_P_ARP

Код:
struct arphdr *arpHeader;

//теперь у нас в arpHeader заголовок ARP,разбираем аналогично.
printf("====ARP заголовок=====");
printf("format of hardware address: %d",htons(arpHeader->ar_hrd));
//ну и так далее проход по нужным полям.


После ARP/IP следует TCP/UDP заголовки,или какие там еще протоколы есть.
Разбирается все аналогично.
например ip заголовок
Код:
ipHeader = (struct arphdr *)(pkt_data + sizeof(struct ethhdr)+sizeof(struct arphdr));
И так же по всем полям printf)))
или че там с ними делать собрались.

Осталось написать структуру ip tcp udp и т.д. пакетов
и в путь.

зы.
Где можно почитать
о всех этих %s %d и т.д. в printf()?
а не то я кроме s и d ничего не знаю. :)
 
S

S-haman

при компилировании пишет что неизвестны переменные ETH_P_ARP, ETH_P_RARP и ETH_P_IP
 
R

ReindeeR

Код:
#define ETH_P_RARP 0x8035
#define ETH_P_ARP 0x0806
#define ETH_P_IP 0x0800
объявите константы)
 
S

S-haman

Или хотябы по какому закону заполняются элементы этих структур, те что описаны элементы совпадают по названиям с названиями в программе wireshark, но когда я пробую добавть те что мне надо выводитсмя полня ерунда
по какому закону, это в смысле как выбирать имена и типы переменных в структуре, ведь если к примеру написать Source- то в эту переменну будет записано какоето левое число, также как выбирать тип для этих переменных. Я пробовал давать имена наподобие как в программе wireshark но там выводило немного не то что надо.
 
R

ReindeeR

Типы в струткурах задаются по размеру данных.
Расскажу подробнее,просто щас винда слетела,
терь до утра ***ться :huh:
 
R

ReindeeR

Ну вроде все работает,начнем))
Рассказывать буду напримере IP.
Первым делом идем к гуглю и спрашиваем RFC IP.
Выдает нам что rfc ip протокола номер 791.
Если траблы с английским,то ищем "RFC 791 на русском".
Идем по первой попавшейся ссылке.

Если вы мазохист или же нужно досконально разобраться в протоколе,то читаем все.
Находим структуру заголовка.
Там вот такая бодяга.
Код:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service|		 Total Length		 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|		 Identification		|Flags|	 Fragment Offset	|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live |	Protocol  |		 Header Checksum	  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|					  Source Address						 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|					Destination Address						|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|					Options					|	Padding	|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Как написано,каждая позиция соответствует одному биту.
Можно читать,а можно и самому крестики/плюсики считать.
Для начала объявим структуру,пока что пустую.
Ну например так.

Код:
struct ip_header
{
}

Первым у нас идет поле Version,и занимает оно у нас 4 бита.

Version (версия) 4 бита
Поле версии показывает формат заголовка Internet. Данный документ
описывает версию 4.
Значит нам нужно поле в 4 бита.

Код:
struct ip_header
{
unsigned int version: 4;
}

имя можно задавать любое,какое душе угодно,главное чтобы размер подходил.
Далее идет поле IHL,тоже 4 бита.

IHL (длина Internet заголовка) 4 бита
Длина Internet заголовка измеряется в словах по 32 бита каждый и
указывает на начало поля данных. Заметим, что корректный заголовок
может иметь минимальный размер 5 слов.

Дополняем нашу структуру:

Код:
struct ip_header
{
unsigned int version: 4;
unsigned int ihl: 4;
}
Далее у нас идет Type of Service-8 бит.
Для этого поля лучше создать свою структуру

Type of Service (тип сервиса) 8 бит
Тип сервиса определяет с помощью неких абстрактных параметров тип
требуемого обслуживания. Эти параметры должны использоваться для
управления выбором реальных рабочих характеристик при передаче
датаграммы через конкретную сеть. Некоторые сети осуществляют
обслуживание с приоритетом, которое неким образом дает преимущество
для продвижения данной датаграммы по сравнению со всеми остальными.
Реально выбор осуществляется между тремя альтернативами: малой
задержкой, высокой достоверностью и высокой пропускной способностью.
биты 0-2 приоритет
бит 3 0 - нормальная задержка, 1 - малая задержка
бит 4 0 - нормальная пропускная способность,
1 - высокая пропускная способность
бит 5 0 - обычная достоверность, 1 - высокая достоверность
биты 6-7 зарезервированы
0 1 2 3 4 5 6 7
+-----+-----+-----+-----+-----+-----+-----+-----+
| приоритет | D | T | R | 0 | 0 |
+-----+-----+-----+-----+-----+-----+-----+-----+

Разъяснять написание структуры уж не буду,просто приведу ее в конце.
Структура так и будет называться TypeOfService;
Дополняем структуру IP заголовка.

Код:
struct ip_header
{
unsigned int version: 4;
unsigned int ihl: 4;
struct TypeOfService typeServ;
}
Total Length,Identification.
Оба по 16 бит,то есть два байта.

Total Length (общая длина) 16 бит
Общая длина - это длина датаграммы, измеренная в октетах, включая
Internet заголовок и поле данных. Это поле может задавать длину
датаграммы вплоть до 65535 октетов. В большинстве хост-компьютеров и
сетей столь большие датаграммы не используются. Все хосты должны быть
готовы принимать датаграммы вплоть до 576 октетов длиной (приходят ли
они целиком или по фрагментам). Хостам рекомендуется отправлять
датаграммы размером более чем 576 октетов, только если они уверены,
что принимающий хост готов обслуживать датаграммы повышенного
размера.
Значение 576 выбрано с тем, чтобы соответсвующим образом
ограниченный блок данных передавался вместе с требуемой информацией в
заголовке. Например, этот размер позволяет заполнять датаграмму полем
данных размером в 512 октетов и заголовком в 64 октета. Наибольший
Internet заголовок занимает 60 октетов, а его типичный размер
составляет всего 20 октетов, что оставляет место под заголовки
протоколов более высокого уровня.
Identification (идентификатор) 16 бит
Идентификатор устанавливается отправителеим для сборки фрагментов
какой-либо датаграммы.


А два байта у нас занимает тип short.
Дописываем

Код:
struct ip_header
{
unsigned int version: 4;
unsigned int ihl: 4;
struct TypeOfService typeServ;
short length;
short id;
}

Далее поле Flags,занимает 3 бита.В переводе RFC по ссылке,которую я дал
ошибка,там написано 16 бит.На самом деле 3.

Flags (различные управляющие флаги) 3 бита
бит 0 зарезервирован, должен быть нуль
бит 1 (DF) 0 - возможно фрагментирование, 1 - запрет фрагментации
бит 2 (MF) 0 - последний фрагмент, 1 - будут еще фрагменты
0 1 2
+----+----+----+
| 0 | DF | MF |
+----+----+----+
Дорисываем в структуру еще одно значение.

Код:
unsigned int flags:3;

unsigned int везде пишу не по каким-то правилам,а так,от балды :huh:

Далее:
Fragment Offset (смещение фрагмента) 13 бит
Это поле показывает, где в датаграмме находится этот фрагмент.
Смещение фрагмента изменяется порциями по 8 октет (64 бита). Первый
фрагмент имеет смещение нуль.

Код:
unsigned short offset: 13;

Далее у нас идет время жизни в размере 8 бит или одного байта.

Time to Live (Время жизни) 8 бит
Это поле показывает максимальное время, в течении которого датаграмме
позволено находиться в системе Internet. Если это поле имеет значение
нуль, то датаграмма должна быть разрушена. Значение этого поля
изменяется при обработке заголовка Internet. Время измеряется в
секундах. Однако, поскольку каждый модуль, обрабатывающий датаграмму,
должен уменьшать значение поля TTL по крайней мере на единицу, даже
если он обрабатываетт эту датаграмму менне, чем за секунду, то поле
TTL следует понимать как максимальный интервал времени, в течении
которого датаграмма может сущенствовать. Внимание следует обратить на
разрушение датаграмм, не могущих достигнуть получателя, а также на
ограничение времени жизни датаграммы.
Подойдет тип char.
Дописываем.

Код:
unsigned char timeLive;

Далее идет протокол в размере 8 бит,протоколы описаны в документе "Assigned Numbers".
В сети не составит труда его найти.

Protocol (Протокол) 8 бит
Это поле показывает, какой протокол следующего уровня использует
данные из Internet датаграммы. Значения для различных протоколов
приводятся в документе "Assigned Numbers" [9].
Код:
unsigned char proto;

Header Checksum (Контрольная сумма заголовка) 16 бит
Поскольку некоторые поля заголовка меняют свое значение (например,
время жизни), это значение проверяется и повторно рассчитывается при
каждой обработке Internet заголовка.
Алгоритм контрольной суммы следующий:
Поле контрольной суммы - это 16 бит, дополняющие биты в сумме всех
16 битовых слов заголовка. Для вычисления контрольной суммы
значение этого поля устанавливается в нуль.
Контрольную сумму легко рассчитать и опытным путем доказать ее
адекватность, однако это временная мера и должна быть заменена CRC
процедурой в зависимости от дальнейшего опыта.
Дописываем поле для контрольной суммы.

Код:
unsigned short ckeksum;

Далее идут адреса отправителя и получателя.
Source Address (адрес отправителя) 32 бита
Destination Address (адрес получателя) 32 бита
Здесь не будем ничего придумывать своего,а исполльзуем уже определенную структуру
для IP адресов.
Код:
struct in_addr source_addr;
struct in_addr dest_addr;

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

Ну и в конце привожу,как все это выглядит вместе.

Код:
struct TypeOfService
{
unsigned int Priority: 3;
unsigned int D: 1;
unsigned int T: 1;
unsigned int R: 1;
unsigned int reserved:2;
}

struct ip_header
{
unsigned int version: 4;
unsigned int ihl: 4;
struct TypeOfService typeServ;
unsigned short length;
unsigned short id;
unsigned int flags:3;
unsigned short offset: 13;
unsigned char timeLive;
unsigned char proto;
unsigned short ckeksum;
struct in_addr source_addr;
struct in_addr dest_addr;
}

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

©btrfly, 2008;
 
R

ReindeeR

p.s.
в некоторых импровизированных таблицах все сбилось :ph34r: ,
так что лучше смотреть в оригинале.
 
S

S-haman

Спасибо хороший ответ ))
Всё изложено грамотно и доступно ))
Остался только один вопрос а как получить мак адрес получателя и отправителя, пробовал создавать структру как и для ап адресса, но забивает ерундой, в той структуре что написана там просто адресс источника и приемника 32 бита это только под ап отводится а как тогда мак достать?
 
R

ReindeeR

мак передается в ethernet заголовке.
в IP заголовке соответственно айпи получателя и отправителя.

ап.
и если ARP,то мак можно еще и оттуда выудить.
 
S

S-haman

Есть ли возможность получить имя компютера, тоесть оно передаеться в пакете или нет?
Как можно узнать конечный/начальный адресс назначения, тоесть если я к примеру получаю данные от компютера из интернета, посредством тогоже торрента, у меня сниффер получает адресс шлюза , а не той машини.
 
R

ReindeeR

Есть ли возможность получить имя компютера, тоесть оно передаеться в пакете или нет?
точно не помню,но вроде можно.погуглите на этот счет.
Как можно узнать конечный/начальный адресс назначения, тоесть если я к примеру получаю данные от компютера из интернета, посредством тогоже торрента, у меня сниффер получает адресс шлюза , а не той машини.
с торрентами никогда не связывался,так что предположение:
посмотрите протокол торрента,как и че там устроено.
из айпи заголовков скорее всего нельзя вытянуть,так как там указывается шлюз сервера.
 
Z

zenitChampion

S-haman, как с тобой можно связаться? здесь я не могу отправлять личные сообщения :)
мне оч нужна твоя помощь!
 

SearcherSlava

Red Team
10.06.2017
943
1 259
BIT
113











 
  • Нравится
Реакции: Vertigo
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!