赞
踩
是在之前五元组信息的代码基础上改的,因此有一些冗余。
主要思想就是字符串匹配。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<netinet/in.h> typedef int32_t bpf_int32; typedef u_int32_t bpf_u_int32; typedef u_int16_t u_short; typedef u_int32_t u_int32; typedef u_int16_t u_int16; typedef u_int8_t u_int8; char tempSrcIp[256];//存储转化后的字符地址。 char tempDstIp[256]; //pacp文件头结构体 struct pcap_file_header { bpf_u_int32 magic; /* 0xa1b2c3d4 */ u_short version_major; /* magjor Version 2 */ u_short version_minor; /* magjor Version 4 */ bpf_int32 thiszone; /* gmt to local correction */ bpf_u_int32 sigfigs; /* accuracy of timestamps */ bpf_u_int32 snaplen; /* max length saved portion of each pkt */ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ }; //时间戳 struct time_val { int tv_sec; /* seconds 含义同 time_t 对象的值 */ int tv_usec; /* and microseconds */ }; //pcap数据包头结构体 struct pcap_pkthdr { struct time_val ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }; //IP数据报头 20字节 typedef struct IPHeader_t { //IP数据报头 u_int8 Ver_HLen; //版本+报头长度 u_int8 TOS; //服务类型 u_int16 TotalLen; //总长度 u_int16 ID; //标识 u_int16 Flag_Segment; //标志+片偏移 u_int8 TTL; //生存周期 u_int8 Protocol; //协议类型 u_int16 Checksum; //头部校验和 u_int32 SrcIP; //源IP地址 u_int32 DstIP; //目的IP地址 } IPHeader_t; //TCP/UDP数据 typedef struct TCPUDPHeader_t { u_int16_t SrcPort; // 源端口号16bit u_int16_t DstPort; // 目的端口号16bit }TCPUDPHeader_t; typedef struct Quintet { u_int32 SrcIP; //源IP地址 u_int32 DstIP; //目的IP地址 u_int16_t SrcPort; // 源端口号16bit u_int16_t DstPort; // 目的端口号16bit u_int8 Protocol; //协议类型 }Quintet_t; //查找src在dst中的位置,不存在则返回-1.考虑HOST、Host、host三种情况 //直接return host的值。 char * get_data_offset(char *src, char *dst,int dst_len) { //先把src的首字母在dst中找,如果找到,则把dst中后面一部分与src相同长度的字符串摘出来进行比较,若相等则返回第一个位置, //否则返回-1. int dIndex=0;//dst移动下标 int sIndex = 0;//src移动下标 int src_len=strlen(src); //printf("%s\n",dst); //printf("!!!%d",src_len); while(dIndex <= dst_len-src_len){ //如果两个字母相等,继续判断剩下的 if(*src == *(dst+dIndex)){ sIndex = 0; for(;sIndex<src_len;sIndex++){//往后遍历src长度的字符串 //dst 和src一直没移动。 if(*(dst+sIndex+dIndex)!=*(src+sIndex))//如果中间任何一个字母不等于 { /*printf("-------------break"); printf("%d\n",sIndex); printf("dst:%s",dst+sIndex+dIndex); printf("src:%s\n",src+sIndex);*/ break; }else{ //如果全部等于 //之前是sIndex和dIndex一直在移动。用一个tmpindex记录。 /* printf("---%d\n",sIndex); printf("dst:%c",*(dst+sIndex+dIndex)); printf("src:%c\n",*(src+sIndex));*/ //sIndex++; } } if(sIndex == src_len){ int tmp_index=dIndex+sIndex+2;//把: 都省略掉 int host_len=0; char * host; host=(char *)malloc (100); while(*(dst+tmp_index)!='\r' && *(dst+tmp_index+1)!='\n'){//一直+1,直到碰到\r\n printf("%c",*(dst+tmp_index)); *(host+host_len)=*(dst+tmp_index); tmp_index++; host_len++; } printf("\n"); return host; } } dIndex++; //printf("src:%s",src); //printf("dst:%s\n",dst); } return NULL; } int main() { struct pcap_pkthdr *ptk_header = NULL;//设置将要读取的pcap包的包头 IPHeader_t *ip_header = NULL; TCPUDPHeader_t *tcpudp_header = NULL; Quintet_t *quintet = NULL; //初始化,分配内存 ptk_header = (struct pcap_pkthdr *)malloc(256); ip_header = (IPHeader_t *)malloc(sizeof(IPHeader_t)); tcpudp_header = (TCPUDPHeader_t *)malloc(sizeof(TCPUDPHeader_t)); quintet = (Quintet_t *)malloc(sizeof(Quintet_t)); //memset(buf, 0, sizeof(buf)); FILE* pFile = fopen( "data.pcap", "r"); if( pFile == 0) { printf( "打开pcap文件失败"); return 0; } FILE *output = fopen("./5_tuple.txt","w+"); if( output == 0) { printf( "打开txt文件失败"); return 0; } //开始读数据包------------ long int pkt_offset; //用来文件偏移 pkt_offset = 24; //pcap文件头结构 24个字节 int i = 0; fprintf(output,"index sip dip sport dport protocol\n"); while(1) //遍历数据包,结构:pcap文件头24B,数据包头16B(包括caplen),数据包内容中包括数据帧头14B,IP数据报头20B(源地址和目的地址),UDP/TCP数据包内容。 { i++; fseek(pFile, pkt_offset, SEEK_SET);//移动pfile文件指针位置,跳过pcap文件头 //对要存储的变量地址的内容进行初始化。 memset(ptk_header, 0, sizeof(struct pcap_pkthdr)); memset(quintet,0,sizeof(struct Quintet)); //读pcap数据包头结构,16个字节 if(fread(ptk_header, 16, 1, pFile) != 1) { printf("%d: can not read ptk_header\n", i); break; } pkt_offset += 16 + ptk_header->caplen; //下一个数据包的开始位置为此数据包的起始位置+数据包头(16B)+数据长度caplen printf("caplen:%d\n",ptk_header->caplen); //数据帧头 14字为ethnet协议大小,跳过。 fseek(pFile,14, SEEK_CUR); //IP数据报头 20字节 memset(ip_header, 0, sizeof(IPHeader_t)); if(fread(ip_header, sizeof(IPHeader_t), 1, pFile) != 1) { printf("%d: can not read ip_header\n", i); break; } quintet->SrcIP = ip_header->SrcIP; quintet->DstIP = ip_header->DstIP; quintet->Protocol = ip_header->Protocol; memset(tcpudp_header,0,sizeof(TCPUDPHeader_t)); //TCP/UDP头 20字节,端口字段是一样的 if(fread(tcpudp_header, sizeof(TCPUDPHeader_t), 1, pFile) != 1) { printf("%d: can not read tcpudp_header\n", i); break; } quintet->SrcPort = tcpudp_header->SrcPort; quintet->DstPort = tcpudp_header->DstPort; //将数值转化为ip地址 //printf("???%d\n",&ip_header->SrcIP); inet_ntop(AF_INET,&(ip_header->SrcIP),tempSrcIp,sizeof(tempSrcIp)); inet_ntop(AF_INET, &(ip_header->DstIP),tempDstIp,sizeof(tempDstIp)); //将数值转换为端口号 quintet->SrcPort = ntohs(quintet->SrcPort); quintet->DstPort = ntohs(quintet->DstPort); //先把caplen长度的数据包内容读取到一个空间。再使用字符串查找的方法,形如http.host == "xxx" 或者Host: jingxi.co\r\n char tmp_http[10000]; fseek(pFile, (pkt_offset-16-ptk_header->caplen), SEEK_SET);//回到每个数据包的开头。 if(fread(tmp_http,ptk_header->caplen,1,pFile)!=1) { printf("fail"); } //使用字符串查找的方法。 char *x="host"; char * res=get_data_offset(x,tmp_http,ptk_header->caplen); if(res==NULL){ x="Host"; char * res=get_data_offset(x,tmp_http,ptk_header->caplen); if(res==NULL){ x="HOST"; char * res=get_data_offset(x,tmp_http,ptk_header->caplen); if(res==NULL){ printf("search host fail"); } } } } fclose(pFile); fclose(output); return 0; }
输出如下:
主要思想是先判断有没有.com.cn,有的话取倒数第三个.右边的所有内容;没有的话取第二个.右边的。(做得比较简单,可以再改进)。
代码如下:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<netinet/in.h> typedef int32_t bpf_int32; typedef u_int32_t bpf_u_int32; typedef u_int16_t u_short; typedef u_int32_t u_int32; typedef u_int16_t u_int16; typedef u_int8_t u_int8; char tempSrcIp[256];//存储转化后的字符地址。 char tempDstIp[256]; //pacp文件头结构体 struct pcap_file_header { bpf_u_int32 magic; /* 0xa1b2c3d4 */ u_short version_major; /* magjor Version 2 */ u_short version_minor; /* magjor Version 4 */ bpf_int32 thiszone; /* gmt to local correction */ bpf_u_int32 sigfigs; /* accuracy of timestamps */ bpf_u_int32 snaplen; /* max length saved portion of each pkt */ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ }; //时间戳 struct time_val { int tv_sec; /* seconds 含义同 time_t 对象的值 */ int tv_usec; /* and microseconds */ }; //pcap数据包头结构体 struct pcap_pkthdr { struct time_val ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }; //IP数据报头 20字节 typedef struct IPHeader_t { //IP数据报头 u_int8 Ver_HLen; //版本+报头长度 u_int8 TOS; //服务类型 u_int16 TotalLen; //总长度 u_int16 ID; //标识 u_int16 Flag_Segment; //标志+片偏移 u_int8 TTL; //生存周期 u_int8 Protocol; //协议类型 u_int16 Checksum; //头部校验和 u_int32 SrcIP; //源IP地址 u_int32 DstIP; //目的IP地址 } IPHeader_t; //TCP/UDP数据 typedef struct TCPUDPHeader_t { u_int16_t SrcPort; // 源端口号16bit u_int16_t DstPort; // 目的端口号16bit }TCPUDPHeader_t; typedef struct Quintet { u_int32 SrcIP; //源IP地址 u_int32 DstIP; //目的IP地址 u_int16_t SrcPort; // 源端口号16bit u_int16_t DstPort; // 目的端口号16bit u_int8 Protocol; //协议类型 }Quintet_t; //查找src在dst中的位置,不存在则返回-1.考虑HOST、Host、host三种情况 //直接return host的值。 char * get_data_offset(char *src, char *dst,int dst_len) { //先把src的首字母在dst中找,如果找到,则把dst中后面一部分与src相同长度的字符串摘出来进行比较,若相等则返回第一个位置, //否则返回-1. int dIndex=0;//dst移动下标 int sIndex = 0;//src移动下标 int src_len=strlen(src); //printf("%s\n",dst); //printf("!!!%d",src_len); while(dIndex <= dst_len-src_len){ //如果两个字母相等,继续判断剩下的 if(*src == *(dst+dIndex)){ sIndex = 0; for(;sIndex<src_len;sIndex++){//往后遍历src长度的字符串 //dst 和src一直没移动。 if(*(dst+sIndex+dIndex)!=*(src+sIndex))//如果中间任何一个字母不等于 { break; }else{ //如果全部等于 //之前是sIndex和dIndex一直在移动。用一个tmpindex记录。 } } if(sIndex == src_len){ int tmp_index=dIndex+sIndex+2;//把: 都省略掉 int host_len=0; char * host; host=(char *)malloc (100); while(*(dst+tmp_index)!='\r' && *(dst+tmp_index+1)!='\n'){//一直+1,直到碰到\r\n printf("%c",*(dst+tmp_index)); *(host+host_len)=*(dst+tmp_index); tmp_index++; host_len++; } printf("\n"); return host; } } dIndex++; //printf("src:%s",src); //printf("dst:%s\n",dst); } return NULL; } //先用字符串匹配,匹配是否有.com.cn,有的话取倒数第三个.右边的所有字符;没有的话取倒数第二个.右边的所有字符。 char * get_domain_from_host(char * host) { char *z=".com.cn"; char *tmp_res; char *res; int len=strlen(host);//记录host的长度。 tmp_res=(char *)malloc (100); res=(char *)malloc (20);//输出的结果 //调用字符串查找函数找有没有.com.cn tmp_res=get_data_offset(z,host,len); //创建一个函数,读取host中.的个数,并将其对应的下标位置记录下。 //定义一个数组,记录下标值。再定义一个num记录.的个数。 int mark[10]; int num=0; int i=0; while(i<len){//遍历host if(*(host+i)=='.'){ mark[num]=i; num++; } i++; } if(tmp_res==NULL){//说明没有.com.cn //取倒数第二个.右边的所有字符。第一个.的位置是mark[0],第二个.的位置是mark[1]... 倒数第一个.的位置是num-1;倒数第二个是num-2,倒数第三个是num-3. int j=mark[num-2]+1; int k=0; while(j<len){ *(res+k)=*(host+j); k++; j++; } return res; }else{//说明有,取倒数第三个.右边的所有字符 int j=mark[num-3]+1; int k=0; while(j<len){ *(res+k)=*(host+j); k++; j++; } return res; } return NULL; } int main() { struct pcap_pkthdr *ptk_header = NULL;//设置将要读取的pcap包的包头 IPHeader_t *ip_header = NULL; TCPUDPHeader_t *tcpudp_header = NULL; Quintet_t *quintet = NULL; //初始化,分配内存 ptk_header = (struct pcap_pkthdr *)malloc(256); ip_header = (IPHeader_t *)malloc(sizeof(IPHeader_t)); tcpudp_header = (TCPUDPHeader_t *)malloc(sizeof(TCPUDPHeader_t)); quintet = (Quintet_t *)malloc(sizeof(Quintet_t)); //memset(buf, 0, sizeof(buf)); FILE* pFile = fopen( "data.pcap", "r"); if( pFile == 0) { printf( "打开pcap文件失败"); return 0; } FILE *output = fopen("./5_tuple.txt","w+"); if( output == 0) { printf( "打开txt文件失败"); return 0; } //开始读数据包------------ long int pkt_offset; //用来文件偏移 pkt_offset = 24; //pcap文件头结构 24个字节 int i = 0; fprintf(output,"index sip dip sport dport protocol\n"); while(1) //遍历数据包,结构:pcap文件头24B,数据包头16B(包括caplen),数据包内容中包括数据帧头14B,IP数据报头20B(源地址和目的地址),UDP/TCP数据包内容。 { i++; fseek(pFile, pkt_offset, SEEK_SET);//移动pfile文件指针位置,跳过pcap文件头 //对要存储的变量地址的内容进行初始化。 memset(ptk_header, 0, sizeof(struct pcap_pkthdr)); memset(quintet,0,sizeof(struct Quintet)); //读pcap数据包头结构,16个字节 if(fread(ptk_header, 16, 1, pFile) != 1) { printf("%d: can not read ptk_header\n", i); break; } pkt_offset += 16 + ptk_header->caplen; //下一个数据包的开始位置为此数据包的起始位置+数据包头(16B)+数据长度caplen //printf("caplen:%d\n",ptk_header->caplen); //数据帧头 14字为ethnet协议大小,跳过。 fseek(pFile,14, SEEK_CUR); //IP数据报头 20字节 memset(ip_header, 0, sizeof(IPHeader_t)); if(fread(ip_header, sizeof(IPHeader_t), 1, pFile) != 1) { printf("%d: can not read ip_header\n", i); break; } quintet->SrcIP = ip_header->SrcIP; quintet->DstIP = ip_header->DstIP; quintet->Protocol = ip_header->Protocol; memset(tcpudp_header,0,sizeof(TCPUDPHeader_t)); //TCP/UDP头 20字节,端口字段是一样的 if(fread(tcpudp_header, sizeof(TCPUDPHeader_t), 1, pFile) != 1) { printf("%d: can not read tcpudp_header\n", i); break; } quintet->SrcPort = tcpudp_header->SrcPort; quintet->DstPort = tcpudp_header->DstPort; //将数值转化为ip地址 //printf("???%d\n",&ip_header->SrcIP); inet_ntop(AF_INET,&(ip_header->SrcIP),tempSrcIp,sizeof(tempSrcIp)); inet_ntop(AF_INET, &(ip_header->DstIP),tempDstIp,sizeof(tempDstIp)); //将数值转换为端口号 quintet->SrcPort = ntohs(quintet->SrcPort); quintet->DstPort = ntohs(quintet->DstPort); //先把caplen长度的数据包内容读取到一个空间。再使用字符串查找的方法,形如http.host == "xxx" 或者Host: jingxi.co\r\n char tmp_http[10000]; fseek(pFile, (pkt_offset-16-ptk_header->caplen), SEEK_SET);//回到每个数据包的开头。 if(fread(tmp_http,ptk_header->caplen,1,pFile)!=1) { printf("fail"); } //使用字符串查找的方法。 char *x="host"; char * res; res=(char *)malloc (100); res=get_data_offset(x,tmp_http,ptk_header->caplen); if(res==NULL){ x="Host"; res=get_data_offset(x,tmp_http,ptk_header->caplen); if(res==NULL){ x="HOST"; res=get_data_offset(x,tmp_http,ptk_header->caplen); if(res==NULL){ printf("search host fail"); } } } //从host里面提取出顶级域名。考虑以下几种情况:除了.com.cn,都取倒数第二个.右边的所有字符。 //所以先用字符串匹配,匹配是否有.com.cn,有的话取倒数第三个.右边的所有字符;没有的话取倒数第二个.右边的所有字符。 char * domain_host; domain_host=(char *)malloc (20); domain_host=get_domain_from_host(res); printf("res:%s\n",domain_host); } fclose(pFile); fclose(output); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。