HTTP标头的起始位置并不总是相同

时间:2016-10-27 18:53:56

标签: c http winpcap

我尝试计算数据包的HTTP标头的开头,例如

GET /test.html HTTP1.1
Host: example.com
...

使用C中的WinPcap尝试

ih = (ip_header *) (pkt_data + 14);
ip_len = (ih->ver_ihl & 0xf) * 4;

th = (tcp_header *) ((u_char*)ih + ip_len);
tcp_len = (((u_char*)ih)[ip_len + 12] >> 4) * 4;

tcp_payload = (u_char*)ih + ip_len + tcp_len;
url = tcp_payload + 4;
end_url = strchr((char*)url, ' ');
url_length = end_url - url;

req_url = (u_char*)malloc(url_length+1);
strncpy((char*)req_url, (char*)url, url_length);
req_url[url_length] = '\0';
printf("%s", req_url); 

输出有时是正确的,但有时会输出cookie的某些部分或cept-Encodin什么是http标题的一部分,但位置错误。我想也许一些tcp有效载荷的长度不同,因为一些额外的字段,但我不知道如何检查?谢谢

#include <stdio.h>
#include <string.h>
#include "pcap.h"

#include <windows.h> 
#include <winsock.h>

/* 4 bytes IP address */
typedef struct ip_address{
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
}ip_address;

/* IPv4 header */
typedef struct ip_header{
    u_char  ver_ihl;        // Version (4 bits) + Internet header length (4 bits)
    u_char  tos;            // Type of service 
    u_short tlen;           // Total length 
    u_short identification; // Identification
    u_short flags_fo;       // Flags (3 bits) + Fragment offset (13 bits)
    u_char  ttl;            // Time to live
    u_char  proto;          // Protocol
    u_short crc;            // Header checksum
    ip_address  saddr;      // Source address
    ip_address  daddr;      // Destination address
    u_int   op_pad;         // Option + Padding
}ip_header;

typedef struct tcp_header // structure TCP Header
{
  //Pour processeur de type little-endian
  unsigned short source;  // port source
  unsigned short dest;    // port de destination
  unsigned int   seq;     // Sequence number
  unsigned int   ack_seq; // acknowledge sequence

  unsigned short res1:4,  // Reserved 1 : 4 bits
                 doff:4,  // Data Offset
                 fin:1,   // Flag FINISH
                 syn:1,   // Flag SYNCHRONIZE
                 rst:1,   // Flag RESET
                 psh:1,   // Flag PUSH
                 ack:1,   // Flag ACKNOLEDGE
                 urg:1,   // Flag URGENT
                 res2:2;  // Reserved 2 : 2 bits (res1 + res2 = 6 bits reserved)

    unsigned short window;
    unsigned short check;   // checksum
    unsigned short urg_ptr; // urgent
}tcp_header;

void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

int main(int argc, char *argv[]) {

pcap_loop(adhandle, 0, packet_handler, NULL);


/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) {

    ip_header *ih;
    tcp_header *th;

    u_int ip_len;   
    int tcp_len, url_length, udp_len;
    u_char *url, *cont, *end_url, *final_url, *tcp_payload;

    /* position of the ip header */
    ih = (ip_header *) (pkt_data + 14); //length of ethernet header
    ip_len = (ih->ver_ihl & 0xf) * 4;
    /* position of the tcp header */
    th = (tcp_header *) ((u_char*)ih + ip_len);
    tcp_len = (((u_char*)ih)[ip_len + 12] >> 4) * 4;

    tcp_payload = (u_char*)ih + ip_len + tcp_len;

    url = tcp_payload + 4; // skip "GET " 
    end_url = strchr((char*)url, ' ');
    url_length = end_url - url;

    if(url_length>0) {
        final_url = (u_char*)malloc(url_length+1);
        strncpy(final_url, url, url_length);
        final_url[url_length] = '\0';
        printf("\n%s\n", final_url); 
    } 

}

}

1 个答案:

答案 0 :(得分:0)

要解析HTTP请求,您需要按行分解请求,每行都要单独解析。第一个是请求本身,然后是标题,最后是数据。

每一行以"\r\n"组合结束,因此您应该搜索该字符,第一行始终是请求行。

例如

char *end_of_line;
end_of_line = strstr(tcp_payload, "\r\n");
if (end_of_line != NULL) {
    // Your request line goes from `tcp_payload' to `end_of_line'.
}

解析HTTP请求远非简单。你应该知道这一点。

由于您的代码有时会正常工作,因此您可能会在代码中的某个地方执行某些未发布的操作。