【问题标题】:Base64 encoded string searchBase64 编码字符串搜索
【发布时间】:2008-12-07 04:43:20
【问题描述】:

我有一个 base64 编码的字符串。如何搜索此字符串以检查此字符串是否包含未编码的特定子字符串?我不想解码那个字符串然后搜索它。

我可以只编码那个特定的子字符串,然后使用编码的子字符串搜索编码的字符串吗?

谢谢,

【问题讨论】:

    标签: java search base64 encode


    【解决方案1】:

    最好的方法可能是对字符串进行解码。但是,如果确实有必要,可以即时执行此操作,而不是先进行完整解码,然后再进行搜索。您必须执行一次搜索,并且只解码您当前正在检查的那部分。这很可能仅在您确实不想(或不能)在内存中存储两次的非常非常大的字符串时才有用。

    如果您搜索的字符串足够长,您还可以使用不同的填充(例如“”、“x”和“xx”)对该字符串进行三次编码,然后搜索没有前 4 个和后 4 个字符的字符串(你不想匹配填充)。当您找到匹配项时,您必须确保对齐与填充相对应,并验证您尚未匹配的部分(由于填充)也在适当的位置。当然,后者确实需要一些解码。

    【讨论】:

    • 很好,很彻底。我肯定会去即时解码,你解码字符但不存储它们。其他任何事情都将是噩梦。但如果你必须受苦,这个答案会告诉你如何:-)
    【解决方案2】:

    假设您知道所涉及的 base64 编码的确切形式,您可以对字符串进行编码,就好像它发生在三个偏移量中的每一个处一样(start%3 == 0, start%3 == 1, start%3 == 2 )。您必须巧妙地处理字符串的开头和结尾,因为这些字符会受到周围数据的影响。然后,您可以只使用普通的 IndexOf 或其他任何东西来检查字符串的中间部分,然后更智能地检查开始和结束。

    虽然我个人不会遇到所有这些麻烦 - 正如其他建议所建议的那样,只需解码然后搜索即可。 会更容易做到正确。

    【讨论】:

      【解决方案3】:

      Base64 可以通过不同的算法或实现采用多种不同的形式或含义。即使查看Wikipedia 上的示例,也可以看到字符的编码值可能会根据位置而变化。简短回答:不,您不能只对字符串进行编码并在较大的编码文本中进行搜索。

      【讨论】:

      • 良好的外部参照;不确定“不同的含义”。相同的文本可以以 3 种不同的形式编码,具体取决于它是字符串中的第一个、第二个还是第三个字节。这肯定会使搜索复杂化。
      • 是的,这就是我试图理解和简化的内容。
      【解决方案4】:

      正如其他人所指出的,对子字符串进行编码并直接使用它进行搜索可能具有挑战性。不过,从子字符串创建正则表达式会更容易一些。

      通过一个示例,考虑确定 Base64 编码数据是否对应于 Windows 可执行文件的用例。一些恶意软件包含 Base64 编码的 EXE,它将在受感染的系统上执行,并且在进行恶意软件分析以检测这一点时非常有用。可以通过在数据开头查找MZ 和之后某处查找PE\x00\x00 来识别Windows 可执行文件。

      Base64 的工作原理是将字节流解释为 6 位值,默认情况下对应于字符 AZaz09、@987654332 @ 和 \。下表显示了这些映射:

      首先,首先将MZ 转换为其二进制等效项(在这种情况下,我们可以假设字符集是ASCII,所以M01001101Z01011010)。将这 16 位分成 6 位组会产生:

      010011 010101 1010xx
      T      V      ???
      

      由于 16 不能被 6 整除,因此最后两位取决于MZ 后面的数据。但是,由于仅缺少两位,因此该字符只有四个可能的值:

      101000: o
      101001: p
      101010: q
      101011: r
      

      因此,要在 Base64 编码文本块的开头查找 MZ,可以使用正则表达式 ^TV[o-r]

      寻找PE\x00\x00 更具挑战性,因为我们不知道它前面出现了多少个字符。根据 8 位集合如何划分为 6 位集合以形成 Base64 输出,需要考虑三种不同的情况:

      • 零前字节:前字节中的任何位都不会影响第一个字符 (0 % 6 == 0)
      • 前一个字节:前一个字节的两位影响第一个字符(8 % 6 == 2;最后两位溢出)
      • 前两个字节:前一个字节的四位影响第一个字符(16 % 6 == 4;最后四位溢出)
      • 前面三个字节:前面字节中的任何位都不会影响第一个字符 (24 % 6 == 0)
      • ...等等

      解决三个案例:

      Zero-bit shift:
      P        E        \x00     \x00
      01010000 01000101 00000000 00000000
      becomes:
      010100 000100 010100 000000 000000 00xxxx
      U      E      U      A      A      [A-P]
      
      Two-bit shift:
      ???      P        E        \x00     \x00
      xxxxxxxx 01010000 01000101 00000000 00000000
      becomes:
      xxxxxx xx0101 000001 010100 000000 000000 0000xx
             [FVl1] B      F      A      A      [A-D]
      
      Four-bit shift:
      ???      ???      P        E        \x00     \x00
      xxxxxxxx xxxxxxxx 01010000 01000101 00000000 00000000
      becomes:
      xxxxxx xxxxxx xxxx01             010000 010001 010000 000000 000000
                    [BFJNRVZdhlptx159] Q      R      Q      A      A
      

      总的来说,您可以使用以下正则表达式来确定 Base64 编码的数据是否是 Windows 可执行文件:

      ^TV[o-r][A-Za-z0-9\+/]+(?:UEUAA[A-P]|[FVl1]BFAA[A-D]|[BFJNRVZdhlptx159]QRQAA)
      

      请注意,在有效的可执行文件中,DOS 标头和 PE 标头之间的空间可能受到限制,因此 [A-Za-z0-9\+/]+ 可以替换为更小的界限。

      Base64 字符表来自:https://en.wikipedia.org/wiki/Base64#Base64_table

      【讨论】:

        【解决方案5】:

        您不能只搜索编码的子字符串。您的搜索字符串将根据其在原始字符串中出现的位置进行不同的编码。我认为您需要解码整个字符串,然后搜索您的子字符串。

        【讨论】:

          【解决方案6】:

          您可以将纯文本和 base64 字符串转换为它们的字节或十六进制表示。然后,您可以像搜索任何其他字符串一样搜索字节或十六进制。然后,您不必进行位移或类似的任何花哨的操作,因为一旦将字符串编码转换为字节,它们之间就没有区别了。

          可以在此处找到 JavaScript 实现:https://github.com/nanaknihal/js-search-plaintext-within-base64

          【讨论】:

          • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
          • 感谢您的反馈——想知道为什么它被否决了。它背后的逻辑是将两者都转换为它们的字节或十六进制,然后像搜索任何其他字符串一样搜索字节或十六进制。然后你不必做任何花哨的位移
          猜你喜欢
          • 1970-01-01
          • 2011-04-22
          • 2018-12-28
          • 1970-01-01
          • 1970-01-01
          • 2012-11-13
          • 2017-06-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多