В неразборчивом режиме recv не принимает ничего

 
0
 
C++
ava
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 ничего не читает из сокета, и в буфере остается мусор. Что я делаю не так?
Kommentare (2)
ava
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;
}
ava
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;
}

Registrieren Sie sich oder melden Sie sich an, um schreiben zu können.
Unternehmen des Tages
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Mitwirkende
  Aoizora
advanced
Absenden