【问题标题】:Writing actual packet data, pcap写入实际数据包数据,pcap
【发布时间】:2014-04-23 09:12:32
【问题描述】:

我正在编写一个程序,应该将 strongSwan 日志转换为 WireShark 数据包。因此,例如,我们在文本文件中有一个像这样的序列。

Feb 14 14:53:22 dubu12 charon: 13[IKE] sending cert request for "C=RU, ST=NW, O=Company, CN=StronSwanSERV"
Feb 14 14:53:22 dubu12 charon: 13[IKE] shared Diffie Hellman secret => 128 bytes @ 0x7f36e8001ed0
Feb 14 14:53:22 dubu12 charon: 13[IKE] 0: 23 D9 25 9F F1 78 9F C4 83 89 2F 06 E3 DB C2 69 #.%..x..../....i
Feb 14 14:53:22 dubu12 charon: 13[IKE] 16: 24 06 49 01 75 2E 6A 4F AF E6 07 9C F9 77 07 A1 $.I.u.jO.....w..
Feb 14 14:53:22 dubu12 charon: 13[IKE] 32: 02 D8 52 0C F0 27 10 14 19 69 B8 B7 CB 0F 41 40 ..R..'...i....A@
Feb 14 14:53:22 dubu12 charon: 13[IKE] 48: 72 AA 50 8C 90 FF 4D C8 66 88 6C F8 44 B3 2E A2 r.P...M.f.l.D...
Feb 14 14:53:22 dubu12 charon: 13[IKE] 64: 62 F4 C8 4B 31 3C A9 DF DE C8 DF 85 6D 3E E7 56 b..K1<......m>.V
Feb 14 14:53:22 dubu12 charon: 13[IKE] 80: 9D 32 6B 29 C9 7E 9F 41 9C C2 EB D8 8D 3F 51 68 .2k).~.A.....?Qh
Feb 14 14:53:22 dubu12 charon: 13[IKE] 96: 75 74 3A 96 D6 09 B6 34 38 D8 28 5E 6F 7D 20 44 ut:....48.(^o} D
Feb 14 14:53:22 dubu12 charon: 13[IKE] 112: E3 3F 72 1E DD A5 73 B0 CC E0 92 8C 7A 54 3B 34 .?r...s.....zT;4

我有自己的类,通过 Libpcap 执行所有操作。

int TgrReader::dump(std::deque<TgrPacket> deqTgrPacket, char* fileName)
{
  pcap_t* pHandle = pcap_open_dead(DLT_RAW, 65535);
  pcap_dumper_t* pDumper = pcap_dump_open(pHandle, fileName);
  std::deque<TgrPacket>::iterator iter=deqTgrPacket.begin();
  while(iter != deqTgrPacket.end())
  {
    pcap_dump(reinterpret_cast<u_char*>(pDumper), &(iter->header), reinterpret_cast<u_char*>(iter->data.toLocal8Bit().data()));
    iter++;
  }
  pcap_dump_close(pDumper);
  pcap_close(pHandle);
  return 0;
}

所以,我们有那个数据包。我们制作了数据包的标头,数据(从 0: 到 112: 的字符串)存储在 char* 变量中。我正在尝试转储这样的数据包,但它以某种方式弄乱了位置

. 在这种情况下,我试图用谷歌搜索正确的倾销方式,但似乎找不到解决方案。有谁知道我做错了什么?

=============================================

更新: 带有数据的双端队列包含以下元素:

struct TgrPacket
{
  pcap_pkthdr header;
  QString data;
  TgrPacket(pcap_pkthdr pHeader, QString pData);
};

因此数据存储在单个 QString 中。在扫描文本文件时,我正在寻找第一个数据字符串(看起来像“... 0: 23 D9 25...”)并从“:”中剪切所有内容并将其附加到 QString 数据中。然后我从下一个字符串中获取数据,直到我到达这个数据包的最后一行,然后我再次开始寻找新的数据包。完成附加 QString 后,我得到了数据包的时间,将其转换为 time_val 并创建一个带有 time_val 字段和带有数据的 QString 的结构。 想看的话功能是这样的:

