仅以此文作为学习笔记,初学者,如有错误欢迎批评指正,但求轻喷。
一般而言,Linux系统截获数据包后,会通过协议栈,按照TCP/IP层次进行解析,那我们如何直接获得更为底层的数据报文呢,这里用到一个类型SOCK_PACKET类型。
1 int sockfd = socket(AF_INET,SOCK_PACKET,htons(0x0003));
通过上面这个函数可以获得一个特殊的套接字,其中:
AF_INET: 表示因特网协议族
SOCK_PACKET: 表示数据包截取在物理层
0x0003: 表示数据帧类型不确定
修改网络接口结构:
1 struct ifreq ifr; 2 strcpy(ifr.ifr_name,"eth0"); 3 ioctl(sockfd,SIOCGIFFLAGS,&ifr);
设置混杂模式
1 ifr.ifr_flags| = IFR_PROMISC; 2 ioctl(sockfd,SIOCSIFFLAGS,&ifr);
注意:
进行标志位设定时,遵循以下步骤:
(1)取出原标识位;
(2)与待设定标志位进行位或运算(“|”);
(3)重新写入;
一个小小的抓包程序
#include#include #include<string.h> #include #include #include #include #include #include if.h> #include #include #include in.h> #include #include #include using namespace std; char ethernet_frame[ETH_FRAME_LEN];//定义一个数据帧的长度 struct iphdr *ipheader;//定义ip头部指针 int socketcreate() { int sockfd = socket(AF_INET,SOCK_PACKET,htons(0x0003)); //构建了一个数据链路层的数据包; if(sockfd == -1) { cout<<"Socket init error!"<<endl; return -1; } /* 下面设置接口结构 */ char *ifname = "eth0"; struct ifreq ifr; strcpy(ifr.ifr_name,ifname); int result = ioctl(sockfd,SIOCGIFFLAGS,&ifr); if(result == -1) { cout<<"Can't get flags!"<<endl; close(sockfd); return -2; } ifr.ifr_flags|= IFF_PROMISC; /* 一般而言,Linux系统截获数据包后,会通过协议栈,按照TCP/IP层次进行解析,那我们如何直接获得更为底层的数据报文呢,这里用到一个类型SOCK_PACKET类型。 int sockfd = socket(AF_INET,SOCK_PACKET,htons(0x0003)); 通过上面这个函数可以获得一个特殊的套接字,其中: AF_INET: 表示因特网协议族 SOCK_PACKET: 表示数据包截取在物理层 0x0003: 表示数据帧类型不确定 修改网络接口结构: struct ifreq ifr; strcpy(ifr.ifr_name,"eth0"); ioctl(sockfd,SIOCGIFFLAGS,&ifr); 设置混杂模式 ifr.ifr_flags| = IFR_PROMISC; ioctl(sockfd,SIOCSIFFLAGS,&ifr); 注意: 进行标志位设定时,遵循以下步骤: (1)取出原标识位; (2)与待设定标志位进行位或运算(“|”); (3)重新写入; */ result = ioctl(sockfd,SIOCSIFFLAGS,&ifr); if(result == -1) { cout<<"Can't set flags!"<<endl; close(sockfd); return -3; } return sockfd; } int getframe(int sockfd,int num) { struct ethhdr* fheader; fheader = (struct ethhdr*)ethernet_frame; memset(ethernet_frame,0,ETH_FRAME_LEN); int size = read(sockfd,ethernet_frame,ETH_FRAME_LEN); if(size <= 0) { cout<<"No packet or packet error!"<<endl; return -1; } cout<<"************************Packet"< "received from eth0 START!************************"<<endl; printf("DST MAC: "); for(int i=0;i 1;i++) { printf("%2x-",fheader->h_dest[i]); } printf("%2x\n",fheader->h_dest[ETH_ALEN-1]); printf("SRC MAC: "); for(int i=0;i 1;i++) { printf("%2x-",fheader->h_source[i]); } printf("%2x\n",fheader->h_source[ETH_ALEN-1]); if(ntohs(fheader->h_proto) == 0x0800) { cout<<"Protocol: IP"<<endl; } if(ntohs(fheader->h_proto) == 0x0806) { cout<<"Protocol: RAP"<<endl; } if(ntohs(fheader->h_proto) == 0x8035) { cout<<"Protocol: RARP"<<endl; } int ret = ntohs(fheader->h_proto); return ret; } int getip(int protocol,int num) { if(protocol != 0x0800) { cout<<"NO IP Packet!"<<endl; cout<<"************************Packet"< "received from eth0 END!**************************"<<endl; return 0; } ipheader = (struct iphdr*)(ethernet_frame+ETH_HLEN); printf("Version: 4"); cout<<endl; in_addr *p,*q; p = (struct in_addr*)&ipheader->saddr; printf("SRC IP: %s",inet_ntoa(*p)); cout<<endl; q = (struct in_addr*)&ipheader->daddr; printf("DST IP: %s",inet_ntoa(*q)); cout<<endl; if(ipheader->protocol == 1) { cout<<"PROTOCOL: ICMP"<<endl; } if(ipheader->protocol == 6) { cout<<"PROTOCOL: TCP"<<endl; } if(ipheader->protocol == 17) { cout<<"PROTOCOL: UDP"<<endl; } return ipheader->protocol; } int gettcp(int protocol) { if(protocol != 6) { return -1; } struct tcphdr* tcph; tcph = (struct tcphdr*)(ipheader+((ipheader->ihl)*4)); printf("SRC PORT: %d",ntohs(tcph->source)); cout<<endl; printf("DST PORT: %d",ntohs(tcph->dest)); cout<<endl; return 0; } int getudp(int protocol) { if(protocol != 17) { return -1; } struct udphdr* udph; udph = (struct udphdr*)(ipheader+((ipheader->ihl)*4)); printf("SRC PORT: %d",ntohs(udph->source)); cout<<endl; printf("DST PORT: %d",ntohs(udph->dest)); cout<<endl; return 0; } int main(int argc,char *argv[]) { if(argc < 2) { cout<<"Please input the nummber of packet that you want to catch!"<<endl; return 0; } int num = (int)argv[1][0]; int sock = socketcreate(); for(int i=1;i ) { int ip_protocol = getframe(sock,i); int trasnport_protocol = getip(ip_protocol,i); gettcp(trasnport_protocol); getudp(trasnport_protocol); cout<<"************************Packet"< "received from eth0 END!**************************"<<endl; cout<<endl; cout<<endl; cout<<endl; cout<<endl; } return 0; }