|
截获流经本机网卡的IP数据包(2) WORD DstPort; // 目的端口 DWORD SeqNum; // 顺序号 DWORD AckNum; // 确认号 BYTE DataOff; // TCP头长 BYTE Flags; // 标志(URG、ACK等) WORD Window; // 窗口大小 WORD Chksum; // 校验和 WORD UrgPtr; // 紧急指针 } TCP; typedef TCP *LPTCP; typedef TCP UNALIGNED * ULPTCP; 在网络层,还要给TCP数据包添加一个IP数据段头以组成IP数据报。IP数据头以大端点机次序传送,从左到右,版本字段的高位字节先传输(SPARC是大端点机;Pentium是小端点机)。如果是小端点机,就要在发送和接收时先行转换然后才能进行传输。IP数据段头格式如下: 16位 16位 版本 IHL 服务类型 总长 标识 标志 分段偏移 生命期 协议 头校验和 源地址 目的地址 选项(0或更多) 同样,在实际编程中也需要通过一个数据结构来表示此IP数据段头,下面给出此数据结构的定义: typedef struct _IP{ union{ BYTE Version; // 版本 BYTE HdrLen; // IHL }; BYTE ServiceType; // 服务类型 WORD TotalLen; // 总长 WORD ID; // 标识 union{ WORD Flags; // 标志 WORD FragOff; // 分段偏移 }; BYTE TimeToLive; // 生命期 BYTE Protocol; // 协议 WORD HdrChksum; // 头校验和 DWORD SrcAddr; // 源地址 DWORD DstAddr; // 目的地址 BYTE Options; // 选项 } IP; typedef IP * LPIP; typedef IP UNALIGNED * ULPIP; 在明确了以上几个数据段头的组成结构后,就可以对捕获到的数据包进行分析了。 嗅探器的具体实现 根据前面的设计思路,不难写出网络嗅探器的实现代码,下面就给出一个简单的示例,该示例可以捕获到所有经过本地网卡的数据包,并可从中分析出协议、IP源地址、IP目标地址、TCP源端口号、TCP目标端口号以及数据包长度等信息。由于前面已经将程序的设计流程讲述的比较清楚了,因此这里就不在赘述了,下面就结合注释对程序的具体是实现进行讲解,同时为程序流程的清晰起见,去掉了错误检查等保护性代码。主要代码实现清单为: // 检查 Winsock 版本号,WSAData为WSADATA结构对象 WSAStartup(MAKEWORD(2, 2), &WSAData); // 创建原始套接字 sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW));
|