【问题标题】:Manual packet generation using <pcap.h>使用 <pcap.h> 手动生成数据包
【发布时间】:2014-03-31 21:56:51
【问题描述】:

假设我们有一个包含数据包信息的 XML 文件

<packet> 
    <frame_type>Ethernet</frame_type> 
    <local_mac_address>00-21-85-11-29-1b</local_mac_address> 
    <remote_mac_address>ff-ff-ff-ff-ff</remote_mac_address> 
    <protocol>IP</protocol> 
    <version>4</version> 
    <local_address>147.175.106.141</local_address> 
    <remote_address>255.255.255.255</remote_address> 
    <protocol_type>UDP</protocol_type> 
    <protocol>UDP</protocol> 
    <local_port>17500</local_port> 
    <remote_port>17500</remote_port> 
    <service_name></service_name> 
    <packets>8</packets> 
</packet>

我可以使用 pugiXML 或其他一些 XML 解析器轻松解析。

使用纯 C++ 生成此类数据包的方法是什么(以正确的顺序获取数据包信息)并使用 pcap.h 中声明的函数将其保存到wireshark 可读的文件中?

pcap_dump(dumpfile, header, pkt_data);

u_char *dumpfile, const struct pcap_pkthdr *header, const u_char *pkt_data;

我应该如何使用纯 C++ 填充 pkt_dataheader

struct pcap_pkthdr {
    struct timeval ts;  /* time stamp */
    bpf_u_int32 caplen; /* length of portion present */
    bpf_u_int32 len;    /* length this packet (off wire) */
};

是否有我应该设置到tscaplenlen 的数据示例?


编辑

所以经过一段时间的谷歌搜索后,我在 SO 上发现了这个 thread

所以我使用这些结构来填充我的以太网 -> IP -> TCP 数据包,如下所示

我不熟悉 uint16_t、uint8_t 等类型。

pcap_hdr_t pcaphdr;

pcaphdr.magic_number = 0xd4c3b2a1; //0xa1b2c3d4 || 0xd4c3b2a1 <- i am on winwows (Little endian)
pcaphdr.sigfigs = 0;
pcaphdr.version_major = 2;
pcaphdr.version_minor = 4;
pcaphdr.snaplen = 65536;
pcaphdr.thiszone = 0;
pcaphdr.network = DLT_EN10MB;

ethernet_hdr_t ethernethdr;

ethernethdr.dst = ??; // I have no clue how to fill this either ...dst[0] = 0xFF? type is uint8_t.
ethernethdr.src = ??;//same as above
ethernethdr.type = 2048; //? //(I want to use IP = 0x800), it is uint16_t

//and for IP

ip_hdr_t ipp;

ipp.ip_dst = parseIPV4string(ipAddressString); //this function converts string into uint32_t 
ipp.ip_src = parseIPV4string(ipAddressString);
ipp.ip_v = 4; //version
ipp.ip_hl = 20; //header length
ipp.ip_id = 12758; //id whatever id
ipp.ip_ttl = 125; //time to live
ipp.ip_p = 6; //protocol 6 = TCP 
ipp.ip_off = 0; 
ipp.ip_tos = 0;

//and save all this by 

FILE *ptr_myfile;
ptr_myfile=fopen("test.pcap", "wb");
if (!ptr_myfile)
{
    printf("Unable to open file!");
    return 1;
}

fwrite(&pcaphdr, 1, sizeof(pcap_hdr_t), ptr_myfile);
fwrite(&ethernethdr, 1, sizeof(ethernet_hdr_t), ptr_myfile);
fwrite(&ipp, 1, sizeof(ip_hdr_t), ptr_myfile);
fclose(ptr_myfile);

我不希望创建带有有效负载(数据)的数据包,我正在尝试处理没有数据的纯数据包 + 在 Wireshark 中检查此数据包。

