如何捕获传入数据包?

问题描述:

我想写迷你嗅探器。问题是那些来自我的地址的数据包。目前,我只打印“源”和“目的地”地址。如何解决这个程序?对不起,我的“英语”:d感谢的如何捕获传入数据包?

Log: 

Source: 172.16.226.207 Destination: 173.194.112.78 

Source: 172.16.226.207 Destination: 23.78.81.224 

Source: 172.16.226.207 Destination: 69.171.247.29 

Source: 172.16.226.207 Destination: 173.194.71.84 

Source: 172.16.226.207 Destination: 173.194.71.94 
#include <stdio.h> 
#include <winsock2.h> 
#include <conio.h> 

#define SIO_RCVALL  0x98000001 
#define MAX_PACKET_SIZE 0x10000 

typedef struct _IPHeader 
{ 
    unsigned char verlen; 
    unsigned char tos; 
    unsigned short length; 
    unsigned short id; 
    unsigned short offset; 
    unsigned char ttl; 
    unsigned char protocol; 
    unsigned short xsum; 
    unsigned long src; 
    unsigned long dest; 
} IPHeader; 

int main(void) 
{ 
    WSADATA  wsaData; 
    SOCKET  s; 
    HOSTENT* phe; 
    SOCKADDR_IN saClient; 
    IN_ADDR  sa; 
    char  name[128]; 

    int error; 

    error = WSAStartup(MAKEWORD(2, 2), &wsaData); 
    if (error) 
    { 
     printf("WSAStartup failed with error: %d\n", error); 
     return 1; 
    } 
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) 
    { 
     printf("Could not find a usable version of Winsock.dll\n"); 
     WSACleanup(); 
     return 1; 
    } 
    else 
     printf("The Winsock 2.2 dll was found\n"); 

    s = socket(AF_INET, SOCK_RAW, IPPROTO_IP); 

    error = gethostname(name, sizeof(name)); 
    if (error) 
    { 
     printf("gethsotname function failed with error: %d\n", error); 
     WSACleanup(); 
     return 1; 
    } 
    else 
     printf("Host name: %s\n", name); 

    phe = gethostbyname(name); 

    error = WSAGetLastError(); 
    if (error) 
    { 
     printf("gethostbyname function failed with error: %d\n", error); 
     WSACleanup(); 
     return 1; 
    } 

    ZeroMemory(&saClient, sizeof(saClient)); 

    saClient.sin_family = AF_INET; 
    saClient.sin_addr.s_addr = ((struct in_addr *)phe->h_addr_list[1])->s_addr; 

    error = bind(s, (SOCKADDR *)&saClient, sizeof(SOCKADDR)); 
    if (error == SOCKET_ERROR) 
    { 
     printf("bind function failed with error: %d\n", error); 
     closesocket(s); 
     WSACleanup(); 
     return 1; 
    } 

    unsigned long flag = 1; 
    ioctlsocket(s, SIO_RCVALL, &flag); 

    // Packet processing 
    char buffer[MAX_PACKET_SIZE]; 

    printf("\n"); 

    IPHeader* hdr; 
    while (!_kbhit()) 
    { 
     error = recv(s, buffer, sizeof(buffer), 0); 
     if (error > sizeof(IPHeader)) 
     { 
      hdr = (IPHeader *)buffer; 

      sa.s_addr = hdr->src; 
      printf("Source: %s\n", inet_ntoa(sa)); 

      sa.s_addr = hdr->dest; 
      printf("Destination: %s\n\n", inet_ntoa(sa)); 
     } 
     else if (error == 0) 
      printf("Connection closed\n"); 
     else 
      printf("recv failed with error: %d\n", error); 
    } 

    closesocket(s); 
    WSACleanup(); 
    return 0; 
} 
+0

您应该使用'h_addr_list [0]'代替。并且请注意,计算机可以安装多个网络,因此,如果要监视所有地址,您必须将每个地址绑定(')一个单独的套接字,以便gethostbyname()报告。另外,'gethostbyname(gethostname)'有缺陷,所以使用'getaddrinfo()','GetAdaptersInfo()'或GetAdaptersAddresses()来获取本地IP地址。 –

+0

考虑使用[Winpcap](http://www.winpcap.org)而不是使用套接字手动监视。 –

如果我是正确的,要嗅探从远程主机传入数据包。在这种情况下,您可以看到下面的链接(对于Linux): link

您需要在混杂模式下使用接口运行程序。

+0

SIO_RCVALL启用混杂模式。 –

+0

这是对的,但我说的是启用Promisc模式的程序在链接工作整个网络:) –