【问题标题】:Rebuilding a packet to inject via pcap重建数据包以通过 pcap 注入
【发布时间】:2011-11-19 18:57:38
【问题描述】:

情况如下:在我的场景中,我有 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 头的结构,我如何将它们重新组合成 pcap_inject 可以使用的 u_char

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

【问题讨论】:

    标签: c code-injection pcap tcpdump


    【解决方案1】:

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

    如果您通过这些指针修改此内存,您已经修改了进程内存中它的唯一副本——并且可以使用一些“更基本”的指针将整个内存块交给@987654324 @ 或其他不需要重新组装数据的东西——你永远不会把它拆开。

    更新

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

    让内核重新计算它愿意为你做什么。

    【讨论】:

    • 我只复制了一个sn-p的教程。教程在这里:tcpdump.org/pcap.html,代码在这里:tcpdump.org/sniffex.c 无论如何,他们似乎正在做的是通过进行类型转换来填写每种类型的标题的结构。所以我想知道是否有某种简单的反向过程我可以做来重建一个数据包并将其提供给注入器功能。抱歉,如果我的要求似乎是一种误导。我正在为 EE 的一个高级设计项目做这个。 CS 和代码相关的东西真的是我正在学习的东西。
    • 啊。我没有看到任何修改,但我也没有看到任何看起来像实际上复制数据的代码。
    • 我按回车不小心过早发布了。我正在编辑评论以便为更多内容腾出空间。
    • 您肯定已经找到了一些难以实施的方法,那里做得很好。 :) 你真正想做什么?我开始认为可能会有更好的工具。
    • 嗯,我的项目的目标是能够让客户端计算机进入睡眠状态,同时给人一种它仍然存在于网络上的错觉。因此,我正在编写的代码将在位于网络和客户端之间的低功耗设备上运行。当客户端打开时,它需要做的就是捕获、修复标头、注入到客户端(转发)。如果客户端睡着了,我缓存需要转发的数据,通过魔术包唤醒客户端,然后发送缓存的数据。我知道我可以让设备成为 NAT,但我希望其他机器能够像没有中间设备一样交谈。
    猜你喜欢
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 2014-03-13
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多