// capture.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream"
#include "winsock2.h"
#include "mstcpip.h"
#pragma comment(lib,"WS2_32")
using namespace std;
void DecodeIPPacket(char * pData);
void DecodeTCPPacket(char * pData);
void DecodeUDPPacket(char * pData);
void DecodeICMPPacket(char * pData);
/*IP分组首部结构*/
typedef struct _IPHeader
{
unsigned char iphVerLen;
unsigned char ipTOS;
unsigned short ipLength;
unsigned short ipID;
unsigned short ipFlags;
unsigned char ipTTL;
unsigned char ipProtocol;
unsigned short ipChecksum;
unsigned long ipSource;
unsigned long ipDestination;
}IPHeader, * PIPHeader;
/*ICMP包头结构*/
typedef struct icmphdr
{
char i_type;
char i_code;
unsigned short i_cksum;
unsigned short i_id;
unsigned short i_seq;
unsigned long timestamp;
}ICMPHeader;
/*UDP包头结构*/
typedef struct _UDPHeader
{
unsigned short sourcePort;
unsigned short destinationPort;
unsigned short len;
unsigned short checksum;
}UDPHeader;
/*TCP包头结构*/
typedef struct _TCPHeader
{
unsigned short sourcePort;
unsigned short destinationPort;
unsigned long sequenceNumber;
unsigned long acknowledgeNumber;
char dataoffset;
char flags;
unsigned short window;
unsigned short checksum;
unsigned short urgentPointer;
}TCPHeader;
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
int ret;
if((ret=WSAStartup(MAKEWORD(2,2),&wsaData))!=0)
{
cout<<"初始化winsock出错!";
return -1;
}
/*创建原始套接字*/
SOCKET sRaw = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
/*获取本地IP地址*/
char sHostName[256];
SOCKADDR_IN addr_in;
struct hostent * hptr;
gethostname(sHostName,sizeof(sHostName));
if((hptr = gethostbyname(sHostName)) == NULL)
{
cout<<"未能获取本地IP地址!错误码:"<<WSAGetLastError()<<endl;
WSACleanup();
return -1;
}
char **pptr = hptr->h_addr_list;
/*在屏幕上显示本机所有的IP地址*/
cout<<"本机IP地址:\n";
while(*pptr!=NULL)
{
cout<<inet_ntoa(*(struct in_addr *)(*pptr))<<endl;
pptr++;
}
/*输入想要要监听的接口的IP地址*/
cout<<"请输入要监听接口的IP地址:\n";
char snfIP[20];
cin.getline(snfIP,sizeof(snfIP));
/*填写地址结构*/
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(0);
addr_in.sin_addr.S_un.S_addr = inet_addr(snfIP);
/*绑定网卡IP地址*/
if(bind(sRaw,(PSOCKADDR)&addr_in,sizeof(addr_in)) == SOCKET_ERROR)
{
cout<<"地址绑定出错!错误码:"<<WSAGetLastError()<<endl;
closesocket(sRaw);
WSACleanup();
return -1;
}
//调用ioctlsocket将网卡设为混杂模式前,套接字必须绑定该网卡的IP地址
DWORD dwValue = 1;
if(ioctlsocket(sRaw,SIO_RCVALL,&dwValue)!=0)
{
cout<<"设置网卡为混杂模式时出错!错误码:"<<WSAGetLastError()<<endl;
closesocket(sRaw);
WSACleanup();
return -1;
}
//开始抓取IP分组
char buff[50][4096];
int packetNumber;
cout<<"请输入要抓取的分组数量(不超过50):"<<endl;
cin>>packetNumber;
cout<<"正在等待抓取IP数据包..";
int i,nRet;
for(i=0;i<packetNumber;i++)
{
if(i>=50)break;
nRet=recv(sRaw,buff[i],4096,0);
cout<<"#";
if(nRet<=0)
{
cout<<"抓取数据包时出错!错误码:"<<WSAGetLastError()<<endl;
break;
}
}
//解析IP包
int j=0;
for(j=0;j<i;j++)
{
cout<<endl<<j<<"--------------------------"<<endl;
DecodeIPPacket(buff[j]);
}
closesocket(sRaw);
WSACleanup();
return 0;
}
/***IP分组解析函数****/
void DecodeIPPacket(char *pData)
{
IPHeader * pIPHdr =(IPHeader *) pData;
in_addr source,dest;
char szSourceIp[32],szDestIp[32];
/****从IP头中取出源IP地址和目的地址IP***/
source.S_un.S_addr = pIPHdr ->ipSource;
dest.S_un.S_addr = pIPHdr ->ipDestination;
strcpy_s(szSourceIp,inet_ntoa(source));
strcpy_s(szDestIp,inet_ntoa(dest));
cout<<"Source IP:"<<szSourceIp;
cout<<"Destionation IP:"<<szDestIp<<endl;
int nHeaderLen = (pIPHdr-> iphVerLen &0xf) * sizeof(ULONG);
switch (pIPHdr -> ipProtocol)
{
case IPPROTO_TCP:
DecodeTCPPacket(pData + nHeaderLen);
break;
case IPPROTO_UDP:
DecodeUDPPacket(pData + nHeaderLen);
break;
case IPPROTO_ICMP:
DecodeUDPPacket(pData + nHeaderLen);
break;
defualt:
cout<<"协议号:",pIPHdr->ipProtocol;
}
}
/****TCP包解析函数***/
void DecodeTCPPacket(char * pData)
{
TCPHeader * pTCPHdr =(TCPHeader *) pData;
cout<<"TCP Source Port :"<<ntohs(pTCPHdr ->sourcePort);
cout<<"Destination Port :"<<ntohs(pTCPHdr ->destinationPort)<<endl;
}
/****UDP包解析函数***/
void DecodeUDPPacket(char * pData)
{
UDPHeader * pUDPHdr =(UDPHeader *) pData;
cout<<"UDP Source Port :"<<ntohs(pUDPHdr ->sourcePort);
cout<<"Destination Port :"<<ntohs(pUDPHdr ->destinationPort)<<endl;
}
/****ICMP包解析函数***/
void DecodeICMPPacket(char * pData)
{
ICMPHeader * pICMPHdr =(ICMPHeader *) pData;
cout<<"IMCP Type:" <<pICMPHdr->i_type<<"Code :"<<pICMPHdr ->i_code<<endl;
switch(pICMPHdr -> i_type)
{
case 0:
cout<<"Echo Response .\n"; break;
case 8:
cout<<"Echo Request. \n";break;
case 3:
cout<<"Destination Unreachable .\n"; break;
case 11:
cout<<"Datagram Timeout(TTL=0).\n"; break;
}
}
运行结果: