1

情况如下:在我的场景中,我有 3 台计算机,A、B 和 C。

计算机 A 向计算机 B 发送数据。计算机 B 使用 pcap 捕获这些数据包,附加标头,重做校验和,并将其从另一个以太网接口注入计算机 C。所以基本上 A 向 C 发送数据,尽管从 C 的角度来看,数据来自计算机 B。

我的问题是这样的:按照 TCPDUMP 的关于剖析捕获的数据包的教程,我学会了计算偏移量并使用类型转换来获取以太网、ip 和 tcp 标头结构。这样做的方法如下所示:

ethernet = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
    printf("   * Invalid IP header length: %u bytes\n", size_ip);
    return;
}
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
size_tcp = TH_OFF(tcp)*4;
if (size_tcp < 20) {
    printf("   * Invalid TCP header length: %u bytes\n", size_tcp);
    return;
}
payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);

因为我想注入捕获的数据包以将其从计算机 B 发送到计算机 C,所以我必须修改一些源/目标信息并在完成后重新计算校验和。但是,我的问题是,由于这些数据现在被分成以太网头、IP 头和 TCP 头的结构,我如何将它们重新组合成一个u_char可以pcap_inject使用的结构?

是否可以在这里进行某种连接?

4

1 回答 1

1

从我在这里看到的代码中,您实际上并没有剖析libpcap为您捕获的内存。每个转换操作都只是告诉编译器您打算如何处理从指针开始的字节——这些对象的大小、查找哪些数据的偏移量以及它们的长度。

如果您通过这些指针修改此内存,则您已经修改了进程内存中它的唯一副本——并且可以使用一些“更基本”的指针将整个内存块交给sendmsg(2)或其他任何东西,而无需重新组装数据——你从来没有把它拆开。

更新

要将数据包注入网络,您需要使用raw(7)套接字类型;套接字选项是通过套接字IPPROTO_RAW发送 TCP 数据包所必需的raw(7)——否则,所有TCP 数据包都将被定向到raw(7)您打开的套接字,从而使机器上的网络难以使用。

raw(7)套接字将为您执行一些重新计算任务:

   A protocol of IPPROTO_RAW implies enabled IP_HDRINCL and is
   able to send any IP protocol that is specified in the passed
   header.  Receiving of all IP protocols via IPPROTO_RAW is not
   possible using raw sockets.

          ┌───────────────────────────────────────────────────┐
          │IP Header fields modified on sending by IP_HDRINCL │
          ├──────────────────────┬────────────────────────────┤
          │IP Checksum           │Always filled in.           │
          ├──────────────────────┼────────────────────────────┤
          │Source Address        │Filled in when zero.        │
          ├──────────────────────┼────────────────────────────┤
          │Packet Id             │Filled in when zero.        │
          ├──────────────────────┼────────────────────────────┤
          │Total Length          │Always filled in.           │
          └──────────────────────+────────────────────────────┘

   If IP_HDRINCL is specified and the IP header has a nonzero
   destination address then the destination address of the
   socket is used to route the packet.  When MSG_DONTROUTE is
   specified, the destination address should refer to a local
   interface, otherwise a routing table lookup is done anyway
   but gatewayed routes are ignored.

   If IP_HDRINCL isn't set, then IP header options can be set on
   raw sockets with setsockopt(2); see ip(7) for more
   information.

让内核重新计算它愿意为您做的任何事情。

于 2011-11-19T10:10:26.600 回答