在前面的一篇文章中,简单了介绍了HTTP报文格式,详情参考http://www.firefoxbug.net/?cat=47

这里大概介绍下基本的,常见的HTTP包头格式。

POST /report/getComment.jsp HTTP/1.1
Host: yeeg.com
Connection: keep-alive
Content-Length: 161
Origin: http://www.1g1g.com
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7
content-type: application/x-www-form-urlencoded
Accept: */*
Referer: http://www.1g1g.com/player/loader.swf?uid=0.8106261373031884
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=C3F105F72E3602D6292D3E4561E8E400

上面是一个POST包的包头,其中Content-Length字段里面的值就是POST包数据段的长度。可以用

wireshark抓取POST包,会发现,post包是把报文头和数据内容分开来发的,会被TCP分片,然后重组。

具体这里不详细讨论。

GET /enclosure/2010-09-10T02_51_05-07_00.mp3 HTTP/1.1
Host: 805665086.podomatic.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7
Accept: */*
Referer: http://www.1g1g.com/player/loader.swf?uid=0.8106261373031884
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

上面是一个GET包,GET包请求的资源都是在URL里面的,所以数据段也就没有了,可以通过抓包分析。

HTTP/1.1 200 OK
Date: Tue, 10 Jul 2012 09:12:52 GMT
Server: Apache/2.2.14 (Ubuntu)
Last-Modified: Thu, 23 Dec 2010 19:29:26 GMT
ETag: "960fcf-4a6459-49818e3486374"
Accept-Ranges: bytes
Content-Length: 487
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: audio/mpeg

上面是一个http响应包,Content-Length指明了数据段的大小。

下面是我今天用C写了解析HTTP报文头的程序。注意:下面代码只主要用libcap实现实现了部分功能,具体

是解析GET包头,POST包头,还有HTTP相应包头,可能存在一些不足,希望大家多多交流。

  1. /*
  2. capture http packet by firefoxbug
  3. */
  4. #include <pcap.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/socket.h>
  9. #include <arpa/inet.h>
  10. #include <net/ethernet.h>
  11. #include <netinet/ip_icmp.h>  //Provides declarations for icmp header
  12. #include <netinet/udp.h>      //Provides declarations for udp header
  13. #include <netinet/tcp.h>      //Provides declarations for tcp header
  14. #include <netinet/ip.h>       //Provides declarations for ip header
  15. #define BUFFSIZE 1500
  16. typedef struct port{
  17. unsigned int src_port;
  18. unsigned int des_port;
  19. }Port;
  20. Port port;
  21. int tcp=0;
  22. FILE *logfile;
  23. int size;
  24. void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *buffer);
  25. char *print_tcp_packet(const char *Buffer);
  26. void get_line(char *data,char *buff,int length);
  27. void print_http_req_packet(char *data);
  28. void print_http_ans_packet(char *data);
  29. int main(int argc,char *argv[])
  30. {
  31. pcap_if_t *alldevsp , *device;
  32. pcap_t *handle; //Handle of the device that shall be sniffed
  33. char errbuf[100] , *devname , devs[100][100];
  34. int count = 1 , n;
  35. //First get the list of available devices
  36. printf("Finding available devices ... ");
  37. if( pcap_findalldevs( &alldevsp , errbuf) )
  38. {
  39. printf("Error finding devices : %s" , errbuf);
  40. exit(1);
  41. }
  42. printf("Done");
  43. //Print the available devices
  44. printf("\nAvailable Devices are :\n");
  45. for(device = alldevsp ; device != NULL ; device = device->next)
  46. {
  47. printf("%d. %s - %s\n" , count , device->name , device->description);
  48. if(device->name != NULL)
  49. {
  50. strcpy(devs[count] , device->name);
  51. }
  52. count++;
  53. }
  54. //Ask user which device to sniff
  55. printf("Enter the number of the device you want to sniff : ");
  56. scanf("%d" , &n);
  57. devname = devs[n];
  58. //Open the device for sniffing
  59. printf("Opening device %s for sniffing ... " , devname);
  60. handle = pcap_open_live(devname , 65536 , 1 , 0 , errbuf);
  61. if (handle == NULL)
  62. {
  63. fprintf(stderr, "Couldn't open device %s : %s\n" , devname , errbuf);
  64. exit(1);
  65. }
  66. printf("Done\n");
  67. logfile=fopen("log.txt","w");
  68. if(logfile==NULL)
  69. {
  70. printf("Unable to create file.");
  71. }
  72. //Put the device in sniff loop
  73. pcap_loop(handle , -1 , process_packet , NULL);
  74. return 0;
  75. }
  76. void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *buffer)
  77. {
  78. size = header->len;
  79. //  fprintf(logfile,"length of packet : %d \n",size);
  80. //Get the IP Header part of this packet , excluding the ethernet header
  81. struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
  82. switch (iph->protocol) //Check the Protocol and do accordingly...
  83. {
  84. case 6:  //TCP Protocol
  85. ++tcp;
  86. //  printf("TCP : %d \n", tcp);
  87. unsigned char *data = print_tcp_packet(buffer);
  88. if (size <= 0)
  89. break;
  90. if (port.des_port == 80)
  91. {
  92. print_http_req_packet(data);
  93. }
  94. else if ( port.src_port == 80 )
  95. {
  96. print_http_ans_packet(data);
  97. }
  98. break;
  99. }
  100. }
  101. char *print_tcp_packet(const char *Buffer)
  102. {
  103. //IP header
  104. struct iphdr *iph = (struct iphdr *)( Buffer  + sizeof(struct ethhdr) );
  105. unsigned int iphdrlen = iph->ihl*4;
  106. //TCP header
  107. struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr));
  108. port.src_port = ntohs(tcph->source);
  109. port.des_port = ntohs(tcph->dest);
  110. // mac_header + ip_header + tcp_header
  111. int header_size =  sizeof(struct ethhdr) + iphdrlen + tcph->doff*4;
  112. size = size - header_size;
  113. //  fprintf(logfile,"length of header : %d \n",header_size );
  114. return (char *)(Buffer + header_size);
  115. }
  116. void print_http_req_packet(char *data)
  117. {
  118. if( strncmp(data,"GET",3) == 0 || strncmp(data,"POST",4) == 0 )
  119. {
  120. fprintf(logfile,"\n/***********************length of data : %d**********************/ \n",size);
  121. fprintf(logfile,"From %d To %d \n",port.src_port,port.des_port);
  122. int i = 0;
  123. for( ; i < size ; ++i)
  124. {
  125. fprintf(logfile,"%c",*(data + i));
  126. }
  127. fprintf(logfile,"/***************************** end *******************************/ \n\n");
  128. }
  129. return ;
  130. }
  131. void print_http_ans_packet(char *data)
  132. {
  133. if( strncmp(data,"HTTP",4) == 0 )
  134. {
  135. fprintf(logfile,"\n/***********************length of data : %d**********************/ \n",size);
  136. fprintf(logfile,"From %d To %d \n",port.src_port,port.des_port);
  137. char buff[BUFFSIZE] = {'\0'};
  138. get_line(data,buff,size);
  139. fprintf(logfile,"%s",buff);
  140. unsigned int off = strlen(buff);
  141. size = size - off;
  142. while(strcmp(buff,"\r\n") != 0)
  143. {
  144. memset(buff,'\0',sizeof(buff));
  145. get_line(data + off,buff,size);
  146. fprintf(logfile,"%s",buff);
  147. off = off + strlen(buff);
  148. size = size - off;
  149. }
  150. fprintf(logfile,"/***************************** end *******************************/ \n\n");
  151. }
  152. }
  153. void get_line(char *data,char *buff,int length)
  154. {
  155. int i = 0;
  156. char ch;
  157. for ( ; i < length;++i)
  158. {
  159. ch = *(data + i);
  160. *(buff + i) = ch;
  161. if(ch == '\n')
  162. break;
  163. }
  164. }

最新文章

  1. SQL 事务
  2. asp.net中如何防止用户重复点击提交按钮
  3. Android技能树
  4. thinkphp 3+ 观后详解 (2)
  5. 存储过程/游标/mysql 函数
  6. 转:45 Useful JavaScript Tips, Tricks and Best Practices
  7. QP在STM32F10X上第一个应用
  8. Java获取随机数的几种方法
  9. 开源一个适用iOS的数据库表结构更新机制的代码
  10. hbase 第一篇
  11. 解决mac 中的myeclipse控制台中文乱码问题
  12. keras初涉笔记【一】
  13. Xamarin Forms error MSB6006: “java.exe”已退出,代码为 2 解决办法
  14. XHR简介
  15. Iowait的成因、对系统影响及对策--systemtap
  16. [Oracle]坏块处理:确认坏块的对象
  17. .net framework多个版本在IIS服务器上时应注意-重新注册IIS-错误Server Application Unavailable
  18. 八月(The Summer is Gone)观后感
  19. (转)Python——functools
  20. 11th 单元测试工具JUnit的学习

热门文章

  1. Qt国际化详细介绍,中文乱码以及解决方案
  2. QT 内存泄露 检测
  3. ActiveNotifications
  4. Gradle学习目录总结
  5. LNMP wget 记录
  6. js的异步的问题的再次理解
  7. jsp页面可以巧用模态框
  8. Python 函数的使用 外加引入文件
  9. C# 自定义线程修改UI(一)
  10. Android打开系统的Document文档图片选择