僅以此文做爲學習筆記,初學者,若有錯誤歡迎批評指正,但求輕噴。ios
通常而言,Linux系統截獲數據包後,會經過協議棧,按照TCP/IP層次進行解析,那咱們如何直接得到更爲底層的數據報文呢,這裏用到一個類型SOCK_PACKET類型。網絡
int sockfd = socket(AF_INET,SOCK_PACKET,htons(0x0003));
經過上面這個函數能夠得到一個特殊的套接字,其中:socket
修改網絡接口結構:tcp
struct ifreq ifr; strcpy(ifr.ifr_name,"eth0"); ioctl(sockfd,SIOCGIFFLAGS,&ifr);
設置混雜模式函數
ifr.ifr_flags| = IFR_PROMISC; ioctl(sockfd,SIOCSIFFLAGS,&ifr);
注意:進行標誌位設定時,遵循如下步驟:學習
一個小小的抓包程序spa
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<sys/ioctl.h> #include<net/if.h> #include<arpa/inet.h> #include<netinet/if_ether.h> #include<netinet/in.h> #include<netinet/ip.h> #include<netinet/tcp.h> #include<netinet/udp.h> 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"<<num<<"received from eth0 START!************************"<<endl; printf("DST MAC: "); for(int i=0;i<ETH_ALEN-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<ETH_ALEN-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"<<num<<"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<num;i++) { int ip_protocol = getframe(sock,i); int trasnport_protocol = getip(ip_protocol,i); gettcp(trasnport_protocol); getudp(trasnport_protocol); cout<<"************************Packet"<<num<<"received from eth0 END!**************************"<<endl; cout<<endl; cout<<endl; cout<<endl; cout<<endl; } return 0; }