从http响应中提取http正文

时间:2014-09-11 13:53:59

标签: c httpresponse pcap extraction tcp-ip

我编写了一个程序,它接受一个.pcap文件,该文件是wireshark捕获的输出,包含图像请求的响应。我的程序必须从数据包中收集http正文数据并将它们全部附加到文件中。但是这里发生了错误: 写入文件的每个数据包的正文数据大小小于其实际数据大小。 我可以看到header.caplen和header.len是一样的。 在我的代码中,每个数据包的标题部分总共有54个字节(14个以太网+ 20个tcp + 20个ip),但是strlen(payload)小于(header.len - 54)

这是我的结构:

/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN  6

    struct sniff_ethernet {
        u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
        u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
        u_short ether_type; /* IP? ARP? RARP? etc */
    };

    /* IP header */
    struct sniff_ip {
        u_char ip_vhl;      /* version << 4 | header length >> 2 */
        u_char ip_tos;      /* type of service */
        u_short ip_len;     /* total length */
        u_short ip_id;      /* identification */
        u_short ip_off;     /* fragment offset field */
    #define IP_RF 0x8000        /* reserved fragment flag */
    #define IP_DF 0x4000        /* dont fragment flag */
    #define IP_MF 0x2000        /* more fragments flag */
    #define IP_OFFMASK 0x1fff   /* mask for fragmenting bits */
        u_char ip_ttl;      /* time to live */
        u_char ip_p;        /* protocol */
        u_short ip_sum;     /* checksum */
        struct in_addr ip_src,ip_dst; /* source and dest address */
    };
    #define IP_HL(ip)       (((ip)->ip_vhl) & 0x0f)
    #define IP_V(ip)        (((ip)->ip_vhl) >> 4)

    /* TCP header */
    typedef u_int tcp_seq;

    struct sniff_tcp {
        u_short th_sport;   /* source port */
        u_short th_dport;   /* destination port */
        tcp_seq th_seq;     /* sequence number */
        tcp_seq th_ack;     /* acknowledgement number */
        u_char th_offx2;    /* data offset, rsvd */
    #define TH_OFF(th)  (((th)->th_offx2 & 0xf0) >> 4)
        u_char th_flags;
    #define TH_FIN 0x01
    #define TH_SYN 0x02
    #define TH_RST 0x04
    #define TH_PUSH 0x08
    #define TH_ACK 0x10
    #define TH_URG 0x20
    #define TH_ECE 0x40
    #define TH_CWR 0x80
    #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
        u_short th_win;     /* window */
        u_short th_sum;     /* checksum */
        u_short th_urp;     /* urgent pointer */
};

这是我的主要功能:

/* ethernet headers are always exactly 14 bytes */
#define SIZE_ETHERNET 14

    const struct sniff_ethernet *ethernet; /* The ethernet header */
    const struct sniff_ip *ip; /* The IP header */
    const struct sniff_tcp *tcp; /* The TCP header */
//  const char *payload; /* Packet payload */

    u_int size_ip;
    u_int size_tcp;

    char *img_body;
    FILE *img;

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

    char *file = "/home/test1/app-engine1/right/r_response.pcap";
    pcap_t *pcap;
    const unsigned char *packet;
    char errbuf[PCAP_ERRBUF_SIZE];
    struct pcap_pkthdr header;
    u_char *payload = (u_char*) malloc(sizeof(u_char) * 3000);
    int counter = 0;
    int real_len = 0;
    img = fopen("/home/test1/app-engine1/img", "wa");


    pcap = pcap_open_offline(file, errbuf);
    if (pcap == NULL)
    {
            fprintf(stderr, "error reading pcap file: %s\n", errbuf);
            return 1;
    }    


    while((packet = pcap_next(pcap, &header)) != NULL){
        counter++;
        ethernet = (struct sniff_ethernet*)(packet);

        ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);

        printf("len=%d, eth_type=%d, protocol=%d\n", header.caplen, ethernet->ether_type, ip->ip_p);

        size_ip = IP_HL(ip)*4;

        usleep(1e5);

        if (size_ip < 20) 
        {
                printf("   * Invalid IP header length: %u bytes\n", size_ip);
                continue;
            }

        tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);

        size_tcp = TH_OFF(tcp)*4;

        if (size_tcp < 20) 
        {
                printf("   * Invalid TCP header length: %u bytes\n", size_tcp);
                continue;
            }
        strcpy(payload, (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp));
            if(strlen(payload) <= 0)
                continue;
        real_len += strlen(payload);
        printf("caplen:%d       len:%d     strlen(payload):%u\n", header.caplen, header.len, strlen(payload));
        fwrite(payload, strlen(payload), 1, img);

    }
    fclose(img);
    printf("counter:%d  real_len:%d\n", counter, real_len);
}

0 个答案:

没有答案