使用<pcap.h> </pcap.h>生成手动数据包

时间:2014-03-31 21:56:52

标签: c++ pcap

假设我们有一个包含数据包信息的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

所以我使用这些结构来填充我的以太网 - &gt; IP - &gt; 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中检查此数据包。

1 个答案:

答案 0 :(得分:2)

你真的不需要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返回的值,标题与上面的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校验和。

for x86想到uint16_t = unsigned short,uint8_t = unsigned char