Tcp有效负载提取和正确的IP地址

时间:2012-01-12 14:06:27

标签: tcp pcap

我正在尝试从数据包中提取tcp有效负载,这是捕获回调的最小情况:

void capture_callback (u_char *hdr , const struct pcap_pkthdr* pkthdr , const u_char* buff)
{
    struct ether_header *eptr = (struct ether_header *) buff;
    buff += sizeof (ether_header); /* jump over ethernet header: 14 bytes */

    if ( ntohs (eptr->ether_type) == ETHERTYPE_IP )
    {
        struct ip *iph;
        struct tcphdr *tcp_header;

        iph = (struct ip *) buff;
        buff += sizeof (ip); /* jump over ip header */

        if ( iph->ip_p == IPPROTO_TCP )
        {
            tcp_header = (struct tcphdr *) buff;
            buff += sizeof (tcphdr); /* jump over tcp header */

            cout << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
                        " --> " << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;

        }

    }
}
  1. 但是这里出了点问题,源IP地址和目标IP地址是一样的。

  2. 此外,我如何打印有效载荷?因为我不能只显式地将unsigned char数组转换为char数组,它以“\ 0”结尾,所以它可能会出错。

    192.168.56.1:48065 - &gt; 192.168.56.1:80

    192.168.56.80:80 - &gt; 192.168.56.80:48065

  3. 修改

    ---------------------

    感谢Celeda,我通过分离inet_ntoa的调用解决了ip地址问题:

        cout << "IP: " << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
                    " --> ";
        cout << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;
    

    现在是第二部分,我正在使用:

    cout << hex << buff << endl;

    对于HTTP协议,我没有看到类似“GET /”的内容,但有多个空行

    编辑2

    --------------------------

    我现在不太关心TCP选项,我会检查更多关于细节的文档, 但是现在这个功能很好。

        if ( iph->ip_p == IPPROTO_TCP )
        {
            tcp_header = (struct tcphdr *) buff;
            buff += tcp_header->th_off * 4;
    
            cout << "IP: " << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
                        " --> ";
            cout << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;
    
            for ( int i = 0 ; i < iph->ip_len - iph->ip_off * 4; i ++ )
            {
                if ( isascii (buff[i]) )
                {
                    cout << buff[i];
                }
            }
            cout << endl << "-----------" << endl;
    
        }
    

1 个答案:

答案 0 :(得分:1)

  1. inet_ntoa()使用静态缓冲区。您通过调用它两次覆盖缓冲区。请改用inet_ntop()

  2. 有效负载可能是二进制数据。你想怎么打印出来?作为十六进制转储或类似的东西?只需查看有效负载并一次打印十六进制字节,即可实现简单的十六进制转储。或者,如果您确定它是可打印数据,您可以使用fwrite()之类的任何函数将其直接转储到输出,该函数允许您指定要写入的字符串的长度。

  3. 编辑问题中的其他信息

    您在HTTP数据发出之前看到的“额外字符”就像您尝试将其解释为有效负载数据的TCP选项一样。当您将buff指针跳过它时,请务必正确计算TCP标头的大小。这是4个字节* th_off。当你使用ip_hl时,你应该对IP头做同样的事情,因为IP头也不总是20个字节。

    之后,for循环中的结束条件错误。首先,ip_off(片段偏移量)不会进入它,其次,ip_hltcp_off都以4个字节为单位进行测量,而不是以字节为单位。

    将您获得的代码与Wireshark解码相同数据包的方式进行比较,您将能够轻松诊断出任何进一步的差异。