std::deque<TgrPacket> TgrReader::readFile(std::deque<TgrPacket>& deqTgrPacket)
{
    //1) read to "dataString"
    //2) parse it
    //3) loop add data from "dataString" to "qDataString" if data was found
    //4) eject time from "dataString" and add it to "vTm", which is struct tm type
    //5) create packet and add to deque
    char* dataString = new char [ 255 ];
    char* dataBlock = new char [40];
    QString* qTimeString = new QString;
    QString* qTempDataString = new QString;
    time_t vTime_t = 0;
    struct tm* vTm = new tm;
    while(!feof(srcFile))
    {
        fgets(dataString, 65535, srcFile);
        switch(parse(dataString, stringState))
        {
        case BLANK: //skip blank lines
            stringState = BLANK;
            break;
        case LINE: //read data lines until last one is read
            stringState = LINE;
            qTimeString = new QString;            
            qTempDataString = new QString;
            vTime_t = 0;
            vTm = new tm;
            while(stringState != END && !feof(srcFile))
            {
                sscanf(dataString, "%*s %*s %*s %s", dataBlock);
                for(int j = 39 + strlen(dataBlock); j < strlen(dataString) - 17; j++)
                {
                    qTempDataString->append(dataString[j]);
                }
                fgets(dataString, 65535, srcFile);                
                qTimeString->append(dataString);
                stringState = parse(dataString, stringState);
            }
            stringState = END;
            qTimeString->truncate(15);
            vTm->tm_year = 114;
            strptime(qTimeString->toLatin1().data(),"%h  %d %H:%M:%S",vTm);
            vTime_t = mktime(vTm);
            deqTgrPacket.push_back(createPacket(&vTime_t, qTempDataString, qTempDataString->length()));
            break;
        }
    }
    return deqTgrPacket;
}

【问题讨论】:

  • 问题可能在于您如何读取源日志文件以及如何在现有结构中存储数据。请显示所涉及的结构以及如何从日志文件中读取/解析实际数据。
  • 为您添加了更多信息,希望这将有助于我们找到解决方案
  • 首先,您的代码中有 undefined behavior:您为 dataString 分配了 255 个字符,但随后最多允许读取 65535 个字节。此外,您永远不应该while (!feof(...)),因为在您尝试从文件之外读取之前不会设置 EOF 标志。在这种情况下,请执行 while (fgets(...) != NULL)。为什么你使用 C 文件 I/O 而不是 C++ 流?以及为什么指向 QString 对象的指针(您分配了两次并且从不释放)。而且你也永远不会释放vTm 对象(这里也不需要指针)。
  • 即使有些函数需要指针,你实际上也不必使用指针和new。以您的mktime 调用为例,它希望您提供指向struct tm 的指针,因此您创建一个指针并为其分配内存。相反,您可以只声明一个非指针变量并使用地址运算符来创建它的指针,例如 tm vTm; ...; vTime_t = mktime(&amp;vTm); 没有指针,没有分配,没有内存泄漏。
  • 感谢所有的建议,我肯定会在未来继续努力。但是,目前的主要问题仍然是不正确的数据写入。对此有什么想法吗?

标签: c++ wireshark packet dump libpcap


【解决方案1】:

虽然我并不真正了解 PCAP,但我会做一个有根据的猜测:pcap_dump 函数期望数据(作为最后一个参数传递)是数据包的实际 二进制 数据.由于您将数据读取并存储为字符串,因此pcap_dump 将转储 ASCII 值。

您可能应该将数据解析为二进制数据的字节而不是字符串。使用标准库(因为我不太了解 Qt)你可能会做这样的事情:

std::istringstream istr(qTempDataString->toStdString());
std::string value;
std::string data;
while (istr >> value)
    data += static_cast<char>(std::stoi(value, nullptr, 16));

*qTempDataString = QString::fromStdString(data);

这里的重要位是istr &gt;&gt; value,它从流中提取一个以空格分隔的“单词”并将其放入字符串value,以及std::stoi(value, nullptr, 16),它接收字符串并将其转换为数字(@ 987654327@ 是基数,是十六进制)。

【讨论】:

  • 非常感谢,它看起来像解决方案。最后一件事不起作用的是,当我应用此算法时,它对于 17、20、33 等数字(不带字母)可以正常工作,但是当它尝试转换 BB、DC 和 B9 时,它会给出 ef、bf 和 bd分别。有什么想法吗?
  • @LeonidBor 如果基数设置为 16,那么它应该适用于所有十六进制数字(包括字母)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多