当前位置:   article > 正文

Winpcap数据包的抓取及还原_清空pcap_next_ex中pkt_data指向的缓存

清空pcap_next_ex中pkt_data指向的缓存

转载:https://blog.csdn.net/x_white/article/details/8545593

winpcap技术手册,除了安装文件里doc文件下有个帮助,这里在给一个:http://www.ferrisxu.com/WinPcap/html/index.html

这里我们用pcap_next_ex 函数抓取到数据包后,我们就要开始提取其中的关键信息了,这里我保存在了pkt_data里,之后又传到了处理函数中

代码如下,我也已经写的很清楚了。其中MAC地址是在数据链路层获取的,其他的诸如端口号,IP等都是通过分析IP包和TCP包获取。

唯一需要注意的就是在定义结构体的时候要注意字节的大小,不然获取的信息就是错误的了。

  1. #include <stdio.h>
  2. #include <iostream>
  3. #define HAVE_REMOTE
  4. #include "pcap.h"
  5. #include "remote-ext.h"
  6. #pragma comment(lib, "Ws2_32.lib")
  7. #pragma comment(lib, "wpcap.lib")
  8. using namespace std;
  9. FILE* fp;
  10. // 以太网协议格式的定义
  11. typedef struct ether_header {
  12. u_char ether_dhost[6]; // 目标地址
  13. u_char ether_shost[6]; // 源地址
  14. u_short ether_type; // 以太网类型
  15. }ether_header;
  16. // 用户保存4字节的IP地址
  17. typedef struct ip_address {
  18. u_char byte1;
  19. u_char byte2;
  20. u_char byte3;
  21. u_char byte4;
  22. }ip_address;
  23. // 用于保存IPV4的首部
  24. typedef struct ip_header {
  25. #ifdef WORDS_BIGENDIAN
  26. u_char ip_version : 4, header_length : 4;
  27. #else
  28. u_char header_length : 4, ip_version : 4;
  29. #endif
  30. u_char ver_ihl; // 版本以及首部长度,各4位
  31. u_char tos; // 服务质量
  32. u_short tlen; // 总长度
  33. u_short identification; // 身份识别
  34. u_short offset; // 分组偏移
  35. u_char ttl; // 生命周期
  36. u_char proto; // 协议类型
  37. u_short checksum; // 包头测验码
  38. ip_address saddr; // 源IP地址
  39. ip_address daddr; // 目的IP地址
  40. u_int op_pad; //可选 填充字段
  41. }ip_header;
  42. // 保存TCP首部
  43. typedef struct tcp_header {
  44. u_short sport;
  45. u_short dport;
  46. u_int sequence; // 序列码
  47. u_int ack; // 回复码
  48. #ifdef WORDS_BIGENDIAN
  49. u_char offset : 4, reserved : 4; // 偏移 预留
  50. #else
  51. u_char reserved : 4, offset : 4; // 预留 偏移
  52. #endif
  53. u_char flags; // 标志
  54. u_short windows; // 窗口大小
  55. u_short checksum; // 校验和
  56. u_short urgent_pointer; // 紧急指针
  57. }tcp_header;
  58. typedef struct udp_header {
  59. u_int32_t sport; // 源端口
  60. u_int32_t dport; // 目标端口
  61. u_int8_t zero; // 保留位
  62. u_int8_t proto; // 协议标识
  63. u_int16_t datalen; // UDP数据长度
  64. }udp_header;
  65. typedef struct icmp_header {
  66. u_int8_t type; // ICMP类型
  67. u_int8_t code; // 代码
  68. u_int16_t checksum; // 校验和
  69. u_int16_t identification; // 标识
  70. u_int16_t sequence; // 序列号
  71. u_int32_t init_time; // 发起时间戳
  72. u_int16_t recv_time; // 接受时间戳
  73. u_int16_t send_time; // 传输时间戳
  74. }icmp_header;
  75. typedef struct arp_header {
  76. u_int16_t arp_hardware_type;
  77. u_int16_t arp_protocol_type;
  78. u_int8_t arp_hardware_length;
  79. u_int8_t arp_protocol_length;
  80. u_int16_t arp_operation_code;
  81. u_int8_t arp_source_ethernet_address[6];
  82. u_int8_t arp_source_ip_address[4];
  83. u_int8_t arp_destination_ethernet_address[6];
  84. u_int8_t arp_destination_ip_address[4];
  85. }arp_header;
  86. void tcp_protocol_packet_handle(
  87. u_char *argument,
  88. const struct pcap_pkthdr *packet_header,
  89. const u_char *packet_content
  90. ) {
  91. struct tcp_header *tcp_protocol;
  92. u_short sport;
  93. u_short dport;
  94. int header_length;
  95. u_short windows;
  96. u_short urgent_pointer;
  97. u_int sequence;
  98. u_int acknowledgement;
  99. u_short checksum;
  100. u_char flags;
  101. printf("===========TCP Protocol===========\n");
  102. tcp_protocol = (struct tcp_header*)(packet_content + 14 + 20);
  103. sport = ntohs(tcp_protocol->sport);
  104. dport = ntohs(tcp_protocol->dport);
  105. header_length = tcp_protocol->offset * 4;
  106. sequence = ntohl(tcp_protocol->sequence);
  107. acknowledgement = ntohl(tcp_protocol->ack);
  108. windows = ntohs(tcp_protocol->windows);
  109. urgent_pointer = ntohs(tcp_protocol->urgent_pointer);
  110. flags = tcp_protocol->flags;
  111. checksum = ntohs(tcp_protocol->checksum);
  112. fprintf(fp, "%d0%d%d%c%d", header_length, sport, dport, flags, windows);
  113. switch(dport) {
  114. default:
  115. break;
  116. }
  117. if(flags & 0x08) printf("PSH");
  118. if(flags & 0x10) printf("ACK");
  119. if(flags & 0x02) printf("SYN");
  120. if(flags & 0x20) printf("URG");
  121. if(flags & 0x01) printf("FIN");
  122. if(flags & 0x04) printf("RST");
  123. printf("\n");
  124. }
  125. void udp_protocol_packet_handle(
  126. u_char *argument,
  127. const struct pcap_pkthdr *packet_header,
  128. const u_char *packet_content
  129. ) {
  130. struct udp_header* udp_protocol;
  131. u_short sport;
  132. u_short dport;
  133. u_short datalen;
  134. udp_protocol = (struct udp_header*)(packet_content + 14 + 20);
  135. sport = ntohs(udp_protocol->sport);
  136. dport = ntohs(udp_protocol->dport);
  137. datalen = ntohs(udp_protocol->datalen);
  138. fprintf(fp, "0%d%d%d",datalen, sport, dport);
  139. }
  140. void arp_protocol_packet_handle(
  141. u_char *argument,
  142. const struct pcap_pkthdr *packet_header,
  143. const u_char *packet_content
  144. ) {
  145. struct arp_header *arp_protocol;
  146. u_short protocol_type;
  147. u_short hardware_type;
  148. u_short operation_code;
  149. u_char hardware_length;
  150. u_char protocol_length;
  151. struct tm* ltime;
  152. char timestr[16];
  153. time_t local_tv_sec;
  154. local_tv_sec = packet_header->ts.tv_sec;
  155. ltime = localtime(&local_tv_sec);
  156. strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
  157. printf("-------- ARP协议 --------\n");
  158. arp_protocol = (struct arp_header*)(packet_content + 14);
  159. hardware_type = ntohs(arp_protocol->arp_hardware_type);
  160. protocol_type = ntohs(arp_protocol->arp_protocol_type);
  161. operation_code = ntohs(arp_protocol->arp_operation_code);
  162. hardware_length = arp_protocol->arp_hardware_length;
  163. protocol_length = arp_protocol->arp_protocol_length;
  164. fprintf(fp, "%d%s", protocol_length, timestr);
  165. switch (operation_code)
  166. {
  167. case 1:
  168. printf("ARP请求协议\n");
  169. break;
  170. case 2:
  171. printf("ARP应答协议\n");
  172. break;
  173. case 3:
  174. printf("RARP请求协议\n");
  175. break;
  176. case 4:
  177. printf("RARP应答协议\n");
  178. break;
  179. default:
  180. break;
  181. }
  182. }
  183. void icmp_protocol_packet_handle(
  184. u_char *argument,
  185. const struct pcap_pkthdr *packet_header,
  186. const u_char *packet_content
  187. ) {
  188. struct icmp_header *icmp_protocol;
  189. u_short type;
  190. u_short datalen;
  191. u_int init_time;
  192. u_int recv_time;
  193. u_int send_time;
  194. icmp_protocol = (struct icmp_header*)(packet_content + 14 + 20);
  195. datalen = sizeof(icmp_protocol);
  196. type = icmp_protocol->type;
  197. init_time = icmp_protocol->init_time;
  198. recv_time = icmp_protocol->recv_time;
  199. send_time = icmp_protocol->send_time;
  200. fprintf(fp, "%d%c%d%d%d", datalen, type, init_time, recv_time, send_time);
  201. // printf("===========ICMP Protocol==========\n");
  202. switch(icmp_protocol->type) {
  203. case 8:
  204. // 回显请求报文
  205. break;
  206. case 0:
  207. // 回显应答报文
  208. break;
  209. default:
  210. break;
  211. }
  212. }
  213. void ip_protocol_packet_handle(
  214. u_char *argument,
  215. const struct pcap_pkthdr *packet_header,
  216. const u_char *packet_content
  217. ) {
  218. struct ip_header *ip_protocol;
  219. u_int header_length;
  220. u_char tos;
  221. u_short checksum;
  222. ip_address saddr;
  223. ip_address daddr;
  224. u_char ttl;
  225. u_short tlen;
  226. u_short identification;
  227. u_short offset;
  228. printf("===========IP Protocol===========\n");
  229. ip_protocol = (struct ip_header*)(packet_content + 14);
  230. header_length = ip_protocol->header_length * 4;
  231. checksum = ntohs(ip_protocol->checksum);
  232. tos = ip_protocol->tos;
  233. offset = ntohs(ip_protocol->offset);
  234. saddr = ip_protocol->saddr;
  235. daddr = ip_protocol->daddr;
  236. ttl = ip_protocol->ttl;
  237. identification = ip_protocol->identification;
  238. tlen = ip_protocol->tlen;
  239. offset = ip_protocol->offset;
  240. fprintf(fp, "%d%d%c%d%d%d", saddr, daddr, ttl, identification, tlen, offset);
  241. switch(ip_protocol->proto) {
  242. case 6:
  243. tcp_protocol_packet_handle(argument, packet_header, packet_content);
  244. break;
  245. case 17:
  246. udp_protocol_packet_handle(argument, packet_header, packet_content);
  247. break;
  248. case 1:
  249. icmp_protocol_packet_handle(argument, packet_header, packet_content);
  250. break;
  251. default:
  252. break;
  253. }
  254. }
  255. void ethernet_protocol_packet_handle (
  256. u_char *argument,
  257. const struct pcap_pkthdr *packet_header,
  258. const u_char *packet_content
  259. ) {
  260. u_short ethernet_type; // 以太网类型
  261. struct ether_header *ethernet_protocol; // 以太网协议变量
  262. u_char *mac_string; // 以太网地址
  263. ethernet_protocol = (struct ether_header*)packet_content; // 获取以太网数据内容
  264. printf("Ethernet type is : \n");
  265. ethernet_type = ntohs(ethernet_protocol->ether_type); // 获取以太网类型
  266. printf(" %04x\n", ethernet_type);
  267. switch(ethernet_type) {
  268. case 0x0800:
  269. printf("The network layer is IP protocol\n");
  270. break;
  271. case 0x0806:
  272. printf("The network layer is ARP protocol\n");
  273. break;
  274. default:
  275. break;
  276. }
  277. // 获取以太网源地址
  278. // printf("MAC Source Address is : \n");
  279. mac_string = ethernet_protocol->ether_shost;
  280. fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x",
  281. *mac_string,
  282. *(mac_string + 1),
  283. *(mac_string + 2),
  284. *(mac_string + 3),
  285. *(mac_string + 4),
  286. *(mac_string + 5)
  287. );
  288. // 获取以太网目的地址
  289. // printf("MAC Target Address is : \n");
  290. mac_string = ethernet_protocol->ether_dhost;
  291. fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x",
  292. *mac_string,
  293. *(mac_string + 1),
  294. *(mac_string + 2),
  295. *(mac_string + 3),
  296. *(mac_string + 4),
  297. *(mac_string + 5)
  298. );
  299. fprintf(fp, "%d", sizeof(packet_content));
  300. switch(ethernet_type) {
  301. case 0x0800:
  302. ip_protocol_packet_handle(argument, packet_header, packet_content);
  303. break;
  304. default:
  305. break;
  306. }
  307. }
  308. int main() {
  309. pcap_if_t *alldevs;
  310. pcap_if_t *d;
  311. pcap_t *adhandle;
  312. char errbuf[PCAP_ERRBUF_SIZE];
  313. int inum;
  314. int i = 0;
  315. u_int netmask;
  316. char packet_filter[] = "ip and tcp";
  317. struct bpf_program fcode;
  318. int res;
  319. struct pcap_pkthdr *header;
  320. struct tm *ltime;
  321. const u_char *pkt_data;
  322. time_t local_tv_sec;
  323. char timestr[16];
  324. ip_header *ih;
  325. // 获得设备列表 pcap_findalldevs_ex()
  326. if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
  327. fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
  328. exit(1);
  329. }
  330. for(d = alldevs; d; d = d->next) {
  331. printf("%d. %s", ++i, d->name);
  332. if(d->description) {
  333. printf("(%s)\n", d->description);
  334. }
  335. else {
  336. printf("No description available\n");
  337. }
  338. }
  339. if(0 == i) {
  340. printf("\nNo interface found!Make sure WinPcap is installed\n");
  341. return -1;
  342. }
  343. printf("Enter the interface number(1-%d):", i);
  344. scanf_s("%d", &inum);
  345. if(inum < 1 || inum > i) {
  346. printf("\nInterface number out of range.\n");
  347. pcap_freealldevs(alldevs);
  348. return -1;
  349. }
  350. for(d = alldevs, i = 0; i < inum-1; d=d->next, i++);
  351. // 跳转到该设备,打开适配器
  352. // 设备名,要捕捉的数据包的部分(65536保证能捕获到不同数据链路层上的每个数据包的全部内容),混杂模式,读取超时时间,错误缓冲池
  353. if((adhandle = pcap_open_live(d->name, 65536, 1, 1000, errbuf)) == NULL) {
  354. fprintf(stderr, "\nUnable to open the adapter.%s is not supported by WinPcap\n", errbuf);
  355. pcap_freealldevs(alldevs);
  356. return -1;
  357. }
  358. // 检查数据链路层(只考虑了以太网)
  359. if(pcap_datalink(adhandle) != DLT_EN10MB) {
  360. fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
  361. pcap_freealldevs(alldevs);
  362. return -1;
  363. }
  364. if(d->addresses != NULL) {
  365. // 获得接口的第一个地址的掩码
  366. netmask = ((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
  367. }
  368. else {
  369. netmask = 0xffffff;
  370. }
  371. /*
  372. // 编译过滤器
  373. if(pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0) {
  374. fprintf(stderr, "\nUnable to compile the packet filter.Check the syntax\n");
  375. pcap_freealldevs(alldevs);
  376. return -1;
  377. }
  378. // 设置过滤器
  379. if(pcap_setfilter(adhandle, &fcode) < 0) {
  380. fprintf(stderr, "\nError setting the filter.\n");
  381. pcap_freealldevs(alldevs);
  382. return -1;
  383. }
  384. printf("\nlistenting on %s...\n", d->description);
  385. */
  386. fp = freopen("in.txt", "w", stdin);
  387. while((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0) {
  388. // 请求超时
  389. if(0 == res) {
  390. continue;
  391. }
  392. // 分析数据包
  393. ethernet_protocol_packet_handle(NULL, header, pkt_data);
  394. // 将时间戳转换成可识别的格式
  395. local_tv_sec = header->ts.tv_sec;
  396. ltime = localtime(&local_tv_sec);
  397. strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
  398. ih = (ip_header *)(pkt_data + 14); //以太网头部长度
  399. // 输出时间和IP信息
  400. printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len);
  401. printf("%d.%d.%d.%d -> %d.%d.%d.%d\n",
  402. ih->saddr.byte1,
  403. ih->saddr.byte2,
  404. ih->saddr.byte3,
  405. ih->saddr.byte4,
  406. ih->daddr.byte1,
  407. ih->daddr.byte2,
  408. ih->daddr.byte3,
  409. ih->daddr.byte4);
  410. }
  411. if(-1 == res) {
  412. printf("Error reading the packet:%s\n", pcap_geterr(adhandle));
  413. return -1;
  414. }
  415. pcap_freealldevs(alldevs);
  416. fclose(fp);
  417. fclose(stdin);
  418. return 0;
  419. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/162541
推荐阅读
相关标签
  

闽ICP备14008679号