c语言编程题报文解析,C语言解析HTTP_POST PCAP 格式包(邮件发送)

本文档展示了如何使用C语言解析PCAP文件,通过Wireshark抓包得到test.pcap,然后逐层解析文件头、数据包头、帧头、IP头、TCP头,最终提取HTTP信息。程序会查找HTTP请求中的特定字段,如Host、GET、content等,并进行URL解码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、

C语言实现PCAP文件分析

实现步骤:1)用Wireshark软件抓包得到test.pcap文件2)程序:分析pcap文件头

->

分析pcap_pkt头

->

分析帧头 ->

分析ip头

->

分析tcp头

->

分析http信息

#include "stdio.h"

#include "string.h"

#include "stdlib.h"

#include "netinet/in.h"

#include "sys/types.h"

#include "sys/socket.h"

#include "arpa/inet.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;

//pacp文件头结构体

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;

};

//pcap数据包头结构体

struct

pcap_pkthdr

{

struct time_val ts;

bpf_u_int32

caplen;

bpf_u_int32 len;

};

//数据帧头

typedef struct

FramHeader_t

{

//Pcap捕获的数据帧头

u_int8 DstMAC[6];

//目的MAC地址

u_int8 SrcMAC[6];

//源MAC地址

u_short FrameType;

//帧类型

}

FramHeader_t;

//IP数据报头

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数据报头

typedef struct

TCPHeader_t

{ //TCP数据报头

u_int16 SrcPort;

//源端口

u_int16 DstPort;

//目的端口

u_int32 SeqNO;

//序号

u_int32 AckNO;

//确认号

u_int8 HeaderLen; //数据报头的长度(4

bit) + 保留(4 bit)

u_int8 Flags;

//标识TCP不同的控制消息

u_int16 Window;

//窗口大小

u_int16 Checksum;

//校验和

u_int16 UrgentPointer;

//紧急指针

}TCPHeader_t;

//

void match_http(FILE *fp, char

*head_str, char *tail_str, char *buf, int total_len); //查找 http

信息函数

void urldecode(char *p);

//

int main()

{

struct pcap_file_header

*file_header;

struct pcap_pkthdr

*ptk_header;

IPHeader_t

*ip_header;

TCPHeader_t

*tcp_header;

FILE *fp,

*output;

int  pkt_offset, i=0;

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];

characcount[STRSIZE],

sendto[BUFSIZE],subject[BUFSIZE],sendcc[BUFSIZE],content[BUFSIZE];

//初始化

file_header = (struct

pcap_file_header *)malloc(sizeof(struct

pcap_file_header));

ptk_header  =

(struct pcap_pkthdr *)malloc(sizeof(struct

pcap_pkthdr));

ip_header = (IPHeader_t

*)malloc(sizeof(IPHeader_t));

tcp_header = (TCPHeader_t

*)malloc(sizeof(TCPHeader_t));

memset(buf, 0,

sizeof(buf));

//

if((fp =

fopen("test.pcap","r")) == NULL)

{

printf("error: can not open

pcap file\n");

exit(0);

}

if((output =

fopen("output.txt","w+")) == NULL)

{

printf("error: can not open

output file\n");

exit(0);

}

//开始读数据包

pkt_offset = 24; //pcap文件头结构

24个字节

while(fseek(fp, pkt_offset,

SEEK_SET) == 0) //遍历数据包

{

i++;

//pcap_pkt_header 16

byte

if(fread(ptk_header, 16, 1,

fp) != 1) //读pcap数据包头结构

{

printf("\nread end of pcap

file\n");

break;

}

pkt_offset += 16 +

ptk_header->caplen;  //下一个数据包的偏移值

strftime(my_time,

sizeof(my_time), "%Y-%m-%d %T",

localtime(&(ptk_header->ts.tv_sec)));

//获取时间

// printf("%d: %s\n", i,

my_time);

//数据帧头 14字节

fseek(fp, 14, SEEK_CUR);

//忽略数据帧头

//IP数据报头

20字节

if(fread(ip_header,

sizeof(IPHeader_t), 1, fp) != 1)

{

printf("%d: can not read

ip_header\n", i);

break;

}

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数据报总长度

printf("%d:

src=%s\n", i, src_ip);

printf("%d:

dst=%s\n", i, dst_ip);

if(ip_proto != 0x06) //判断是否是

TCP 协议

{

continue;

}

printf("ip_proto =

%0x\n",ip_proto);

//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);

printf("dst_port =

%d\n",dst_port);

tcp_flags =

tcp_header->Flags;

printf("%d:

src=%x\n", i, tcp_flags);

if(tcp_flags == 0x18) // (PSH,

ACK) 3路握手成功后

{

if(dst_port == 80) // HTTP

GET请求

{

http_len = ip_len - 40; //http

报文长度

//match_http(fp, "Host: ",

"\r\n", host, http_len); //查找 host 值

//match_http(fp, "GET ",

"HTTP", uri, http_len); //查找 uri 值

match_http(fp, "content=",

"&",content, http_len); //查找 uri 值

match_http(fp, "subject=",

"&",subject, http_len); //查找 uri 值

match_http(fp, "account=",

"&",account, http_len); //查找 uri

match_http(fp, "to=",

"&",sendto, http_len); //查找 uri 值

match_http(fp, "cc=",

"&",sendcc, http_len); //查找 uri 值

urldecode(account);

urldecode(sendto);

urldecode(subject);

urldecode(content);

urldecode(sendcc);

sprintf(buf, "%d:

%s  src=%s:%d

dst=%s:%d  from:%s

to:%s  cc:%s

subject = %s  content= %s\r\n",

i, my_time, src_ip, src_port, dst_ip,

dst_port,account, sendto,

sendcc,subject,content);

//printf("host = %s\n,uri = %s

\n",host,uri);

if(fwrite(buf, strlen(buf), 1,

output) != 1)

{

printf("output file can not

write");

break;

}

}

}

} // end

while

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报文初始文件偏移

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)

//匹配到第一个字符

{

for(i=1; 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];

//用buf 存储 value 直到查找到 tail_str

if(tail_tmp[0] == *tail_str)

//匹配到第一个字符

{

for(i=1; i

{

tail_tmp[i]=fgetc(fp);

if(tail_tmp[i] !=

*(tail_str+i))

break;

}

if(i == tail_len) //匹配

head_str 成功,停止遍历

{

buf[val_len-1] = 0;

//清除多余的一个字符

break;

}

}

}

printf("val=%s\n",

buf);

fseek(fp, http_offset,

SEEK_SET); //将文件指针 回到初始偏移

}

void urldecode(char *p)

{

register i=0;

while(*(p+i))

{

if ((*p=*(p+i)) == '%')

{

*p=*(p+i+1) >= 'A' ? ((*(p+i+1) & 0XDF) -

'A') + 10 : (*(p+i+1) - '0');

*p=(*p) * 16;

*p+=*(p+i+2) >= 'A' ? ((*(p+i+2) & 0XDF)

- 'A') + 10 : (*(p+i+2) - '0');

i+=2;

}

else if (*(p+i)=='+')

{

*p=' ';

}

p++;

}

*p='\0';

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值