Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > В неразборчивом режиме recv не принимает ничего


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

Код

#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;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
            NULL,
            WSAGetLastError(),
            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 >= 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 sockaddr;
        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);
                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(&sockaddr, sizeof(sockaddr));
                sockaddr.sin_family = AF_INET;
                sockaddr.sin_addr.s_addr = ((struct in_addr *)hostinfo->h_addr_list[0])->s_addr;
                bind(sock, (SOCKADDR *)&sockaddr, sizeof(SOCKADDR));

                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;
}



Но при выполнении sniff в цикле функция recv ничего не читает из сокета, и в буфере остается мусор. Что я делаю не так?

Автор: Aoizora 27.11.2016, 15:53
Добавил несколько проверок. При бинде сокета возвращается ошибка 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?


Код

#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;
}

Автор: Aoizora 27.11.2016, 16:10
Одну проблему решил: не хватало закрывающей скобки. Каким образом из полученных данных можно извлечь данные и распечатать, а не выводить заголовок?

Для переделывания под IPv6, так понимаю, достаточно заменить структуру IP-пакета?

Код

#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;

                local_addr.sin_family = AF_INET;
                local_addr.sin_port = htons(666);
                local_addr.sin_addr.s_addr = 0;
                if (bind(sock, (sockaddr *)&sa, sizeof(sa)) == 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("%c ", *byte_iterator);
                                        ++byte_iterator;
                                }
                        }
                        free(hdr);
                }
                
                if(WSACleanup()) { ShowError(); }
                else
                { std::cout << "WSACleanup - OK" << std::endl;}
        }
        
        return 0;
}


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)