数据包嗅探器只检测发送的数据包

Packet sniffer only detects sent packets

本文关键字:数据包 检测 嗅探器      更新时间:2023-10-16

我一直在开发一个数据包嗅探器,只是为了好玩/教育,它进展得很顺利。我遇到的问题是,recvfrom()中出现的唯一数据包是SENT数据包,即以我的IP作为源IP的数据包,而不是我的WAN IP,而是我的LAN IP(如果有意义的话)。我试着修复它,花了几个小时阅读我能找到的所有东西,但对我来说似乎没有解决方案。我100%肯定我写的代码没有检测到所有的数据包,因为wireshark检测到更多的数据包(传入和传出),很明显,我的电脑不仅仅有传出流量。

packetsize = recvfrom(sniffer , Buffer , 65536 , 0 , (SOCKADDR *)&SenderAddr , &SenderAddrSize); 
for (int x = 12; x < 16; x++) 
{
    printf("%c ",Buffer[x]); 
}
std::cout << "n";
iphdr = (IPV4_HDR *)Buffer;
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iphdr->ip_srcaddr;
std::cout << inet_ntoa(source.sin_addr) << "nn";

这就是一切失败的地方(还有更多的代码,但并不重要),结构都定义正确,所以没有错误(否则我不可能在每个数据包中一遍又一遍地获得相同的IP地址)。此外,我的网络中还有另一个不存在的IP显示为源IP,偶尔源IP是0.0.0.0,我都觉得很奇怪。

缓冲区被声明为

char *Buffer = (char *)malloc(65536);

所以它是有符号的char,我不知道如何从这些值中手动"提取"标头的单独部分。

我希望任何人都能向我解释,recvfrom实际上没有丢失数据包,我做错了什么。此外,我想知道如何解释recvfrom的输出,即将有符号转换为无符号,或者其他方式?

我希望我把我的问题说清楚了,提前谢谢。

编辑我的代码中更大的一块

int main()
{
    SOCKET sniffer;
    struct in_addr addr;
    int in;
    char hostname[100];
    struct hostent *local;
    WSADATA wsa;

    // Initialise Winsock
    printf("nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
    {
        printf("WSAStartup() failed.n");
        getchar();
        return 1;
    }
    printf("Initialised");
    // Create a RAW Socket
    printf("nCreating RAW Socket....");
    sniffer = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    if (sniffer == INVALID_SOCKET)
    {
        printf("Failed to create raw socket.n");
        printf("WSA throws error code %dn",WSAGetLastError());
        printf("Run as admin to fixn");
        getchar();
        return 1;
    }
    printf("Created.");
    // Retrieve the local hostname
    if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR)
    {
        printf("WSA throws error code %dn",WSAGetLastError());
        getchar();
        return 1;
    }
    printf("nHost name : %s n",hostname);
    bool retry = true;
    signed int maxnumber = -1;
    do
    {
        // Retrieve the available IPs of the local host
        local = gethostbyname(hostname);
        printf("nAvailable Network Interfaces  n");
        if (local == NULL)
        {
            printf("WSA throws error code %d.n",WSAGetLastError());
            getchar();
            return 1;
        }
        // Available interfaces
        for (i = 0; local->h_addr_list[i] != 0; i++) // h_addr_list is null terminated
        {
            // local is hostent struct in which information about the host is stored
            // in_addr represents an IPv4 internet address. inet_ntoa: in_addr to string (ip adress)
            memmove(&addr, local->h_addr_list[i], sizeof(struct in_addr));
            //memmove(destination, source, number of bytes to copy)
            printf("Interface Number : %d Address : %sn", i, inet_ntoa(addr));
            maxnumber = i;
            printf("n");
        }
        // Choose interface
        if (maxnumber > 0)
        {
            printf("Enter the interface number you would like to sniff : ");
            scanf("%d",&in);
            printf(" in: %d | maxnumber: %d n", in, maxnumber);
            if (in <= maxnumber)
            {
                retry = false;
            } else {
                printf("Interface number %d with adress %d does not exist nn", in, local->h_addr_list[in]);
            }
        }
        else
        {
            printf("Only one interface available");
            in = 0;
            retry = false;
        }
    } while (retry);
    self = addr;
    CreateFolder(self);
    memset(&dest, 0, sizeof(dest));
    memcpy(&dest.sin_addr.s_addr,local->h_addr_list[in],sizeof(dest.sin_addr.s_addr));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(source.sin_port);//=0;
    printf("nBinding socket to local system and port 0 ...");
    if (bind(sniffer,(struct sockaddr *)&dest,sizeof(dest)) == SOCKET_ERROR)
    {
        printf("bind(%s) failed.n", inet_ntoa(addr));
        getchar();
        return 1;
    }
    printf("Binding successful");
    j=1;
    unsigned long nbytesret;
    printf("nSetting socket to sniff...");
    if (WSAIoctl(sniffer, SIO_RCVALL, &j, sizeof(j), 0, 0, &nbytesret , 0 , 0) == SOCKET_ERROR)
    {
        printf("WSAIoctl() failed.n");
        getchar();
        return 1;
    }
    printf("Socket setn");
    printf("Press enter to startn");
    getchar();
    printf("Packet Capture Statistics...n");
    StartSniffing(sniffer); 
    printf("Ending sniffer, press enter to exit n");
    getchar();
    closesocket(sniffer);
    WSACleanup();
    return 0;
}
void StartSniffing(SOCKET sniffer)
{
    char *Buffer = (char *)malloc(65536);
    int packetsize;
    if (Buffer == NULL)
    {
        printf("malloc() failed.n");
    getchar();
    return;
    }
    do
    {
        packetsize = recvfrom(sniffer , Buffer , 65536 , 0 , (SOCKADDR *)&SenderAddr , &SenderAddrSize); 
        if(packetsize > 0)
        {
            ProcessPacket(Buffer, packetsize);
        }
        else
        {
            printf( "recvfrom() failed.n");
            getchar();
        }
    }
    while (packetsize > 0);
    free(Buffer);
}

要以无符号形式从缓冲区读取,请使用类似的reinterpret_cast来获得无符号指针:

unsigned char *uBuffer = reinterpret_cast<unsigned char *>(Buffer);