协议的分析需要参考前一篇文章以太网帧格式,IP包头,TCP头格式说明。
抓取网络上的数据包需要设置网卡为混杂模式,调用recvfrom在创建的SOCK_RAW类型的socket上接收来自kernel的信息,然后再按照帧格式,IP头,TCP头格式,指针移动到相应位置并分析。
附上的小程序由于其他原因还在UDP9001端口监听了来自客户端的消息,这与本文无关。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <stdio.h> //for printf #include <stdlib.h> //for exit #include <string.h> // for strcmp #include <sys/socket.h> //for socket,address #include <sys/types.h> #include <netinet/in.h> #include <linux/if_ether.h> #include <net/if.h> #include <sys/ioctl.h> //for ioctl #include <pthread.h> #define INTERFACE "eth0" #define BUFFLEN 2048 #define UDPPORT 9001 #define REQUEST 0 #define RESPONSE 1 #define RESERVE 2 #define z_print(fmt,args...) \ printf("[%s %d]"fmt"\n",__FILE__,__LINE__,##args) typedef struct { uint8_t version; uint8_t type; uint8_t len; uint16_t number; char data[255]; } datasend; void* ch_hanlder(); uint8_t randvalue(); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | #include "zhao_sock.h" int main(int argc,char *argv[]) { int sockfd; int len; int proto; int port_s; int port_d; char recvbuff[BUFFLEN]; unsigned char type[4]; unsigned char *ethhead = NULL; unsigned char *iphead = NULL; unsigned char *p = NULL; struct ifreq ifr; pthread_t thread_ch; pthread_create(&thread_ch,NULL,&ch_hanlder,NULL); sockfd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)); if (sockfd < 0) { z_print("socket create error"); exit(1); } strcpy(ifr.ifr_name,INTERFACE); if (ioctl(sockfd,SIOCGIFFLAGS,&ifr) == -1) { z_print("set PROMISC fail!\n"); exit(1); } ifr.ifr_flags |= IFF_PROMISC; if (ioctl(sockfd,SIOCGIFFLAGS,&ifr) == -1) { z_print("set PROMISC fail!"); exit(1); } while(1) { len = recvfrom(sockfd,recvbuff,sizeof(recvbuff),0,NULL,NULL); if (len < 42) { z_print("receive error!"); continue; } ethhead = recvbuff; //frame head point p = ethhead; sprintf(type,"%02x%02x",p[12],p[13]); //frame type if (strcmp(type,"0800") != 0) //0800 is IP frame { if (strcmp(type,"0806") == 0) printf("protocol: ARP\n"); else if (strcmp(type,"8035") == 0) printf("protocol: RARP\n"); else printf("protocol: unknow\n"); printf("MAC:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x==>%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n\n", \ p[6],p[7],p[8],p[9],p[10],p[11],p[0],p[1],p[2],p[3],p[4],p[5]); //mac address continue; } iphead = ethhead + 14; //ip head point p = iphead + 12; //ip address printf("IP:%d.%d.%d.%d==>%d.%d.%d.%d\n", \ p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]); proto = (iphead + 9)[0]; //ip protocol p = iphead + 20; //ip port switch(proto) { case IPPROTO_ICMP: printf("protocol: ICMP\n"); break; case IPPROTO_IGMP: printf("protocol: IGMP\n"); break; case IPPROTO_IPIP: printf("protocol: IPIP\n"); break; case IPPROTO_TCP: case IPPROTO_UDP: printf("protocol: %s\n",(proto == IPPROTO_TCP) ? "TCP":"UDP"); port_s = (p[0]<<8)&0XFF00 | p[1]&0XFF; //source port port_d = (p[2]<<8)&0XFF00 | p[3]&0XFF; // dest port printf("source port:%u,",port_s); printf("dest port:%u\n",port_d); if (port_s == 80 || port_d == 80) printf("protocol: HTTP\n"); else if (port_s == 67 || port_d == 67) printf("protocol: DHCP\n"); else if (port_s == 21 || port_d == 21) printf("protocol: FTP\n"); else if (port_s == 23 || port_d == 23) printf("protocol: TELNET\n"); else if (port_s == 53 || port_d == 53) printf("protocol: DNS\n"); else if (port_s == 137 || port_d == 137 || port_s == 138 || port_d == 138) printf("protocol: NetBIOS/SMB\n"); else printf("protocol: other\n"); break; case IPPROTO_RAW: printf("RAW\n"); break; default: printf("protocol:unknow(%d)\n",proto); } printf("\n"); } } void* ch_hanlder() { int sockfd; int len; int flag_close = 0; socklen_t addrlen; datasend msg_send; datasend msg_recv; struct sockaddr_in servaddr; memset(&msg_send,0,sizeof(datasend)); memset(&msg_recv,0,sizeof(datasend)); bzero(&servaddr, sizeof(servaddr)); msg_send.version = 1; msg_send.type = RESPONSE; sprintf(msg_send.data,"%s","received!"); sockfd = socket(AF_INET, SOCK_DGRAM, 0); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(UDPPORT); addrlen = sizeof(struct sockaddr_in); if (bind(sockfd, (struct sockaddr *)&servaddr, addrlen) == -1) { perror("bind error"); exit(1); } while (1) { len = recvfrom(sockfd, &msg_recv, sizeof(datasend),0,(struct sockaddr*)&servaddr, &addrlen); printf("version:%3d\n",msg_recv.version); printf("type:%d\n",msg_recv.type); printf("len:%d\n",msg_recv.len); printf("number:%d\n",msg_recv.number); printf("data:%s\n",msg_recv.data); if (strcmp(msg_recv.data,"close") == 0) { sprintf(msg_send.data,"%s","close"); flag_close = 1; } msg_send.number = msg_recv.number + 1; msg_send.len = randvalue(); sendto(sockfd,&msg_send,sizeof(datasend),0,(struct sockaddr*)&servaddr,addrlen); if (flag_close) break; } return; } uint8_t randvalue() { srand(time(0)); return (rand() % 255); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #include "zhao_sock.h" int main(int argc, char *argv[]) { int sockfd; int len; socklen_t addrlen; struct sockaddr_in cliaddr; FILE *fd; datasend msg_send; datasend msg_recv; fd = fopen("/root/zhao_log.txt","a"); memset(&msg_send,0,sizeof(datasend)); memset(&msg_recv,0,sizeof(datasend)); bzero(&cliaddr, sizeof(cliaddr)); msg_send.version = 1; msg_send.type = REQUEST; msg_send.number = 1; msg_send.len = randvalue(); sockfd = socket(AF_INET, SOCK_DGRAM, 0); cliaddr.sin_family = AF_INET; cliaddr.sin_port = htons(UDPPORT); cliaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); addrlen = sizeof(struct sockaddr_in); while (1) { printf("please input send msg:"); scanf("%s",msg_send.data); sendto(sockfd,&msg_send,sizeof(datasend),0,(struct sockaddr*)&cliaddr,addrlen); len = recvfrom(sockfd, &msg_recv, sizeof(datasend),0,(struct sockaddr*)&cliaddr, &addrlen); msg_send.number = msg_recv.number + 1; msg_send.len = randvalue(); printf("version:%3d\n",msg_recv.version); printf("type:%d\n",msg_recv.type); printf("len:%d\n",msg_recv.len); printf("number:%d\n",msg_recv.number); printf("data:%s\n",msg_recv.data); fprintf(fd,"version:%d\n",msg_recv.version); fprintf(fd,"type:%d\n",msg_recv.type); fprintf(fd,"len:%d\n",msg_recv.len); fprintf(fd,"number:%d\n",msg_recv.number); fprintf(fd,"data:%s\n",msg_recv.data); if (strcmp(msg_recv.data,"close") == 0) break; } fclose(fd); return 0; } uint8_t randvalue() { srand(time(0)+1); return (rand() % 255); } |


COMMENTS