Форум программистов
 
Расширенный поиск
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail



Ответ
 
Опции темы
Старый 27.11.2016, 16:55   #1
Aoizora
Пользователь
 
Регистрация: 11.11.2016
Сообщений: 35
Репутация: 10
По умолчанию Не получается забиндить сокет

Мне нужно написать простой анализатор пакетов, который снифает трафик, слегка анализирует пакеты и решает, отбрасывать пакет или нет. Написал такую программу:

Код:

#include <Winsock2.h>
#include <Windows.h>
#include <iostream>

#pragma comment(lib, "Ws2_32.lib")

#define SIO_RCVALL 0x98000001
#define MAX_PACKET_SIZE 0x10000

typedef struct tagIPHeader
{
  unsigned char  ver_len;		// версия и длина заголовка
  unsigned char  tos;			// тип сервиса 
  unsigned short length;		// длина всего пакета 
  unsigned short id;			// Id 
  unsigned short flgs_offset;		// флаги и смещение
  unsigned char  ttl;			// время жизни 
  unsigned char  protocol;		// протокол 
  unsigned short xsum;			// контрольная сумма 
  unsigned long  src;			// IP-адрес отправителя 
  unsigned long  dest;			// IP-адрес назначения 
  unsigned short *params;		// параметры (до 320 бит)
  unsigned char  *data;			// данные (до 65535 октетов)
} IPHeader;

void ShowError()
{
        LPVOID lpMsgBuf = NULL;
		int error = WSAGetLastError();
		printf("error = %d\n", error);
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
			NULL,
			error,
			MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
			(LPTSTR)&lpMsgBuf,0,NULL);
        std::cout << (LPCTSTR)lpMsgBuf << std::endl;
        LocalFree(lpMsgBuf);
}

IPHeader* sniff(SOCKET sock)
{
	IPHeader *hdr;
	char buffer[MAX_PACKET_SIZE];
	int count = 0;

	count = recv(sock, buffer, sizeof(buffer), 0);
	if (count >= (int)sizeof(IPHeader))
	{
		hdr = (IPHeader *)malloc(MAX_PACKET_SIZE);
		memcpy(hdr, buffer, MAX_PACKET_SIZE);
		return hdr;
	}
	else
		return 0;
}

int main()
{
		WSADATA wsaData;
		char hostname[128];
		HOSTENT* hostinfo;
		SOCKADDR_IN sa;
		sockaddr_in local_addr;
		unsigned long flag = 1;

        if(WSAStartup(0x0202, &wsaData)){ ShowError(); }
        else
        {
                std::cout << "WSAStartup - OK" << std::endl;
                SOCKET sock;
                sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);	// Create raw socket
                if(sock == INVALID_SOCKET){ ShowError(); }
                {
                        std::cout << "Raw scoket is created" << std::endl;
                        //if(closesocket(sock) == SOCKET_ERROR) { ShowError(); }
                }


				gethostname(hostname, sizeof(hostname));
				hostinfo = gethostbyname(hostname);

				ZeroMemory(&sa, sizeof(sockaddr));
				sa.sin_family = AF_INET;
				sa.sin_addr.s_addr = ((struct in_addr *)hostinfo->h_addr_list[0])->s_addr;

				ZeroMemory(&local_addr, sizeof(local_addr));
				local_addr.sin_family=AF_INET;
				local_addr.sin_addr.s_addr=((struct in_addr *)hostinfo->h_addr_list[0])->s_addr;
				if (bind(sock, (sockaddr *)&local_addr, sizeof(sockaddr) == SOCKET_ERROR))
				{
					ShowError();
				}

				ioctlsocket(sock, SIO_RCVALL, &flag);

				// Analyze packets
				while (true)
				{
						IPHeader* hdr = sniff(sock);
						// обработка IP-пакета
						if (hdr)
						{ 
								unsigned char *byte_iterator = (unsigned char *)hdr;
								for (int i = 0; i < sizeof(IPHeader); i++)
								{
										printf("%02x", *byte_iterator);
										++byte_iterator;
								}
						}
						free(hdr);
				}
                
                if(WSACleanup()) { ShowError(); }
                else
				{ std::cout << "WSACleanup - OK" << std::endl;}
        }
        
        return 0;
}

При бинде сокета возвращается ошибка 10014: Bad address. The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).

Я так понимаю, проблема в размере структур, которые я использую в вызове bind? Как решить проблему?
Aoizora вне форума   Ответить с цитированием
Старый 27.11.2016, 17:14   #2
Aoizora
Пользователь
 
Регистрация: 11.11.2016
Сообщений: 35
Репутация: 10
По умолчанию

