libpcap,有效载荷偏移量为 66,但大小(标头)+ doff = 62



我星期天都在理解使用libpcap嗅探数据包,我已经走了这么远,我可以读取数据包和元数据。当我通过嗅探一些数据包来检查我的代码时,我发现我一定在某处有错误。

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

我现在的问题,我算错data_offset吗?有没有我没有设置的标志?我忘了计算 tcp 选项吗?

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

例如,计算是这样的吗?

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? 

这是代码:

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): %dn", sizeof(struct ip));
  printf("ip_len: %dn", ip_len);
  printf("sizeof(ether_header): %dn", sizeof(struct ether_header));
  printf("sizeof(tcp): %dn", 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 PACKETn");
  printf("tlen: %un", ntohs(ip->ip_len));
  printf("tsrc: %sn", inet_ntoa(ip->ip_src));
  printf("tdst: %sn", inet_ntoa(ip->ip_dst));
  printf("thl: %dn", (ip->ip_hl & 0x0f));
  printf("READ TCPn");
  printf("tsrc port: %un", ntohs(tcp->source));
  printf("tdst port: %un", ntohs(tcp->dest));
  printf("tdata_offset: %dn", data_offset); 
  printf("tdoff: %d-%dn", tcp->doff, ntohs(tcp->doff));
  printf("tpayload len: %dn", payload_len);
  printf("tFLAGSn");
  printf("ttFIN: %in", tcp->fin);
  printf("ttSYN: %in", tcp->syn);
  printf("ttACK: %in", tcp->ack);
  printf("PAYLOAD: n");
  **for (i = 4; i < payload_len; ++i) {**
    printf("%c", payload[i]);
  }
  printf("n");
  printf("n");
  printf("END OF PAYLOADn");
}

输出:

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

似乎不正确,

data_offset = sizeof(struct ether_header) + ip_len + sizeof(struct tcphdr) + tcp->doff

TCP->Doff 已经包含 TCP 标头,并且它是 4 个字节的倍数。所以你想要

 data_offset = sizeof(struct ether_header) + ip_len + tcp->doff * 4;

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

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

  • 假设没有以太网 VLAN
  • 假设 IP 数据包高于以太网(而不是例如 arp 或 stp)
  • 假设 TCP 高于 IP
  • 假设您实际上已捕获所需的所有数据。(即,您应该验证长度不超过标头>cap_len)

最新更新