需要帮助使用 Windows 套接字查看所有传入的数据包

Posted

技术标签:

【中文标题】需要帮助使用 Windows 套接字查看所有传入的数据包【英文标题】:need help using windows sockets to view all incoming packets 【发布时间】:2014-04-29 15:52:13 【问题描述】:

我正在尝试创建一个程序,该程序可以接收和显示所有传入家庭网络的数据包。这只是一个“好玩”的项目,因为我正在努力更好地使用计算机网络。

我找到了一些关于使用套接字的教程,我正在尝试模仿他们正在做的事情。 (目前正在使用this(初始化内容来自this)教程)。

但是,我在使代码正常工作时遇到了一些问题。这是我到目前为止的代码:(因为我知道我只会在 windows 上使用它,所以我只是省略了 mac 和 unix 的其他 marcos)

#define PLATFORM_WINDOWS 1

#if defined(_WIN32)
#define PLATFORM PLATFORM_WINDOWS
#endif

#if PLATFORM == PLATFORM_WINDOWS
#include <WinSock2.h>
#endif

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

#include <iostream>

bool InitializeSockets()

#if PLATFORM == PLATFORM_WINDOWS
    WSADATA WsaData;
    return WSAStartup( MAKEWORD(2,2), &WsaData);
#else
    return true;
#endif



void ShutdownSockets()

#if PLATFORM == PLATFORM_WINDOWS
    WSACleanup();
#endif


void printIpPacket(unsigned char* data, int length)

    printf("-----------------Packet Begins-----------------\n");
    printf("IP Version: %i, Packet Size: %ibytes, Id: %i\n",
        (data[0]>>4), (data[2]*256)+data[3], (data[4]*256)+data[5]);

    printf("Fragment: %i, TTL: %i, HL: %iwds, Protocol: %i\n",
        ((int)(data[6]>>4)*256)+data[7], data[8], ((char)(data[0]<<4))>>4, data[9]);

    printf("Source: %i.%i.%i.%i, Destination: %i.%i.%i.%i\n",
        data[12], data[13], data[14], data[15],
        data[16], data[17], data[18], data[19]);

    //the data inside the packet starts at --> data+(((char)(data[0]<<4))>>2)
    //new data length --> length-(((char)(data[0]<<4))>>2)
    //continue printing the rest of the headers :o  

    printf("\n------------------Packet Ends------------------\n");  


int main()

    InitializeSockets();

    int thisSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

    int optVal = 1;
    setsockopt(thisSocket, IPPROTO_IP, 2, (char *)&optVal, sizeof(optVal));

    int inn = 1, outt;
    long rett;
    int err = WSAIoctl(thisSocket, 0x98000001, &inn, sizeof(inn), &outt, sizeof(outt), &rett, 0, 0);
    int a = WSAGetLastError();

我在使WSAIoctl 函数工作时遇到了一些问题。本教程声称可以工作的代码甚至无法编译。我得到了错误:

error C2664: 'WSAIoctl' : cannot convert parameter 7 from 'long *' to 'LPDWORD'

然后,我将 WSAIoctl 函数行更改为:

int err = WSAIoctl(thisSocket, 0x98000001, &inn, sizeof(inn), &outt, sizeof(outt), (LPDWORD)&rett, 0, 0);

这已编译,但随后 WSAGetLastError() 返回错误代码 10022,根据 this 表示无效参数。

然后我想,“好吧,与其试图强制将错误的类型转换为正确的类型,我想我应该只传递正确的类型。”

然后我创建了一个变量

LPDWORD rett = new DWORD;

这样做,我编译成功,但我再次收到错误代码 10022。

在这一点上,我不知道还能做什么。有人可以帮我让这个程序运行吗?

【问题讨论】:

关于你的变量,改变 variable 的类型有什么问题吗? :DWORD rett = 0;,然后像以前一样通过&amp;rett?关于你的错误。关于您的错误,如果您要使用SIO_RCVALL 嗅探数据包,则套接字应该是SOCK_RAW,而不是SOCK_STREAM。我意识到documentation for WSAIoctl 很广泛,但功能本身的力量也是如此。拥有强大的力量......无论如何,祝你好运。 所以我创建了 DWORD 并按照您所说的传递了它的地址,现在我收到错误代码 10038:Socket operation on nonsocket. An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid. 确保thisSocket创建成功。我想你使用了 SOCK_RAW。您需要提升权限才能执行此操作。 @user58697 啊,检查套接字创建的错误,我收到错误 10013,意味着我没有正确设置权限。我的机器上当前没有运行任何防病毒/防火墙。还有什么我可以尝试解决的吗? @xcdemon05:你需要使用SOCK_RAW来进行数据包捕获,但是正如user58697所说,SOCK_RAW需要管理员权限,并且是documented这样:“原始套接字提供了以下能力操纵底层传输,因此它们可用于构成安全威胁的恶意目的。因此,只有管理员组的成员才能在 Windows 2000 及更高版本上创建 SOCK_RAW 类型的套接字。 【参考方案1】:

