我正在尝试从数据包中提取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;
}
}
}
但是这里出了点问题,源IP地址和目标IP地址是一样的。
此外,我如何打印有效载荷?因为我不能只显式地将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
修改
---------------------
感谢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;
}
答案 0 :(得分:1)
inet_ntoa()
使用静态缓冲区。您通过调用它两次覆盖缓冲区。请改用inet_ntop()
。
有效负载可能是二进制数据。你想怎么打印出来?作为十六进制转储或类似的东西?只需查看有效负载并一次打印十六进制字节,即可实现简单的十六进制转储。或者,如果您确定它是可打印数据,您可以使用fwrite()
之类的任何函数将其直接转储到输出,该函数允许您指定要写入的字符串的长度。
编辑问题中的其他信息
您在HTTP数据发出之前看到的“额外字符”就像您尝试将其解释为有效负载数据的TCP选项一样。当您将buff
指针跳过它时,请务必正确计算TCP标头的大小。这是4个字节* th_off
。当你使用ip_hl
时,你应该对IP头做同样的事情,因为IP头也不总是20个字节。
之后,for
循环中的结束条件错误。首先,ip_off
(片段偏移量)不会进入它,其次,ip_hl
和tcp_off
都以4个字节为单位进行测量,而不是以字节为单位。
将您获得的代码与Wireshark解码相同数据包的方式进行比较,您将能够轻松诊断出任何进一步的差异。