linux下用C语言编写程序打印出抓包信息.pcap文件的内容

时间:2021-04-09 09:16:57
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<time.h>

#define BUFSIZE 10240
#define STRSIZE 1024

typedef long bpf_int32;
typedef unsigned long bpf_u_int32;
typedef unsigned short u_short;
typedef unsigned long u_int32;
typedef unsigned short u_int16;
typedef unsigned char u_int8;

/*PCAP结构*/
struct pcap_file_header
{
bpf_u_int32 magic;
u_short version_major;
u_short version_minor;
bpf_int32 thiszone;
bpf_u_int32 sigfigs;
bpf_u_int32 snaplen;
bpf_u_int32 linktype;
};

//时间濯
struct time_val
{
long tv_sec;
long tv_usec;
};

struct pcap_pkthdr
{
struct time_val ts;
bpf_u_int32 caplen;
bpf_u_int32 len;
};

//数据桢头
typedef struct FrameHeader_t
{
unsigned char  DstMAC[6];
unsigned char  SrcMAC[6];
u_short FrameType;
}FrameHeader_t;

typedef struct IPHeader_t
{
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;
u_int32 DstIP;
}IPHeader_t;


//TCP数据头
typedef struct TCPHeader_t
{
u_int16 SrcPort;
u_int16 DstPort;
u_int32 SeqNO;
u_int32 AckNO;
u_int8 HeaderLen;
u_int8 Flags;
u_int16 Window;
u_int16 Checksum;
u_int16 UrgentPointer;
}TCPHeader_t;

void match_http(FILE *ftp,char *head_str,char *tail_str,char *buf,int total_len);//查找HTTP信息函数