试试这样的:

#define PLATFORM_WINDOWS 1

#if defined(_WIN32)
#define PLATFORM PLATFORM_WINDOWS
#endif

#if PLATFORM == PLATFORM_WINDOWS
#include <WinSock2.h>
#endif

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

#include <iostream>

bool InitializeSockets()

#if PLATFORM == PLATFORM_WINDOWS
    WSADATA WsaData;
    int a = WSAStartup( MAKEWORD(2,2), &WsaData);
    if (a != 0)
    
        printf("WSAStartup() failed. Error %d\n", a);
        return false;
    
#endif
    return true;


void ShutdownSockets()

#if PLATFORM == PLATFORM_WINDOWS
    WSACleanup();
#endif


#if PLATFORM != PLATFORM_WINDOWS
void closesocket(int socket)

    close(socket);

#endif

int GetLastSocketError()

#if PLATFORM == PLATFORM_WINDOWS
    return WSAGetLastError();
#else
    return errno;
#endif


int main()

    if (!InitializeSockets())
        return -1;

    int thisSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    if (thisSocket == -1)
    
        printf("socket() failed. Error %d\n", GetLastSocketError());
        ShutdownSockets();
        return -1;
    

    sockaddr_in bindaddr = 0;
    bindaddr.sin_family = AF_INET;
    // set bindaddr.sin_addr.s_addr to the desired local IP that you want to sniff from...

    if (bind(thisSocket, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) == -1)
    
        printf("bind() failed. Error %d\n", GetLastSocketError());
        closesocket(thisSocket);
        ShutdownSockets();
        return -1;
    

    u_long optVal = 1;
    if (setsockopt(thisSocket, IPPROTO_IP, IP_HDRINCL, (char *)&optVal, sizeof(optVal)) == -1)
    
        printf("setsockopt() failed. Error %d\n", GetLastSocketError());
        closesocket(thisSocket);
        ShutdownSockets();
        return -1;
    

#if PLATFORM == PLATFORM_WINDOWS    
    DWORD inn = RCVALL_ON;
    if (WSAIoctl(thisSocket, SIO_RCVALL, &inn, sizeof(inn), NULL, 0, NULL, NULL, NULL) == -1)
    
        printf("WSAIoctl() failed. Error %d\n", GetLastSocketError());
        closesocket(thisSocket);
        ShutdownSockets();
        return -1;
    
#endif

    u_char Buffer[0xffff];

    while(1)
    
        int len = recvfrom(thisSocket, (char*)Buffer, sizeof(Buffer), NULL, 0, 0);
        if (len == -1)
        
            printf("recvfrom() failed. Error %d\n", GetLastSocketError());
            closesocket(thisSocket);
            ShutdownSockets();
            return -1;
        

        printIpPacket(Buffer, len);
    

    closesocket(thisSocket);
    ShutdownSockets();

    return 0;

【讨论】:

它没有编译 :( VS 无法识别一些 MACROS,包括 SIO_RCVALL、IP_HDRINCL 和 RCVALL_ON。还收到一些关于 recvfrom 无法从 u_char 转换 par 2 的编译错误[65535] 到 char*,但这似乎没什么大不了的。 你需要#include相关的头文件,如Mstcpip.hWs2tcpip.hwinsock2.h。下次遇到有关未知符号的错误时,请阅读相关的 MSDN 文档。

以上是关于需要帮助使用 Windows 套接字查看所有传入的数据包的主要内容,如果未能解决你的问题,请参考以下文章

Windows 上是不是有 Unix 域套接字模拟?

套接字上的内存泄漏

通用 Windows 上的 UDP 套接字未接收数据

C ++套接字不接收传入数据包,在Python中工作

当目前没有 wsarecv 时,传入数据会发生啥

TCP over Bluetooth(Windows 套接字)