Проблему с биндом решил. Не хватало закрывающей скобки.

Остались две задачи:
1. Добраться до данных в пакете и анализировать их
2. Переделать под IPv6

Чтобы получить данные, надо просто перейти по указателю, а размер этих данных равен IPHeader.length - sizeof(tagIPHeader)? Или нет?
Aoizora вне форума   Ответить с цитированием
Старый 27.11.2016, 17:14   #3
p51x
Профессионал
 
Регистрация: 15.02.2010
Сообщений: 8,798
Репутация: 1391

icq: 216409213
По умолчанию

Цитата:
Я так понимаю, проблема в размере структур, которые я использую в вызове bind?
Нет
Цитата:
Как решить проблему?
Расставить скобки правильно. Смотите внимательно как вы вызываете:
Код:

bind(sock, (sockaddr *)&local_addr, sizeof(sockaddr) == SOCKET_ERROR)

Сколько ( sizeof(sockaddr) == SOCKET_ERROR ) вы передаетье как размер?
__________________
Запомните раз и навсегда: помочь != "решите за меня"!
p51x на форуме   Ответить с цитированием
Старый 27.11.2016, 17:30   #4
Aoizora
Пользователь
 
Регистрация: 11.11.2016
Сообщений: 35
Репутация: 10
По умолчанию

Это решил.

Дописал такую процедуру:

Код:

void AnalyzePacket(IPHeader *hdr)
{
	int SizeOfData = hdr->length - sizeof(IPHeader);
	unsigned char *DataPtr = hdr->data;

	for (int i = 0; i < SizeOfData; i++)
	{
		printf("%c ", *DataPtr);
	}
	printf("\n\n");
}

То есть просто хочу вывести данные на экран. В DataPtr оказывается инвалидный указатель. Как вытащить данные из IP-пакета?

Еще хочу понять, какова структура данных, которые лежат в буфере после вызова recv. Там сырые данные, то есть IP-заголовок и прочая ботва, или что-то другое?
Aoizora вне форума   Ответить с цитированием
Старый 27.11.2016, 17:46   #5
waleri
Профессионал
 
Регистрация: 13.07.2012
Адрес: Нижний Новгород
Сообщений: 4,620
Репутация: 1407
По умолчанию

А что, это работает?! В документации прямым текстом написано, что нельзя передавать IPPROTO_IP...

Ref:
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
waleri вне форума   Ответить с цитированием
Старый 27.11.2016, 18:01   #6
Aoizora
Пользователь
 
Регистрация: 11.11.2016
Сообщений: 35
Репутация: 10
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
А что, это работает?! В документации прямым текстом написано, что нельзя передавать IPPROTO_IP...

Ref:
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
Черт знает, но src/dest-адреса в консоли похожи на настоящие, то есть сниффер работает правильно (или я не заметил где-то ошибку).

Остается вопрос, как добраться до данных.
Aoizora вне форума   Ответить с цитированием
Старый 27.11.2016, 18:04   #7
Aoizora
Пользователь
 
Регистрация: 11.11.2016
Сообщений: 35
Репутация: 10
По умолчанию

У меня в строке printf("data = %s\n", *hdr->data); или printf("data = %s\n", hdr->data); обращение к неверной памяти.
Aoizora вне форума   Ответить с цитированием
Старый 29.11.2016, 13:18   #8
Ethereal2
Пользователь
 
Регистрация: 17.02.2013
Сообщений: 25
Репутация: 88
По умолчанию

Цитата:
Сообщение от Aoizora Посмотреть сообщение
unsigned char *DataPtr = hdr->data;
Тебе нужен не указатель, взятый из поля данных, а указатель на поле данных. У тебя лишняя косвенность. Хотя, Си не моя тема, но вроде бы так.
Ethereal2 вне форума   Ответить с цитированием
Ответ



Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Что то не дает забиндить порты Abuhamed Windows 2 03.10.2013 00:14
Забиндить ImageBrush ImageSource coNsept Общие вопросы .NET 1 28.11.2012 05:00
Сокет останавливает другой сокет. batand C/C++ Сетевое программирование 2 09.10.2012 11:58
Вопрос по WinSock: "сокет=сокет." Ksardas13 C/C++ Сетевое программирование 2 27.11.2011 16:12
Как забиндить все ПОРТЫ? KaneKRY Работа с сетью в Delphi 0 02.04.2010 14:45




13:59.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.

Покупайте на сайте www.skinon.ru уникальные чехлы и наклейки для телефонов.
купить трафик


как улучшить посещаемость, а также решения по монетизации сайтов, видео и приложений

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru