封包的截取与解包-1

/*

网络数据包侦听基本原理:*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <Winsock2.h>
#include <mstcpip.h>


#define STATUS_FAILED 0xFFFF  //定义异常出错代码
#define MAX_PACK_LEN  65535   //接收的最大IP报文 
#define MAX_ADDR_LEN  16   //点分十进制地址的最大长度
#define MAX_PROTO_TEXT_LEN 16  //子协议名称(如"TCP")最大长度
#define MAX_PROTO_NUM 12   //子协议数量
#define MAX_HOSTNAME_LAN 255  //最大主机名长度
#define CMD_PARAM_HELP true

HANDLE hFile = NULL;
HANDLE hParse = NULL;

typedef struct _iphdr
{
 unsigned char h_lenver;  //4位首部长度+4位IP版本号
 unsigned char tos;   //8位服务类型TOS
 unsigned short total_len;  //16位总长度(字节)
 unsigned short ident;   //16位标识
 unsigned short frag_and_flags; //3位标志位
 unsigned char ttl;   //8位生存时间 TTL
 unsigned char proto;   //8位协议 (TCP, UDP 或其他)
 unsigned short checksum;  //16位IP首部校验和
 unsigned int sourceIP;  //32位源IP地址
 unsigned int destIP;   //32位目的IP地址
}IP_HEADER;

typedef struct _tcphdr    //定义TCP首部
{
 USHORT th_sport;    //16位源端口
 USHORT th_dport;    //16位目的端口
 unsigned int  th_seq;   //32位序列号
 unsigned int  th_ack;   //32位确认号
 unsigned char th_lenres;  //4位首部长度/6位保留字
 unsigned char th_flag;   //6位标志位
 USHORT th_win;     //16位窗口大小
 USHORT th_sum;     //16位校验和
 USHORT th_urp;     //16位紧急数据偏移量
}TCP_HEADER;

typedef struct _udphdr    //定义UDP首部
{
    unsigned short uh_sport;  //16位源端口
    unsigned short uh_dport;  //16位目的端口
    unsigned short uh_len;   //16位长度
    unsigned short uh_sum;   //16位校验和
} UDP_HEADER;

typedef struct _icmphdr    //定义ICMP首部
{
 BYTE   i_type;     //8位类型
 BYTE   i_code;     //8位代码
 USHORT i_cksum;     //16位校验和
 USHORT i_id;     //识别号(一般用进程号作为识别号)
 USHORT i_seq;     //报文序列号 
 ULONG  timestamp;    //时间戳
}ICMP_HEADER;

typedef struct _protomap   //定义子协议映射表
{
 int  ProtoNum;
 char ProtoText[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   , "NP  " }, 
  { IPPROTO_RAW  , "RAW " }, 
  { IPPROTO_MAX  , "MAX " },
  { NULL , "" } };

SOCKET SockRaw;
char TcpFlag[6]={'F','S','R','P','A','U'}; //定义TCP标志位
bool ParamTcp =false;    // -t关注TCP 报文
bool ParamUdp =false;    // -u关注UDP 报文 
bool ParamIcmp =false;    // -i关注ICMP报文
bool ParamDecode=false;    // -d对协议进行解码
char *strFromIpFilter=NULL;   // 源IP地址过滤
char *strDestIpFilter=NULL;   // 目的地址过滤
char *strSensitive=NULL;   // 敏感字符串
int  iPortFilter=0;     // 端口过滤
int iProtocol, iTTL;    
char szProtocol[MAX_PROTO_TEXT_LEN];
char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN];

int DecodeIpPack(char *, int);  //IP解包函数
int DecodeTcpPack(char *, int);  //TCP解包函数
int DecodeUdpPack(char *, int);  //UDP解包函数
int DecodeIcmpPack(char *, int); //ICMP解包函数
void CheckSockError(int, char*); //出错处理函数
char * CheckProtocol(int);   //协议检查
void usage(void);     //使用说明
bool GetCmdLine(int, char **);  //命令行参数处理


void main(int argc, char ** argv)
{
 hFile = ::CreateFile("NetReport.txt", FILE_ALL_ACCESS, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 hParse = ::CreateFile("NR.txt", FILE_ALL_ACCESS, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 int iErrorCode;
 char RecvBuf[MAX_PACK_LEN] = {0};
 usage();
 if(GetCmdLine(argc, argv)==CMD_PARAM_HELP) exit(0);
 //初始化SOCKET
 WSADATA wsaData;
 iErrorCode = WSAStartup(MAKEWORD(2,1),&wsaData);
 CheckSockError(iErrorCode, "WSAStartup");
 SockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
 CheckSockError(SockRaw, "socket");
 //获取本机IP地址
 char FAR name[MAX_HOSTNAME_LAN];
 iErrorCode = gethostname(name, MAX_HOSTNAME_LAN);
 CheckSockError(iErrorCode, "gethostname");
 struct hostent FAR * pHostent;
 pHostent = (struct hostent * )malloc(sizeof(struct hostent));
 pHostent = 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);
 free(pHostent);
 iErrorCode = bind(SockRaw, (PSOCKADDR)&sa, sizeof(sa));
 CheckSockError(iErrorCode, "bind");
 //设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
 DWORD dwBufferLen[10] ;
 DWORD dwBufferInLen = 1 ;
 DWORD dwBytesReturned = 0 ;
 iErrorCode=WSAIoctl(SockRaw, SIO_RCVALL,&dwBufferInLen, sizeof(dwBufferInLen),            
                        &dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );
 CheckSockError(iErrorCode, "Ioctl");
 //侦听IP报文
 while(1)
 {
  memset(RecvBuf, 0, sizeof(RecvBuf));
  iErrorCode = recv(SockRaw, RecvBuf, sizeof(RecvBuf), 0);
  CheckSockError(iErrorCode, "recv");
  iErrorCode = DecodeIpPack(RecvBuf, iErrorCode);
  CheckSockError(iErrorCode, "Decode");
 }
 ::CloseHandle(hFile);
 ::CloseHandle(hParse);
}
//IP解包程序
int DecodeIpPack(char *buf, int iBufSize)
{
 IP_HEADER *pIpheader;
 SOCKADDR_IN saSource, saDest;
 pIpheader = (IP_HEADER *)buf;
//协议甄别
 iProtocol = pIpheader->proto;
 strncpy(szProtocol, CheckProtocol(iProtocol), MAX_PROTO_TEXT_LEN);
 if((iProtocol==IPPROTO_TCP) && (!ParamTcp)) return true;
 if((iProtocol==IPPROTO_UDP) && (!ParamUdp)) return true;
 if((iProtocol==IPPROTO_ICMP) && (!ParamIcmp)) return true;
//源地址
 saSource.sin_addr.s_addr = pIpheader->sourceIP;
 strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);
 if (strFromIpFilter)
  if (strcmp(strFromIpFilter,szSourceIP)) return true;
//目的地址
 saDest.sin_addr.s_addr = pIpheader->destIP;
 strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);
 if (strDestIpFilter)
  if (strcmp(strDestIpFilter,szDestIP)) return true;
 iTTL = pIpheader->ttl;
//计算IP首部的长度
 int iIphLen = sizeof(unsigned long) * (pIpheader->h_lenver & 0xf);
//根据协议类型分别调用相应的函数
 switch(iProtocol)
 {
  case IPPROTO_TCP :DecodeTcpPack(buf+iIphLen, iBufSize);break;
  case IPPROTO_UDP :DecodeUdpPack(buf+iIphLen, iBufSize);break;
  case IPPROTO_ICMP :DecodeIcmpPack(buf+iIphLen, iBufSize);break;
  default    :break;
 }
 //printf("/n");
 return true;
}

//协议识别程序
char * CheckProtocol(int iProtocol)
{
 for(int i=0; i<MAX_PROTO_NUM; i++)
   if(ProtoMap[i].ProtoNum==iProtocol)
    return ProtoMap[i].ProtoText;
 return "";
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值