【问题讨论】:

  • 您想将 XML 数据包转换为 pcap 数据包吗?除非您的示例中未显示整个二进制数据/十六进制转储,否则确实没有足够的信息来执行此操作。您可以使用您获得的信息为以太网/IP/UDP 创建合成标头,但是没有数据可以放入 UDP 部分,所以它有点毫无意义。
  • 我知道没有数据,我试图了解如何将数据包数据放入 u_char 变量(更多 C 的东西),但总的来说我试图理解 pcap_pkthdr 结构的概念(我知道有一个手动文件,但不清楚)winpcap.org/docs/docs_41b5/html/structpcap__pkthdr.html
  • "Ethernet2" 如果每个数据包都有不同的帧类型,则不能使用 pcap,而必须使用 pcap-ng。
  • 可以是以太网也可以是802.3

标签: c++ pcap


【解决方案1】:

你真的不需要 pcap_dump,你可以自己打开文件并写入它。

示例 pcap 文件头,每个文件在文件开头一次 struct pcap_file_header fh; fh.magic = TCPDUMP_MAGIC; fh.sigfigs = 0; fh.version_major = 2; fh.version_minor = 4; fh.snaplen = USHRT_MAX; fh.thiszone = 0; fh.linktype = LINKTYPE_ETHERNET; fwrite(&fh, sizeof(fh), 1, file);

示例 pcap 数据包头,每个数据包一次 struct pcap_pkthdr pkhdr; pkhdr.len = pkhdr.caplen = your_content_length; pkhdr.ts.tv_sec = 1396306094; // Some unix timestamp fwrite(&pkhdr, sizeof(pkhdr), 1, file); fwrite(your_binary_packet, your_content_length, 1, file) 对您要写入的每个数据包重复此操作

如果你想使用 pcap_dump,第一个参数是 pcap_dump_open 返回的值,header 与上面的 pkhdr 相同,pkt_data 是你的二进制数据,该数据的长度应该与你指定的 pkhdr.len 匹配。要让 pkt_data 指向有意义的东西,请将您拥有的任何数据转换为二进制。

编辑: 您似乎没有在示例中的任何位置写入 pcap 文件头。此外,您需要阅读更多关于您正在使用的协议的信息。我假设您有理由使用 DLT_EN10MB 而不是 LINKTYPE_ETHERNET。我对前者不熟悉。

对于ethernet dst/src,只需填写0进行测试。我假设您稍后想要转换 XML 中的内容。

ip_hl 是 32 位字的数量,而不是字节数,所以 20=5。您也没有指定 ip_len ,它是 IP 标头 + 数据的总字节数。如果您想从仅具有以太网+IP 标头并且没有用于测试目的的其他数据开始,您可以将其保留为 20。使用 htons() 函数。为了正确起见,您最终还需要计算 IP 校验和。

对于 x86,想想 uint16_t=unsigned short, uint8_t=unsigned char

【讨论】:

  • 这就是我一直在寻找的,(现在我放弃了使用pcap_dump() 的想法)。您能否提供“your_binary_packet”示例?
  • 假设我将文件保存到 test.bin(使用fwrite(&amp;pkhdr...)),我无法通过wireshark打开文件(所以我可以调试)。有什么提示吗?
  • your_binary_packet 的创建完全取决于您如何获得可用的二进制数据,并且由于您没有显示示例,因此我真的无法显示转换它。你失败的文件,你是不是也写了pcap文件头?您是如何提供数据的?
  • 查看编辑。做起来并不难,只是要求你在做的事情上要精确。
  • 我不确定从哪里开始,fh.magic 需要为 0xa1b2c3d4,否则所有其他成员也必须交换。不管你是否在 Windows 上,wireshark 都支持,它只需要保持一致。文件头出现,否则没问题。文件中似乎没有有效的数据包头,或者如果你写了一个,你没有设置 caplen=len,但是即使读取 caplen 字节也不起作用,所以它可能丢失了,因为只剩下 12 个字节阅读标题后在文件中。 LINKTYPE_ETHERNET 定义为 1 btw。
猜你喜欢
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 2012-10-02
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多