c语言Winpcap编程构造并接收解析arp包

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

c语⾔Winpcap编程构造并接收解析arp包
/*
程序功能:
1、构造arp包,并发送。

程序参数顺序:源IP、⽬的IP、mac地址、flag
2、获取⽹络中的ARP数据包,解析数据包的内容。

程序参数:⽇志⽂件名
*/
⼀、构造arp包
在构造之前先了解⼀下arp包的结构,先从⽹上找了张图
从图中可以看出以太⽹⾸部占14字节,以太⽹ARP字段占28字节。

其中op字段为操作类型,1表⽰ARP请求、2表⽰ARP应答
再介绍⼏个要⽤到的pcap函数
1. int pcap_findalldevs ( pcap_if_t ** alldevsp, char * errbuf)
函数功能:列出当前所有可⽤的⽹络设备(⽹卡),将设备信息存⼊pcap_if_t结构列表中
参数:1、alldevsp 指向pcap_if_t结构列表的指针的地址(注意这⾥是pcap_if_t指针的地址,⽽不是pcap_if_t结构的地址)
有些地⽅这⾥可能会写pcap_if结构,其实pcap_if和pcap_if_t就是同⼀个东西,我们来看看在pcap.h中是怎么定义的
pcap_if结构体成员:
Struct pcap_if {
struct pcap_if *next; //指向下⼀个链表成员
char *name; //⽹卡名称
chat *description; //⽹卡描述信息
struct pcap_addr address;
u_int flags; //接⼝标志
}
2、errbuf 错误缓冲区,要求长度⾄少为PCAP_ERRBUF_SIZE 字节,那么PCAP_ERRBUF_SIZE是多⼤呢
这在pcap.h中宏定义的,如下图
这个错误缓冲区⽤来做什么呢?在函数错误返回时(返回值为-1)会向错误缓冲中填充错误信息,错误信息为可打印ASCII码 函数正确时返回0
2、pcap_t * pcap_open_live ( char * device, int snaplen, int promisc,int to_ms, char * errbuf )
函数功能:在⽹络中打开⼀个活动的捕获<这是winpcap技术⽂档给出的说明,也就是指定从⼀个⽹络设备捕获数据包,我是这么理解的> 函数的返回值为⼀个结构体指针pcap_t即为struct pcap。

