代码之家  ›  专栏  ›  技术社区  ›  doppelfish

给我命名一个二进制分析器。二进制数据的分析器[关闭]

  •  19
  • doppelfish  · 技术社区  · 14 年前

    所以,我得到了这些数据。从网络套接字,或从文件中。我正在拼凑代码来解释数据。读取一些字节,检查一些标志,一些字节指示后面有多少数据。读取大量数据,冲洗,重复。

    这个任务让我想起了很多解析源代码的事情。我对雷克斯/雅克和安特尔很舒服,但他们不能胜任这项任务。您不能将位和原始字节指定为令牌(也许您可以,但我不知道如何指定),并且不能将它们哄骗为“读取两个字节,使它们成为无符号16位整数,调用它” n 然后读 n 字节。

    然后,当以系统的方式定义协议/数据格式的规范(并非所有规范都是这样)时,应该有一种系统的方式来读取根据协议格式化的数据。对吗?

    一定有个工具可以做到这一点。

    8 回复  |  直到 7 年前
        1
  •  8
  •   Community holdenweb    7 年前

    你可以试着雇用 Boost.Spirit (V2)最近 binary parsing tools ,注意结尾 native mixed parsers

    // This is not a complete and useful example, but just illustration that parsing
    // of raw binary to real data components is possible
    typedef boost::uint8_t byte_t;
    byte_t raw[16] = { 0 };
    char const* hex = "01010000005839B4C876BEF33F83C0CA";
    my_custom_hex_to_bytes(hex, raw, 16);
    
    // parse raw binary stream bytes to 4 separate words
    boost::uint32_t word(0);
    byte_t* beg = raw;
    boost::spirit::qi::parse(beg, beg + 16, boost::spirit::qi::dword, word))
    

    更新:我发现了类似的问题,Joel de Guzman在他的答案中确认了二进制解析器的可用性: Can Boost Spirit be used to parse byte stream data?

        2
  •  10
  •   dpm_min    8 年前

    Kaitai Struct 最近出现了一个解决这个问题的方案:从规范生成二进制解析器。您可以提供一个基于yaml/json格式的任意数据结构序列化方案,如下所示:

    meta:
      id: my_struct
      endian: le
    seq:
      - id: some_int
        type: u4
      - id: some_string
        type: str
        encoding: UTF-8
        size: some_int + 4
      - id: another_int
        type: u4
    

    使用编译它 ksc (它们提供一个引用编译器实现),和VoILA,在任何支持的编程语言中都有一个解析器,例如,C++中的解析器:

    my_struct_t::my_struct_t(kaitai::kstream *p_io, kaitai::kstruct *p_parent, my_struct_t *p_root) : kaitai::kstruct(p_io) {
        m__parent = p_parent;
        m__root = this;
        m_some_int = m__io->read_u4le();
        m_some_string = m__io->read_str_byte_limit((some_int() + 4), "UTF-8");
        m_another_int = m__io->read_u4le();
    }
    

    或者在Java中:

    private void _parse() throws IOException {
        this.someInt = this._io.readU4le();
        this.someString = this._io.readStrByteLimit((someInt() + 4), "UTF-8");
        this.anotherInt = this._io.readU4le();
    }
    

    添加到项目后,它提供了一个非常直观的API(比如Java中的一个例子,但是它们支持更多的语言):

    // given file.dat contains 01 00 00 00|41 42 43 44|07 01 00 00
    
    MyStruct s = MyStruct.fromFile("path/to/file.dat");
    s.someString() // => "ABCD"
    s.anotherInt() // => 263 = 0x107
    

    它支持不同的词尾、条件结构、子结构等等。相当复杂的数据结构,例如 PNG image file format PE executable 可以解析。

        3
  •  2
  •   Craig McQueen Dr. Watson    7 年前

    这个 Construct 用Python编写的解析器在这个领域做了一些有趣的工作。

    该项目有许多作者和停滞期,但截至2017年,似乎再次活跃起来。

        4
  •  1
  •   bmargulies    14 年前

    阅读ASN.1。如果您可以用它的术语描述二进制数据,那么您可以使用各种可用的工具包。不适合胆小的人。

        5
  •  1
  •   noname    12 年前
        6
  •  0
  •   Community holdenweb    7 年前

    当然,没有什么能阻止您像处理文本解析器一样,为二进制数据编写一个递归的合适的解析器。如果您需要阅读的格式不太复杂,这是一种合理的继续阅读的方法。

    当然,如果你的格式是 非常 很简单,你可以看看 Reading binary file defined by a struct 以及类似的问题。

    我不知道任何非文本输入的解析器生成器,尽管它们也是可能的。


    如果您不熟悉手工编写的代码解析器,那么规范的问题是 Learning to write a compiler .这个 Crenshaw tutorial (和) in PDF )是一个快速阅读。

        7
  •  0
  •   fche    13 年前

    另请参见Google协议缓冲区。

        8
  •  0
  •   Albin Stigo    9 年前

    有一个叫做binpac的工具可以做到这一点。

    http://www.icsi.berkeley.edu/pubs/networking/binpacIMC06.pdf