int main()
{
struct pcap_file_header *file_header;
struct pcap_pkthdr *ptk_header;
FrameHeader_t *frameheader;
IPHeader_t *ip_header;
TCPHeader_t *tcp_header;
FILE *fp, *output;

int pkt_offset,i=0;
int len;
int j;
int ip_len,http_len,ip_proto;
int src_port,dst_port,tcp_flags;
char buf[BUFSIZE],my_time[STRSIZE];
char src_ip[STRSIZE],dst_ip[STRSIZE];
char host[STRSIZE],uri[BUFSIZE],AcceptLanguage[BUFSIZE],UserAgent[BUFSIZE];
char Connection[STRSIZE],TransferEncoding[STRSIZE],ContentEncoding[STRSIZE];
char Contenttype[STRSIZE],CacheControl[STRSIZE],AcceptEncoding[STRSIZE];


file_header =(struct pcap_file_header *)malloc(sizeof(struct pcap_file_header));
ptk_header =(struct pcap_pkthdr *)malloc(sizeof(struct pcap_pkthdr));
frameheader=(struct FrameHeader_t *)malloc(sizeof(FrameHeader_t));
ip_header=(IPHeader_t *)malloc(sizeof(IPHeader_t));
tcp_header=(TCPHeader_t *)malloc(sizeof(TCPHeader_t));
memset(buf,0,sizeof(buf));

if((fp=fopen("/xiaxiao/test.pcap","r"))==NULL)
{
printf("error: can not open pcap file \n");
exit(0);
}

if((output=fopen("/xiaxiao/output.txt","w+"))==NULL)
{
printf("error:can not open putput file \n");
exit(0);
}

//开始读取数据包
pkt_offset=24;
while(fseek(fp,pkt_offset,SEEK_SET)==0)//遍历数据包
{
    i++;

if(fread(ptk_header,16,1,fp)!=1)//读取PCAP数据包结构
{
printf("\n read end of pcap file \n");
break;
}
  pkt_offset+=16+ptk_header->caplen;  // 下一个数据包的偏移值  循环一次加一个caplen的长度,直接跳到下一个数据包。
//读取了数据包头之后才能知道caplen的长度,所以上面那句必须在fread的下面。
  
  //数据包头16字节
strftime(my_time,sizeof(my_time),"%Y-%m-%d %T",localtime(&(ptk_header->ts.tv_sec)));//获取时间
printf("第%d个数据包:\n %s\n",i,my_time);
printf("数据包头信息:\n");
printf(" ptk_header->caplen=%d\n",ptk_header->caplen);
printf(" ptk_header->len=%d\n",ptk_header->len);

//数据桢头14字节
if(fread(frameheader,sizeof(FrameHeader_t),1,fp)!=1)
{
printf("%d:can not read ip_header \n",i);
break;
}
//源MAC,目的MAC不能打出来
printf("数据帧首部信息:\n");
  printf(" frameheader->DstMAC[6]=%.2x",frameheader->DstMAC[0]); //6位变1位了
  printf("%.2x",frameheader->DstMAC[1]);
  printf("%.2x",frameheader->DstMAC[2]);
  printf("%.2x",frameheader->DstMAC[3]);
  printf("%.2x",frameheader->DstMAC[4]);
  printf("%.2x\n",frameheader->DstMAC[5]);   
  printf(" frameheader->SrcMAC[6]=%2x",frameheader->SrcMAC[0]);//6位变1位了
  printf("%2x",frameheader->SrcMAC[1]);
  printf("%2x",frameheader->SrcMAC[2]);
  printf("%2x",frameheader->SrcMAC[3]);
  printf("%2x",frameheader->SrcMAC[4]);
  printf("%2x\n",frameheader->SrcMAC[5]);
  printf(" frameheader->FrameType=%4x\n",ntohs(frameheader->FrameType));  

//IP数据包头20字节
if(fread(ip_header,sizeof(IPHeader_t),1,fp)!=1)
{
printf("%d:can not read ip_header \n",i);
break;
}
printf("数据包首部信息:\n");
/*    printf(" ip_header->Ver_HLen=%x\n",ip_header->Ver_HLen);
printf(" ip_header->TOS=%8d\n",ntohs(ip_header->TOS));
printf(" ip_header->TotalLen=%d\n",ntohs(ip_header->TotalLen));
printf(" ip_header->ID=%d\n",ntohs(ip_header->ID));
printf(" ip_header->Flag_Segment=%x\n",ntohs(ip_header->Flag_Segment));
printf(" ip_header->TTL=%d\n",ip_header->TTL);
printf(" ip_header->Protocol=%d\n",ip_header->Protocol);
printf(" ip_header->Checksum=%x\n",ntohs(ip_header->Checksum));*/



inet_ntop(AF_INET,(void *)&(ip_header->SrcIP),src_ip,16);
inet_ntop(AF_INET,(void *)&(ip_header->DstIP),dst_ip,16);
ip_proto=ip_header->Protocol;
//ip_len=ip_header->TotalLen;//IP数据包总长度
ip_len=ntohs(ip_header->TotalLen);

// printf("ip_len=%d\n",ip_len);
printf(" src=%s\n dst=%s\n ",src_ip,dst_ip);

//if(ip_proto!=0x86)//判断是不是TCP协议
if(ip_proto!=6)//判断是不是TCP协议
{
continue;
}
//TCP头部20字节

if(fread(tcp_header,sizeof(TCPHeader_t),1,fp)!=1)
{
printf("%d:can not read ip_header \n",i);
break;
}

src_port=ntohs(tcp_header->SrcPort);
dst_port=ntohs(tcp_header->DstPort);
tcp_flags=tcp_header->Flags;
printf("TCP首部信息:\n");
    printf(" tcp_header->SrcPort=%d\n",ntohs(tcp_header->SrcPort));
printf(" tcp_header->DstPort=%d\n",ntohs(tcp_header->DstPort));
/*  printf(" tcp_header->SeqNO=%u\n",ntohl(tcp_header->SeqNO));
printf(" tcp_header->AckNO=%u\n",ntohl(tcp_header->AckNO));
printf(" tcp_header->HeaderLen=%x\n",tcp_header->HeaderLen);
printf(" tcp_header->Flags=%x\n",tcp_header->Flags);
printf(" tcp_header->Window=%d\n",ntohs(tcp_header->Window));
printf(" tcp_header->Checksum=%x\n",ntohs(tcp_header->Checksum));
printf(" tcp_header->UrgentPointer=%x\n",tcp_header->UrgentPointer);*/



//printf(" tcp_flags=%x\n",tcp_flags);
// printf(" dst_port=%d\n",dst_port);



/* http_len=ip_len-40;
printf("http_len=%d\n",http_len); */


//if(tcp_flags==0x18)//三次握手成功
if(tcp_flags==24)//三次握手成功,这个在LINUX下会自动将16进制的数字转为10进制,如12->18
{
//if(dst_port==80)//HTTP GET
if(dst_port==80)//HTTP GET
{
http_len=ip_len-40;
 match_http(fp,"HOST","\r\n",host,http_len);//查找URI值
    match_http(fp,"GET","HTTP",uri,http_len);//查找URI值     
  match_http(fp,"User-Agent:","\r\n",UserAgent,http_len);//查找User-Agent值
match_http(fp,"Accept-Language:","\r\n",AcceptLanguage,http_len);//查找Accept-Language值

match_http(fp,"Connection:","\r\n",Connection,http_len);
//match_http(fp,"Transfer-Encoding:","\r\n",TransferEncoding,http_len);
//match_http(fp,"Cache-Control:","\r\n",CacheControl,http_len);
//match_http(fp,"Content-Encoding:","\r\n",ContentEncoding,http_len);
          //match_http(fp,"Content-type:","\r\n",Contenttype,http_len);


sprintf(buf,"%d:\n %s\n 源IP=%s:%d \n 目的IP=%s:%d\n uri=%s\n UserAgent=%s\n AcceptLanguage=%s\n Connection=%s\r\n",i,my_time,src_ip,src_port,dst_ip,dst_port,uri,UserAgent,AcceptLanguage,Connection);

if(fwrite(buf,strlen(buf),1,output)!=1)
{
printf("output file can not write");
break;
}
}
}
}

fclose(fp);
fclose(output);
return 0;
}


