首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >libpcap,有效负载偏移量66,但sizeof(标头)+ doff = 62

libpcap,有效负载偏移量66,但sizeof(标头)+ doff = 62
EN

Stack Overflow用户
提问于 2012-07-08 21:25:01
回答 1查看 1.8K关注 0票数 0

我把我的周日花在了理解libpcap包嗅探上,我已经能够读懂包和元数据了。当我通过嗅探一些包来检查我的代码时,我发现我一定是在某个地方出错了。

当我嗅探到我父亲http://www.telpho.de的网页时,我得到了整个服务器的响应。从200OK开始直到...但在每个数据包中,开头有4个字节,它们不是ASCII。在下面的代码中,当我将for循环改为(i = 0)时,4个字节也会被打印出来。当我将其保留为(i = 4)时,有效负载将从收到的第一个ASCII字符开始完美地显示出来。

我现在的问题是,我是否计算错了data_offset?有没有我没设置的标志?我是不是忘了把tcp选项计算在内了?

我还认为这可能与填充有关。TCP标准规定TCP报头长度应该是32的倍数。但是32 - 20 = 12.所以这是3个字节的差异。

例如,会不会是这样的计算?

代码语言:javascript
运行
复制
TCP_HDR_SIZE = 32
sizeof(struct tcphdr) = 20
tcp->doff = 8    

sizeof(struct tcphdr) + tcp->doff = 28
TCP_HDR_SIZE - 28 = 4    <--- the 4 bytes i am looking for??? Maybe options? 

代码如下:

代码语言:javascript
运行
复制
void handle_packet_ip(const struct pcap_pkthdr *header, const u_char* data) {
  struct ip *ip;
  struct tcphdr *tcp;
  int ip_len;
  int data_offset;
  int payload_len;
  int i;
  unsigned char* payload;

  ip = (struct ip*)(data + sizeof(struct ether_header));
  ip_len = (ip->ip_hl & 0x0f) * 4;

  tcp = (struct tcphdr*)(data + sizeof(struct ether_header) + ip_len);
  printf("sizeof(ip): %d\n", sizeof(struct ip));
  printf("ip_len: %d\n", ip_len);
  printf("sizeof(ether_header): %d\n", sizeof(struct ether_header));
  printf("sizeof(tcp): %d\n", sizeof(struct tcphdr));

  data_offset = sizeof(struct ether_header) + ip_len + sizeof(struct tcphdr) + tcp->doff;
  payload_len = header->len - data_offset;

  payload = (unsigned char*)(data + data_offset);

  printf("IP PACKET\n");
  printf("\tlen: %u\n", ntohs(ip->ip_len));
  printf("\tsrc: %s\n", inet_ntoa(ip->ip_src));
  printf("\tdst: %s\n", inet_ntoa(ip->ip_dst));
  printf("\thl: %d\n", (ip->ip_hl & 0x0f));

  printf("READ TCP\n");
  printf("\tsrc port: %u\n", ntohs(tcp->source));
  printf("\tdst port: %u\n", ntohs(tcp->dest));
  printf("\tdata_offset: %d\n", data_offset); 
  printf("\tdoff: %d-%d\n", tcp->doff, ntohs(tcp->doff));
  printf("\tpayload len: %d\n", payload_len);
  printf("\tFLAGS\n");
  printf("\t\tFIN: %i\n", tcp->fin);
  printf("\t\tSYN: %i\n", tcp->syn);
  printf("\t\tACK: %i\n", tcp->ack);
  printf("PAYLOAD: \n");
  **for (i = 4; i < payload_len; ++i) {**
    printf("%c", payload[i]);
  }
  printf("\n");

  printf("\n");
  printf("END OF PAYLOAD\n");
}

输出:

代码语言:javascript
运行
复制
Grabbed Packet:
Length: 74
    Capture Length: 74
sizeof(ip): 20
ip_len: 20
sizeof(ether_header): 14
sizeof(tcp): 20
IP PACKET
len: 60
src: 80.237.132.106
dst: 192.168.0.17
hl: 5
READ TCP
src port: 80
dst port: 57662
data_offset: 62     **this should be 64 ??**
doff: 8
payload len: 10
FLAGS
    FIN: 0
    SYN: 1
    ACK: 1
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-07-08 21:39:29

这看起来不太对,

代码语言:javascript
运行
复制
data_offset = sizeof(struct ether_header) + ip_len + sizeof(struct tcphdr) + tcp->doff

tcp->doff已经包含了tcp报头,并且它是4字节的倍数。所以你会想要

代码语言:javascript
运行
复制
 data_offset = sizeof(struct ether_header) + ip_len + tcp->doff * 4;

仅使用sizeof(struct tcphdr)不会考虑可能出现的任何TCP选项。

请注意,您的代码假设了很多内容:

  • 假设没有以太网vlan
  • 假设IP数据包在以太网之上(而不是arp或stp)
  • 假设IP之上的TCP
  • 假设您已经实际捕获了所有需要的数据。(即,您应验证长度不超过header->cap_len)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11383497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档