重建数据包以通过 pcap 注入

发布于 2024-12-17 03:03:49 字数 953 浏览 3 评论 0原文

情况是这样的:在我的场景中,我有 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 可以用吗?

是否可以在这里进行某种串联?

Here is the situation: in my scenario I have, 3 computers, A, B and C.

Computer A sends data to computer B. Computer B captures these packets with pcap, appends the headers, redoes the checksums, and injects it out another ethernet interface to computer C. So basically A sends to C, though through C's point of view, the data is coming from computer B.

My problem is this: following TCPDUMP's tutorial on dissecting a captured packet, I've learned to calculate offsets and using typecasting to obtain ethernet, ip, and tcp header structures. The method of doing so is shown below:

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);

Because I want to inject the captured packet to send it from computer B to computer C, I must modify some of the source/destination information and recalculate the checksum when I'm done. However, my issue is, since this data is now separated into structures of ethernet header, IP header, and TCP headers, how do I put it back together into a u_char that pcap_inject can use?

Is it possible to do some sort of concatenation here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦里寻她 2024-12-24 03:03:49

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

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

更新

要将数据包注入回网络,您需要使用raw(7)套接字类型;通过 raw(7) 套接字发送 TCP 数据包需要 IPPROTO_RAW 套接字选项 - 否则,所有 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.

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

From the code I see here, you're not actually dissecting the memory that libpcap captured for you. Each of the casting operations simply tells the compiler how you intend to treat the bytes starting from a pointer -- what size those objects are, what offsets to find which pieces of data and how long they are.

If you modify this memory through those pointers, you've modified the one and only copy of it in the process memory -- and can use some of the "more basic" pointers to hand the entire block of memory to sendmsg(2) or whatever without needing to reassemble the data -- you never took it apart.

Update

To inject the packets back on the network you need to use the raw(7) socket type; the IPPROTO_RAW socket option is required to send TCP packets through a raw(7) socket -- otherwise, all TCP packets would be directed to the raw(7) socket you open, making networking on the machine difficult to use.

The raw(7) sockets will perform some re-calculation tasks for you:

   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.

Let the kernel re-calculate whatever it is willing to do for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文