#include <cstdio>
#include <iostream>
#include <cstring>
#include <winsock2.h>
#include <mstcpip.h>
#include <Windows.h>
using namespace std;
#define STATUS_FAILED 0xFFFF //异常出错代码
#define MAX_PACK_LEN 65535
#define MAX_ADDR_LEN 16
#define MAX_PROTO_TEXT_LEN 16
#define MAX_PROTO_NUM 12
#define MAX_HOSTNAME_LEN 255
#define CMD_PARAM_HELP true
#pragma comment (lib,"Ws2_32.lib")
typedef struct _iphead
{
unsigned char headLenIpVersion;
unsigned char serviceType;
unsigned short totalLength;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char protocal;
unsigned short checksum;
unsigned int sourceIp;
unsigned int destIp;
}IPHEAD,*pIPHEAD;
typedef struct _tcphead
{
USHORT sourcePort;
USHORT destPort;
UINT seqNum;
UINT ackNum;
UCHAR headLen_reserve;
UCHAR reserve_flag;
USHORT winLen;
USHORT checkSum;
USHORT mergencyPointer;
}TCPHEAD,pTCPHEAD;
typedef struct _udphead
{
USHORT sourcePort;
USHORT destPort;
USHORT totalLen;
USHORT checkSum;
}UDPHEAD,pUDPHEAD;
typedef struct _icmp
{
BYTE type;
BYTE code;
USHORT checkSum;
USHORT id;
USHORT seq;
ULONG timeStamp;
}ICMPHEAD,pICMPHEAD;
typedef struct _ProtoMap
{
int num;
char protoname[MAX_PROTO_TEXT_LEN];
}PROTOMAP;
PROTOMAP protoMap[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,""}
};
SOCKET SockRaw;
char tcpFlag[6]={'F','S','R','P','A','U'};//TCP标志位
bool ParamTcp=false; //关注TCP
bool ParamUdp=false;//关注UDP
bool ParamIcmp=false;//关注ICMP
bool ParamDecode=true;
char *strFromIpFilter=NULL;
char *strDestIpFilter=NULL;
int DecodeIpPack(char *,int );
int DecodeTcpPack(char *);
int DecodeUdpPack(char *);
int DecodeIcmpPack(char *);
void CheckSockError(int,char * );
char * CheckProtocol(int);
void usage(void);
bool GetCmdLine(int,char **);
int main(int argc,char **argv)
{
printf("%d %s %s %s %s\n",argc,argv[0],argv[1],argv[2],argv[3]);
int iErrorCode;
char RecvBuf[MAX_PACK_LEN]={0};
usage();
if(GetCmdLine(argc,argv)==CMD_PARAM_HELP)
exit(0);
WSADATA wsaData;
iErrorCode=WSAStartup(MAKEWORD(2,2),&wsaData);
CheckSockError(iErrorCode,"WSAStartup");
SockRaw=socket(AF_INET,SOCK_RAW,IPPROTO_IP);
CheckSockError(SockRaw,"socket");
//Get the ip address of my host
char FAR name[MAX_HOSTNAME_LEN];
iErrorCode=gethostname(name,MAX_HOSTNAME_LEN);
CheckSockError(iErrorCode,"gethostname");
struct hostent FAR *pHostent;
pHostent=(struct hostent *)malloc(sizeof(struct hostent));
pHostent=(struct hostent *)gethostbyname(name);
SOCKADDR_IN sa;
sa.sin_family=AF_INET;
sa.sin_port=htons(6000);
memcpy(&sa.sin_addr.S_un.S_addr,pHostent->h_addr_list[0],pHostent->h_length);
iErrorCode=bind(SockRaw,(SOCKADDR *)&sa,sizeof(SOCKADDR_IN));
CheckSockError(iErrorCode,"bind");
DWORD dwBufferLen[10];
DWORD dwBufferInLen=1;
DWORD dwBufferReturned=0;
iErrorCode=WSAIoctl(
SockRaw,
SIO_RCVALL,
&dwBufferInLen,
sizeof(dwBufferInLen),
&dwBufferLen,
sizeof(dwBufferLen),
&dwBufferReturned,
NULL,
NULL
);
printf("%d",WSAGetLastError());
if(WSAGetLastError()==WSAEINVAL)
cout<<"参数不合法"<<endl;
CheckSockError(iErrorCode,"WSAloctl");
while(1)
{
memset(RecvBuf,0,sizeof(RecvBuf));
iErrorCode=recv(SockRaw,RecvBuf,sizeof(RecvBuf),0);
CheckSockError(iErrorCode,"recv");
iErrorCode=DecodeIpPack(RecvBuf,iErrorCode);
CheckSockError(iErrorCode,"DecodeIpPack");
}
return 0;
}
char *CheckProtocal(int iProtocal)
{
int i=0;
for(;i<MAX_PROTO_NUM;i++)
{
if(protoMap[i].num==iProtocal)
return protoMap[i].protoname;
}
return "";
}
int DecodeIpPack(char *buf,int iBufSize)
{
IPHEAD *pIpHead;
int iProtocal,iTTL;
char szProtocal[MAX_PROTO_TEXT_LEN];
char szSourceIp[MAX_ADDR_LEN],szDestIp[MAX_ADDR_LEN];
SOCKADDR_IN source,dest;
pIpHead=(IPHEAD *)buf;
//协议识别程序,如果程序中没有指定ip协议中的几个上层协议,则退出
iProtocal=pIpHead->protocal;
strncpy(szProtocal,CheckProtocal(iProtocal),MAX_PROTO_TEXT_LEN);
if(iProtocal==IPPROTO_TCP&&!ParamTcp)
return true;
if(iProtocal==IPPROTO_UDP&&!ParamUdp)
return true;
if(iProtocal==IPPROTO_ICMP&&!ParamIcmp)
return true;
source.sin_addr.S_un.S_addr=pIpHead->sourceIp;
strncpy(szSourceIp,inet_ntoa(source.sin_addr),MAX_ADDR_LEN);
if(strFromIpFilter)
if(strcmp(szSourceIp,strFromIpFilter))
return true;
dest.sin_addr.S_un.S_addr=pIpHead->destIp;
strncpy(szDestIp,inet_ntoa(dest.sin_addr),MAX_ADDR_LEN);
if(strDestIpFilter)
if(strcmp(szDestIp,strDestIpFilter))
return true;
iTTL=pIpHead->ttl;
printf("%s:",szProtocal);
printf("%s-->%s\n",szSourceIp,szDestIp);
printf(" BYTES is %d,TTL is %d\n",iBufSize,iTTL);
//计算IP数据包头部长度
int iIpHeadLen=sizeof(ULONG)*(pIpHead->headLenIpVersion&0x0F);
//解码上层协议信息
switch (iProtocal)
{
case IPPROTO_TCP:
DecodeTcpPack(buf+iIpHeadLen);
break;
case IPPROTO_UDP:
DecodeUdpPack(buf+iIpHeadLen);
break;
case IPPROTO_ICMP:
DecodeIcmpPack(buf+iIpHeadLen);
break;
default:
break;
}
return true;
}
int DecodeTcpPack( char *TcpPack )
{
TCPHEAD *pTcpHead;
pTcpHead=(TCPHEAD *)TcpPack;
printf(" tcp port %d-->tcp port %d\n",ntohs(pTcpHead->sourcePort),ntohs(pTcpHead->destPort));
UCHAR mask=1;
for(int i=0;i<6;i++)
{
if(pTcpHead->reserve_flag&mask)
printf("%c",tcpFlag[i]);
else
printf("-");
mask=mask<<1;
}
printf("\n");
return true;
}
int DecodeUdpPack( char *UdpPack )
{
UDPHEAD *pUdpHead;
pUdpHead=(UDPHEAD *)UdpPack;
printf("udp port %d--> udp port %d\n",ntohs(pUdpHead->sourcePort),ntohs(pUdpHead->destPort));
printf(" Udp len -->%d\n",ntohs( pUdpHead->totalLen ));
printf("\n");
return true;
}
int DecodeIcmpPack(char *IcmpPack)
{
ICMPHEAD *pIcmpHead;
pIcmpHead=(ICMPHEAD *)IcmpPack;
printf("Type %d %d",pIcmpHead->type,pIcmpHead->code);
printf("ID = %d, SEQ=%d\n",pIcmpHead->id,pIcmpHead->seq);
return true;
}
void CheckSockError(int iErrorCode,char *pErrorMsg)
{
if(iErrorCode==SOCKET_ERROR)
{
printf("%s Error: %s",pErrorMsg,GetLastError());
closesocket(SockRaw);
exit(0);
}
}
bool GetCmdLine(int argc,char **argv)
{
cout<<"参数有四个"<<endl;
if(argc<2)
return CMD_PARAM_HELP;
for(int i=1;i<argc;i++)
{
if(argv[i][0]!='/')
return CMD_PARAM_HELP;
else
switch(argv[i][1])
{
case 't':
case 'T': ParamTcp=true; break;
case 'u':
case 'U': ParamUdp=true; break;
case 'i':
case 'I': ParamIcmp=true; break;
case 'p':
case 'P': ParamDecode=true; break;
case 'f':
case 'F':
{
strFromIpFilter=(char *)malloc(sizeof(char));
memset(strFromIpFilter,0,sizeof(char)*16);
strcpy(strFromIpFilter,argv[i]+3);
break;
}
case 'd':
case 'D':
{
strFromIpFilter=(char *)malloc(sizeof(char));
memset(strFromIpFilter,0,sizeof(char)*16);
strcpy(strFromIpFilter,argv[i]+3);
break;
}
}
}
cout<<"\nNow I Will Sniff"<<endl;
if(ParamTcp)
cout<<"TCP"<<endl;
if(ParamUdp)
cout<<"UDP"<<endl;
if(ParamIcmp)
cout<<"ICMP"<<endl;
if(strFromIpFilter)
cout<<"From Ip:%s"<<strFromIpFilter<<endl;
if(strDestIpFilter)
cout<<"Dest Ip:%s"<<strDestIpFilter<<endl;
return false;
}
void usage()
{
cout<<"sniffer program!"<<endl;
cout<<"/t output tcp pakets!"<<endl;
cout<<"/u output udp pakets!"<<endl;
cout<<"/i output icmp pakets!"<<endl;
cout<<"/p Decode pakets!"<<endl;
cout<<"/f output packet from IP"<<endl;
cout<<"/d output packet dest IP"<<endl;
}
经验1 如果编译后很多错误,一般是windows.h位置不对,要放入头文件包含的最后面
经验2 注意参数····socket函数的三个参数··不要写成SOCK_STREAM