2012-01-12 347 views
0

我试图从包中提取TCP有效载荷,而这里的捕捉回调的最低限度的情况下:TCP有效载荷提取和正确的IP地址

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地址是一样的。

  2. 此外,我怎样才能打印出有效载荷?由于我不能将一个无符号的char数组明确地转换为一个char数组,该数组以“\ 0”结尾,可能会出错。

    192.168.56.1:48065 - > 192.168.56.1:80

    192.168.56.80:80 - > 192.168.56.80:48065

EDIT

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

THanks to Celeda,我解决了ip地址问题,通过分离ine的调用t_ntoa:

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; 

    } 
+0

对于第二部分,我不确定,也许'buff'不是指向正确的位置。我看你做了'buff + = sizeof(tcphdr)',但也许有TCP选项需要跳过。我也不知道C++,所以我不确定'hex << buff'实际上做了什么。但我怀疑它期望一个NUL终止的字符串;我认为你需要使用一些将长度作为输入的函数,因此它不会超出数据包的末尾。 – Celada 2012-01-12 15:50:20

+0

@Celada请参阅“编辑2” – daisy 2012-01-12 16:07:04

回答

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

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

编辑附加信息的问题

“额外的字符”你喜欢你试图解释为有效载荷数据TCP选项的HTTP数据的声音之前看到的。当您将指针跳过buff时,请务必正确计算TCP标头的大小。它是4个字节* th_off。在使用ip_hl时,您应该对IP标头执行相同的操作,因为IP标头并不总是20个字节。

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

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

+0

请参阅我的更新,谢谢! – daisy 2012-01-12 15:33:39