pcap_t结构体有点长就不做说明了,⾥⾯就是捕获句柄的⼀些信息
参数: <⽂档是英⽂的不知道有没有翻译对>
device 设备名
snaplen 单包最⼤捕捉字节数(若数据包⼤于snaplen,只有前⾯snaplen字节⼤⼩的数据被捕获)
promisc 混杂模式(即使该参数是false,也可能由其他原因导致⽹络接⼝为混杂模式)
to_ms 指定毫秒级读超时(当⼀个数据包被发现时,并不⼀定⽴即返回数据包,它会等待⼀段时间,允许⼀个操作从系统内核读取多个数据 包。

不是所有的平台都⽀持读超时,在不⽀持的平台上读超时会被忽略。

)<在⽀持读超时的平台上若读超时为0,将导致永不超时>
errbuf ⽤于返回错误或警告信息
3、void pcap_close ( pcap_t *p )
关闭pcap_open_live()获取的包捕获句柄,释放相关资源
源码:
1/*
2构造并发送ARP包
32015年6⽉24⽇15:44:21
4blog:/wd1001/
5*/
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <pcap.h>
9
10#pragma comment(lib, "wpcap.lib")
11#pragma comment(lib, "wsock32.lib")
12#pragma comment(lib, "ws2_32.lib")
13
14 main(int argc, char **argv)
15 {
16 u_char packet[100];
17 pcap_if_t *alldevs;
18 pcap_if_t *d;
19int inum;
20int i=0,j,k,temp[3];
21 pcap_t * adhandle;
22char errbuf[PCAP_ERRBUF_SIZE];
23/* 获取设备列表 */
24
25if (argc != 5)//argc==5,及程序后⾯有四个参数
26 {
27 printf("usage: %s inerface", argv[0]);
28return -1;
29 }
30
31
32if (pcap_findalldevs(&alldevs, errbuf) == -1)
33 {
34 fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
35 exit(1);
36 }
37/* 数据列表 */
38for(d=alldevs; d; d=d->next)
39 {
40 printf("%d. %s", ++i, d->name);
41if (d->description)
42 printf(" (%s)\n", d->description);
43else
44 printf(" (No description available)\n");
45 }
46if(i==0)
47 {
48 printf("\n找不到⽹卡! 检查是否安装WinPcap.\n");
49return -1;
50 }
51 printf("Enter the interface number (1-%d):",i);
52 scanf("%d", &inum);
53if(inum < 1 || inum > i)
54 {
55 printf("\nInterface number out of range.\n");
56/* 释放设备列表 */
57 pcap_freealldevs(alldevs);
58return -1;
59 }
60/* 转到选择的设备 */
61for(d=alldevs, i=0; i< inum-1;d=d->next, i++);
62/* 打开设备 */
63if ( (adhandle= pcap_open_live(d->name, //设备名
6465536, // 最⼤捕捉字节数
651, // 混杂模式
661000, // 读⼊超时
67 errbuf // 错误缓冲
68 ) ) == NULL)
69 {
70/*打开失败*/
71 fprintf(stderr,"\n打开失败. %s 不被winpcap⽀持\n",d->name);
72/* 释放列表 */
73 pcap_freealldevs(alldevs);
74return -1;
75 }
76/* 释放设备列表 */
77 pcap_freealldevs(alldevs);
78
79/* 填充数据段 */
80
81//flag为1表⽰ARP请求
82if('1'==argv[4][0])
83 {
84//源MAC地址
85 k=0;
86for(i=0;i<18;i=i+3)
87 {
88 temp[0]=(int)argv[3][i];
89 temp[1]=(int)argv[3][i+1];
90if(temp[0]>96) //当输⼊mac为⼩写字母时字符转换为16进制 91 temp[0]=temp[0]-87;
92else if(temp[0]>64)
93 temp[0]=temp[0]-55;//当输⼊mac为⼤写字母时字符转换为16进制 94else
95 temp[0]=temp[0]-48;//当输⼊mac为数字时字符转换为16进制
96if(temp[1]>96)
97 temp[1]=temp[1]-87;
98else if(temp[1]>64)
99 temp[1]=temp[1]-55;
100else
101 temp[1]=temp[1]-48;
102 packet[22+k]=packet[6+k]=temp[0]*16+temp[1];
103 k++;
104 }
105
106//发送ARP请求时⽬的MAC全置为ff
107for(i=0;i<6;i++)
108 {
109 packet[i]=packet[32+i]=0xff;
110 }
111 }
112
113//flag=2:ARP应答
114else
115 {
116//⽬的MAC地址
117 k=0;
118for(i=0;i<18;i=i+3)
119 {
120 temp[0]=(int)argv[3][i];
121 temp[1]=(int)argv[3][i+1];
122if(temp[0]>96)
123 temp[0]=temp[0]-87;
124else if(temp[0]>64)
125 temp[0]=temp[0]-55;
126else
127 temp[0]=temp[0]-48;
128if(temp[1]>96)
129 temp[1]=temp[1]-87;
130else if(temp[1]>64)
131 temp[1]=temp[1]-55;
132else
133 temp[1]=temp[1]-48;
134 packet[k]=packet[32+k]=temp[0]*16+temp[1];
135 k++;
136 }
137//应答ARP请求时把源MAC置为0
138for(i=0;i<6;i++)
139 {
140 packet[6+i]=packet[22+i]=0x00;
141 }
142 }
143
144//源IP地址
145 k=0;
146 temp[2]=0; //指向每个字节初始位置
147for(i=0;i<4;i++)
148 {
149 temp[0]=0;
150 temp[1]=0;
151for(j=0;j<4;j++)
152 {
153if(argv[1][j+temp[2]]>='0'&&argv[1][j+temp[2]]<='9')
154 {
155 temp[0]=(int)argv[1][j+temp[2]]-48;
156 temp[1]=temp[1]*10+temp[0];
157//printf("%d %d\n",temp[0],temp[1]);
158 }
159else
160 {
161//当遇到点时j⾃加1⽬的是让temp[2]+j指向下⼀字节的第⼀位162 j++;
163break;
164 }
165 }
166 packet[28+k]=temp[1];
167 k++;
168 temp[2]+=j;
169 }
170//⽬标IP地址
171 k=0;
172 temp[2]=0;
173for(i=0;i<4;i++)
174 {
175 temp[0]=0;
176 temp[1]=0;
177for(j=0;j<4;j++)
178 {
179if(argv[2][j+temp[2]]>='0'&&argv[2][j+temp[2]]<='9')
180 {
181 temp[0]=(int)argv[2][j+temp[2]]-48;
182 temp[1]=temp[1]*10+temp[0];
183//printf("%d %d\n",temp[0],temp[1]);
184 }
185else
186 {
187 j++;
188break;
189 }
190 }
191 packet[38+k]=temp[1];
192 k++;
193 temp[2]+=j;
194 }
195//ARP⾸部
196 packet[12]=0x08;//12、13位为帧类型
197 packet[13]=0x06;
198 packet[14]=0x00;//14、15位为硬件类型
199 packet[15]=0x01;
200 packet[16]=0x08;//16、17位为协议类型
201 packet[17]=0x00;
202 packet[18]=0x06;//硬件地址长度
203 packet[19]=0x04;//协议地址长度
204 packet[20]=0x00;//op
205 packet[21]=(int)argv[4][0]-48;//op(1为请求2为应答)
206
207
208/* 填充发送包的剩余部分 */
209for(i=0;i<18;i++)
210 {
211 packet[42+i]=0;
212 }
213//这⾥后四个字节本应该是校验位,这⾥就不算了,写个⽇期纪念⼀下214 packet[60]=0x20;
215 packet[61]=0x15;
216 packet[62]=0x6;
217 packet[63]=0x24;
218/* 发送包 */
219 pcap_sendpacket(adhandle, packet, 64);
220 printf("Success!\n");
221
222return0;
223 }
运⾏结果:
输⼊参数:随意设置源IP,⽬的IP和mac地址
选择⽹卡并发送,抓包结果如下
⼆、获取⽹络中的ARP数据包,解析数据包的内容
在上⾯的基础上再解析ARP数据包就简单了
同样在解析前先介绍⼏个要⽤到的函数
1、int pcap_compile ( pcap_t * p, struct bpf_program * fp, char * str,int optimize , bpf_u_int32 netmask )
函数功能:将字符串str编译进⼀个过滤程序,将程序中⾼级的过滤表达式,转换成能被内核级的过滤引擎所处理的东西参数:1、p为pcap_open_live返回的⼀个捕获句柄
2、fp为⼀个指向bpf_program结构的指针,由pcap_compile()函数填写
bpf_program结构为:
struct bpf_program {
u_int bf_len;
struct bpf_insn *bf_insns;
};
bpf_insn结构为:
struct bpf_insn {
u_short code;
u_char jt;
u_char jf;
bpf_int32 k;
};
3、str 过滤串表达式
4、optimize 优化控制,是否执⾏结果代码优化(optimize controls whether optimization on the resulting code is performed)
5、netmask ⼦⽹掩码
2、int pcap_setfilter (pcap_t *p, struct bpf_program *fp)
函数功能:在捕获过程中绑定⼀个过滤器
源码:
1/*
2获取⽹络中的ARP数据包,解析数据包的内容
32015年6⽉24⽇19:36:36
4blog:/wd1001/
5*/
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <pcap.h>
9#pragma comment(lib, "wpcap.lib")
10#pragma comment(lib, "wsock32.lib")
11#pragma comment(lib, "ws2_32.lib")
12//定义ARP包数据
13 typedef struct arppkt
14 {
15 unsigned short hdtyp;//硬件类型
16 unsigned short protyp;//协议类型
17 unsigned char hdsize;//硬件地址长度
18 unsigned char prosize;//协议地址长度
19 unsigned short op;//(操作类型)操作值:ARP/RARP
20 u_char smac[6];//源MAC地址
21 u_char sip[4];//源IP地址
22 u_char dmac[6];//⽬的MAC地址
23 u_char dip[4];//⽬的IP地址
24 }arpp;
25int main(int argc,char * argv[] )
26 {
27struct tm * timeinfo;
28struct tm *ltime;
29 time_t rawtime;
30 FILE * fp=NULL;
32int i=0,inum;
33 pcap_if_t * alldevs;//指向pcap_if_t结构列表指针
34 pcap_if_t * d;
35 pcap_t * adhandle;//定义包捕捉句柄
36char errbuf[PCAP_ERRBUF_SIZE];//错误缓冲最⼩为256
37 u_int netmask; //定义⼦⽹掩码
38char packet_filter[]="ether proto \\arp";
39struct bpf_program fcode;
40struct pcap_pkthdr * header;
41const u_char * pkt_data;
42//打开⽇志⽂件
43if((fp=fopen(argv[1],"a"))==NULL)
44 {
45 printf("打开⽂件失败!\n");
46 exit(0);
47 }
48if (argc != 2)//argc==2,及程序后⾯有1个参数
49 {
50 printf("程序%s需要⼀个⽇志⽂件名参数!\n", argv[0]);
51return -1;
52 }
53//当前所有可⽤的⽹络设备
54if (pcap_findalldevs(&alldevs, errbuf) == -1)
55 {
56 fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
57 exit(1);
58 }
59//列出⽹络设备
60for(d=alldevs; d; d=d->next)
61 {
62 printf("%d. %s", ++i, d->name);
63if (d->description)
64 printf(" (%s)\n", d->description);
65else
66 printf(" (没有描述可⽤)\n");
67 }
68if(i==0)
69 {
70 printf("\n找不到⽹卡! 检查是否安装WinPcap.\n");
71return -1;
72 }
73 printf("选择对应⽹卡编号 (1-%d):",i);
74 scanf("%d", &inum);
75if(inum < 1 || inum > i)
76 {
77 printf("\n输⼊的编号超出范围!\n");
78/* 释放设备列表 */
79 pcap_freealldevs(alldevs);
80return -1;
81 }
82/* 转到选择的设备 */
83 i=0;
84 d=alldevs;
85while(i<inum-1)
86 {
87 d=d->next;
88 i++;
89 }
90if ( (adhandle= pcap_open_live(d->name,65536, 1,1000,errbuf) ) == NULL) 91 {
92/*打开失败*/
93 fprintf(stderr,"\n打开失败. %s 不被winpcap⽀持\n",d->name);
94/* 释放设备列表 */
95 pcap_freealldevs(alldevs);
96return -1;
97 }
98/* 释放设备列表 */
99 pcap_freealldevs(alldevs);
100
101//获得⼦⽹掩码
102 netmask=((sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr; 103//编译过滤器,只捕获ARP包
104if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)<0)
105 {
106 printf("\nUnable to compile the packet filter.Check the syntax.\n");
107 pcap_freealldevs(alldevs);
108return -1;
109 }
110//设置过滤器
111if(pcap_setfilter(adhandle,&fcode)<0)
112 {
113 printf("\nError setting the filter.\n");
114 pcap_freealldevs(alldevs);
116 }
117//输出每次修改⽂件时间
118 time ( &rawtime );
119 timeinfo = localtime ( &rawtime );
120 printf("--------------修改时间:%s",asctime (timeinfo));
121 fprintf(fp,"-----------修改时间:%s",asctime (timeinfo));
122 fflush(fp);//刷新缓冲流
123while((result=pcap_next_ex(adhandle,&header,&pkt_data))>=0) 124 {
125//循环解析ARP数据包
126if(result==0)
127continue;
128//解析ARP包,结果输出到屏幕与⽂件
129 arppkt* arph = (arppkt *)(pkt_data +14);
130//输出操作时间
131 ltime=localtime(&header->_sec);
132 printf("时间:%s",asctime (ltime));
133 fprintf(fp,"时间:%s",asctime (ltime));
134//输出源IP
135 printf("源IP:");
136 fprintf(fp,"源IP:");
137for(i=0;i<3;i++)
138 {
139 printf("%d.",arph->sip[i]);
140 fprintf(fp,"%d.",arph->sip[i]);
141 }
142 printf("%d\t",arph->sip[3]);
143 fprintf(fp,"%d.\t",arph->sip[3]);
144//输出⽬的IP
145 printf("⽬的IP:");
146 fprintf(fp,"⽬的IP:");
147for(i=0;i<3;i++)
148 {
149 printf("%d.",arph->dip[i]);
150 fprintf(fp,"%d.",arph->dip[i]);
151 }
152 printf("%d\t",arph->dip[3]);
153 fprintf(fp,"%d\t",arph->dip[3]);
154//输出源mac
155 printf("源mac:");
156 fprintf(fp,"源mac:");
157for(i=0;i<5;i++)
158 {
159 printf("%x-",arph->smac[i]);
160 fprintf(fp,"%x-",arph->smac[i]);
161 }
162 printf("%x\t",arph->smac[5]);
163 fprintf(fp,"%x\t",arph->smac[5]);
164//输出⽬的mac
165 printf("⽬的mac:");
166 fprintf(fp,"⽬的mac:");
167for(i=0;i<5;i++)
168 {
169 printf("%x-",*(pkt_data+i));
170 fprintf(fp,"%x-",*(pkt_data+i));
171 }
172 printf("%x\t",*(pkt_data+5));
173 fprintf(fp,"%x\t",*(pkt_data+5));
174//输出操作类型
175 printf("操作类型(ARP/RARP):");
176 fprintf(fp,"操作类型(ARP/RARP):");
177if(arph->op==256)
178 {
179 printf("ARP\t");
180 fprintf(fp,"ARP\t");
181 }
182else
183 {
184 printf("RARP\t");
185 fprintf(fp,"RARP\t");
186 }
187 printf("\n");
188 fprintf(fp,"\n");
189 printf("--------------------------------------\n");
190 fprintf(fp,"--------------------------------------\n");
191 fflush(fp);
192 }
193 fclose(fp);
194return0;
195 }。

相关文档
最新文档