//查找HTTP信息
void match_http(FILE *fp,char *head_str,char *tail_str,char *buf,int total_len)
{
int i;
int http_offset;
int head_len,tail_len,val_len;
char head_tmp[STRSIZE],tail_tmp[STRSIZE];
//初始化

memset(head_tmp,0,sizeof(head_tmp));
memset(tail_tmp,0,sizeof(tail_tmp));
head_len=strlen(head_str);
tail_len=strlen(tail_str);


//查找head——str
http_offset=ftell(fp);//记录下HTTP报文初始文件偏移,将指针移动到HTTP数据开始处
//这个http_offset与pkt_offset不相等  为什么???

//printf("http_offset=%d\n",http_offset);

//printf("ftell(fp)=%d\n",ftell(fp));


while((head_tmp[0]=fgetc(fp))!=EOF)//逐个字节遍历
{

if((ftell(fp)-http_offset)>total_len)
{
sprintf(buf,"can not find %s \r\n",head_str);
exit(0);
}

/*if(head_tmp[0]!=*head_str)
{

sprintf(buf,"can not find %s \r\n",head_str);
break;
}
*/
if(head_tmp[0]==*head_str)//匹配到第一个字符
{
  for(i=1;i<head_len;i++)
 {
    head_tmp[i]=fgetc(fp);
    if(head_tmp[i]!=*(head_str+i))
    break;
 }
  if(i==head_len)//匹配head——str成功,停止遍历
  break;
 }
}

//printf("head_tmp=%s \n",head_tmp);

//查找tail——str

val_len=0;
while((tail_tmp[0]=fgetc(fp))!=EOF)// 遍历
{
if((ftell(fp) - http_offset)>total_len)//遍历完成
{
sprintf(buf,"can not find %s \r\n",tail_str);
exit(0);
}


buf[val_len++]=tail_tmp[0];//用BUFF存贮VALUE直到查找到TAIL——STR
if(tail_tmp[0]==*tail_str)
{
for(i=1;i<tail_len;i++)
{
tail_tmp[i]=fgetc(fp);
if(tail_tmp[i]!=*(tail_str+i))
break;
}

if(i==tail_len)
{
buf[val_len-1]=0;
break;
}
}
}


printf("val=%s \n",buf);

fseek(fp,http_offset,SEEK_SET);// 将文件指针回到初始偏移
}




这个程序,由于我的.pcap文件里面第7个数据包没有HOST这个值,所以直接就退出了程序。
我就想把这程序的match_http这个函数修改下,使他在查找head_tmp的时候,如果没有找到这个关键字,就退出,并继续执行下面的代码程序。求哪位大神指教指教啊。。。



4 个解决方案

#1


这个,弄了半天,整出来了。。。把那个exit(0)改成break就对了

#2


直接下个wireshark好了。还有费这个劲,写代码?

#3


该回复于2012-08-10 14:31:53被版主删除

#4


在VC++6.0中这个能编译吗

#1


这个,弄了半天,整出来了。。。把那个exit(0)改成break就对了

#2


直接下个wireshark好了。还有费这个劲,写代码?

#3


该回复于2012-08-10 14:31:53被版主删除

#4


在VC++6.0中这个能编译吗