吴炜文311351课设报告.docx
《吴炜文311351课设报告.docx》由会员分享,可在线阅读,更多相关《吴炜文311351课设报告.docx(23页珍藏版)》请在冰点文库上搜索。
![吴炜文311351课设报告.docx](https://file1.bingdoc.com/fileroot1/2023-6/22/9de0b064-8479-4f78-8edd-86c1f5b5b02e/9de0b064-8479-4f78-8edd-86c1f5b5b02e1.gif)
吴炜文311351课设报告
网络应用编程
项目名称网络嗅探器
学生学院计算机学院
专业班级网络工程12
(1)班
学号3112006351
学生姓名吴炜文
指导教师孙为军
2015年06月24日
目录
一、设计题目--------------------------------------2
二、开发环境-------------------------------------2
三、功能简介-------------------------------------2
四、设计思想-------------------------------------2
1.网络嗅探器的原理------------------------2
2.设计原理--------------------------------3
五、详细设计与实现---------------------------------5
1.方案设计--------------------------------5
2.代码清单--------------------------------5
六、运行测试-------------------------------------17
一.设计题目
编程实现简单的网络嗅探器——协议分析
二.开发环境
1.操作系统:
WindowsXP
2.开发平台:
MicrosoftVisualStudio2010
3.开发语言:
C语言
三.功能简介
1.原始套接字与网卡邦定,并接收流经网卡的所有数据包;
2.对数据包进行分析以获得源IP地址和目的IP地址;
3.对数据包进行分析以获得运输层协议类型、源端口号和目的端口号;
4.对数据包进行分析以获得数据包的长度;
5.在DOS环境下显示分析结果;
四.设计思想
1.网络嗅探器的原理
SNIFF,就是嗅探器,窃听器,它工作在网络的底层,在网络上监听数据包来获取敏感信息。
从原理上来说,在一个实际的系统中,数据的收发是由网卡来完成的,网卡接收到传输来的数据,网卡内的单片程序接收数据帧的目的MAC地址,根据计算机上的网卡驱动程序设置的接收模式判断该不该接收,认为该接收就接收后产生中断信号通知CPU,认为不该接收就丢掉不管,所以不该接收的数据网卡就截断了,计算机根本就不知道。
对于网卡来说一般有四种接收模式:
a)广播方式:
该模式下的网卡能够接收网络中的广播信息。
b)组播方式:
设置在该模式下的网卡能够接收组播数据。
c)直接方式:
在这种模式下,只有目的网卡才能接收该数据。
d)混杂模式:
在这种模式下的网卡能够接收一切通过它的数据,而不管该数据是否是传给它的。
而嗅探程序是一种利用以太网的特性把网络适配卡(NIC,一般为以太网卡)置为混杂模式状态的工具。
总结一下,首先,在以太网中是基于广播方式传送数据的,也就是说,所有的物理信号都要经过我的机器。
其次,网卡可以置于一种模式叫混杂模式(promiscuous),在这种模式下工作的网卡能够接收到一切通过它的数据,而不管实际上数据的目的地址是不是它。
这就是SNIFF工作的基本原理:
让网卡接收一切他所能接收的数据。
2.设计原理
具体到编程实现上,这种对网卡混杂模式的设置是通过原始套接字(rawsocket)来实现的,这也有别于通常经常使用的数据流套接字和数据报套接字。
在创建了原始套接字后,需要通过setsockopt()函数来设置IP头操作选项,然后再通过bind()函数将原始套接字绑定到本地网卡。
为了让原始套接字能接受所有的数据,还需要通过ioctlsocket()来进行设置,对数据包的获取仍象流式套接字或数据报套接字那样通过recv()函数来完成。
但是与其他两种套接字不同的是,原始套接字此时捕获到的数据包并不仅仅是单纯的数据信息,而是包含有IP头、TCP头等信息头的最原始的数据信息,这些信息保留了它在网络传输时的原貌。
通过对这些在低层传输的原始信息的分析可以得到有关网络的一些信息。
由于这些数据经过了网络层和传输层的打包,因此需要根据其附加的帧头对数据包进行分析。
下面先给出结构.数据包的总体结构:
①IP数据报的格式
②ICMP报文的格式
③UDP的首部格式
④TCP报文段的首部格式
⑤套接字socket=(IP地址:
端口号)
五.详细设计与实现
1.方案设计
数据包捕获流程图:
2.代码清单
#include
#include
#include
#include
#include
#include
#pragmacomment(lib,"ws2_32.lib")
#defineSIO_RCVALL_WSAIOW(IOC_VENDOR,1)
#defineMAX_PACK_LEN65535//最大包长度
#defineMAX_ADDR_LEN16//最大地址长度
#defineMAX_PROTO_TEXT_LEN16//子协议名称最大长度
#defineMAX_PROTO_NUM12//子协议数量
#defineMAX_HOSTNAME_LEN255//最大主机名长度
//定义IP首部格式
typedefstruct_IPHeader
{
unsignedcharh_verlen;//版本和首部长度
unsignedchartos;//服务类型
unsignedshorttotal_len;//总长度
unsignedshortident;//标识号
unsignedshortfrag_and_flags;//段偏移量
unsignedcharttl;//生存时间
unsignedcharproto;//协议
unsignedshortchecksum;//首部校验和
unsignedintsourceIP;//源IP地址
unsignedintdestIP;//目的地址
}IPHEADER;
//定义TCP首部格式
typedefstruct_TCPHeader
{
unsignedshortth_sport;//源端口号
unsignedshortth_dport;//目的端口号
unsignedintth_seq;//SEQ序号
unsignedintth_ack;//ACK序号
unsignedcharth_lenres;//首部长度
unsignedcharth_flag;//控制位
unsignedshortth_win;//窗口大小
unsignedshortth_sum;//校验和
unsignedshortth_urp;//紧急指针
}TCPHEADER;
//定义UDP首部格式
typedefstruct_UDPHeader
{
unsignedshortuh_sport;//16位源端口
unsignedshortuh_dport;//16位目的端口
unsignedshortuh_len;//16位长度
unsignedshortuh_sum;//16位校验和
}UDPHEADER;
//定义ICMP首部格式
typedefstruct_ICMPHeader
{
BYTEi_type;//8位类型
BYTEi_code;//8位代码
unsignedshorti_cksum;//16位校验和
unsignedshorti_id;//识别号
unsignedshorti_seq;//报文序列号
unsignedlongtimestamp;//时间戳
}ICMPHEADER;
//----------------------------------------------------------------------------------------------
//定义子协议映射表
typedefstruct_protomap
{
intProtoNum;
charProtoText[MAX_PROTO_TEXT_LEN];
}PROTOMAP;
//为子协议映射表赋值
PROTOMAPProtoMap[MAX_PROTO_NUM]={
{IPPROTO_IP,"IP"},
{IPPROTO_ICMP,"ICMP"},
{IPPROTO_IGMP,"IGMP"},
{IPPROTO_GGP,"GGP"},
{IPPROTO_TCP,"TCP"},
{IPPROTO_PUP,"PUP"},
{IPPROTO_UDP,"UDP"},
{IPPROTO_IDP,"IDP"},
{IPPROTO_ND,"ND"},
{IPPROTO_RAW,"RAW"},
{IPPROTO_MAX,"MAX"},
{NULL,""}
};
SOCKETSockRaw;//全局套接字
charTcpFlag[6]={'F','S','R','P','A','U'};//TCP标志位
boolparamAll=false;//嗅探所有的数据包
boolparamTcp=false;//嗅探TCP数据包
boolparamUdp=false;//嗅探UDP数据包
boolparamIcmp=false;//嗅探ICMP数据包
intpacket_totallen=0;//数据包总长度
charparamHostAddr_A[20];//嗅探的主机A
charparamHostAddr_B[20];//嗅探的主机B
charkeyword[100];//嗅探的关键信息
//IP数据包解析函数
intDecodeIpPack(char*);
//TCP数据包解析函数
intDecodeTcpPack(char*);
//UDP数据包解析函数
intDecodeUdpPack(char*);
//ICMP数据包解析函数
intDecodeIcmpPack(char*);
//显示数据包信息
voidShowPackInfo(char*buf,intiProtocol,char*szSoueceIP,char*szDestIP,char*szProtocol);
//显示子协议数据包函数
voidShowSubPackInfo(char*,int);
//错误检测函数
voidCheckSockError(int,char*);
//协议检测函数
char*CheckProtocol(int);
//设置嗅探器参数函数
boolSetSnifferParam();
//-----------------------------------------------------------------------------------------------------
//SOCK错误处理函数
voidCheckSockError(intiErrorCode,char*pErrorMsg)
{
if(iErrorCode==SOCKET_ERROR)
{
printf("%s出错了:
%d",pErrorMsg,GetLastError());
closesocket(SockRaw);
exit(0);
}
}
//------------------------------------------------------------------------------------------------------
//协议识别函数
char*CheckProtocol(intiProtocol)
{
for(inti=0;i{
//如果找到对应的子协议,则返回名称
if(ProtoMap[i].ProtoNum==iProtocol)
{
returnProtoMap[i].ProtoText;
}
}
return"";
}
//---------------------------------------------------------------------------------------------------------
//TCP解包函数
intDecodeTcpPack(char*TcpBuf)
{
TCPHEADER*pTcpHeader;
chardata[MAX_PACK_LEN];
inti;
//转换成TCP首部格式
pTcpHeader=(TCPHEADER*)TcpBuf;
//输出源端口和目的端口
printf("端口:
%d-->%d",ntohs(pTcpHeader->th_sport),ntohs(pTcpHeader->th_dport));
unsignedcharFlagMask=1;
//输出标志位
//printf("标志位:
");
for(i=0;i<6;i++)
{
if((pTcpHeader->th_flag)&FlagMask)
{
printf("标志位:
%c",TcpFlag[i]);
}
else
{
printf("-");
}
FlagMask=FlagMask<<1;
}
printf("\n");
//求数据段长度
inttotalheadlen=sizeof(IPHEADER)+sizeof(TCPHEADER);
inttcpheadlen=sizeof(TCPHEADER);
memcpy(data,TcpBuf+tcpheadlen,packet_totallen-totalheadlen);
returntrue;
}
//-------------------------------------------------------------------------------------------------------------
//UDP解包函数
intDecodeUdpPack(char*UdpBuf)
{
UDPHEADER*pUdpHeader;
chardata[MAX_PACK_LEN];
pUdpHeader=(UDPHEADER*)UdpBuf;
//输出端口和数据长度
printf("端口号:
%d-->%d",ntohs(pUdpHeader->uh_sport),ntohs(pUdpHeader->uh_dport));
printf("长度:
%d\n",ntohs(pUdpHeader->uh_len));
inttotalheadlen=sizeof(IPHEADER)+sizeof(UDPHEADER);
intudpheadlen=sizeof(UDPHEADER);
memcpy(data,UdpBuf+udpheadlen,packet_totallen-totalheadlen);
returntrue;
}
//---------------------------------------------------------------------------------------------------------------------
//ICMP解包函数
intDecodeIcmpPack(char*IcmpBuf)
{
ICMPHEADER*pIcmpHeader;
pIcmpHeader=(ICMPHEADER*)IcmpBuf;
//输出ICMP数据包类型、ID和SEQ
printf("Type:
%d,%d",pIcmpHeader->i_type,pIcmpHeader->i_code);
printf("ID=%dSEQ=%d\n",pIcmpHeader->i_id,pIcmpHeader->i_seq);
returntrue;
}
//-----------------------------------------------------------------------------------------------------------------------
//根据过滤条件显示数据包信息
voidShowPackInfo(char*buf,intiProtocol,char*szSoueceIP,char*szDestIP,char*szProtocol)
{
//如果设置了主机B的IP,没有设置主机A的IP
if((!
strcmp(paramHostAddr_A,"all"))&&(strcmp(paramHostAddr_B,"all")))
{
if((!
strcmp(paramHostAddr_B,szSoueceIP))
||(!
strcmp(paramHostAddr_B,szDestIP)))
{
printf("-------------------------------------------------------------------------------\n");
printf("|协议|源IP地址|目的IP地址|");
printf("------------------------------------------------------------------------------\n");
printf("\n|%s|",szProtocol);
printf("%s|%s|",szSoueceIP,szDestIP);
//显示子协议数据包相关信息
ShowSubPackInfo(buf,iProtocol);
}
}
//如果设置主机A的IP,没有设置主机B的IP
elseif((strcmp(paramHostAddr_A,"all"))&&(!
strcmp(paramHostAddr_B,"all")))
{
if((!
strcmp(paramHostAddr_A,szSoueceIP))
||(!
strcmp(paramHostAddr_A,szDestIP)))
{
printf("-------------------------------------------------------------------------------\n");
printf("|协议|源IP地址|目的IP地址|\n");
printf("------------------------------------------------------------------------------");
printf("\n|%s|",szProtocol);
printf("%s|%s|",szSoueceIP,szDestIP);
ShowSubPackInfo(buf,iProtocol);
}
}
//如果主机A和B的IP都进行了设置
elseif((strcmp(paramHostAddr_A,"all"))&&(strcmp(paramHostAddr_B,"all")))
{
if((!
strcmp(paramHostAddr_A,szSoueceIP)
&&!
strcmp(paramHostAddr_B,szDestIP))
||(!
strcmp(paramHostAddr_B,szSoueceIP)
&&!
strcmp(paramHostAddr_A,szDestIP)))
{
printf("-------------------------------------------------------------------------------\n");
printf("|协议|源IP地址|目的IP地址|\n");
printf("------------------------------------------------------------------------------");
printf("\n|%s|",szProtocol);
printf("%s|%s|",szSoueceIP,szDestIP);
ShowSubPackInfo(buf,iProtocol);
}
}
//如果主机A和B的IP都没有进行设置
else
{
printf("-------------------------------------------------------------------------------\n");
printf("|协议|源IP地址|目的IP地址|\n");
printf("------------------------------------------------------------------------------");
printf("\n|%s|",szProtocol);
printf("%s|%s|",szSoueceIP,szDestIP);
ShowSubPackInfo(buf,iProtocol);
}
}
//-----------------------------------------------------------------------------------------------------------------------
//显示子协议数据包信息
voidShowSubPackInfo(char*buf,intiProtocol)
{
switch(iProtocol)
{
ca