regex 哪些正则表达式字符串可以区分包含“PE null null L”和“PE null null d”的文件

siotufzp  于 2023-01-31  发布在  其他
关注(0)|答案(1)|浏览(96)

我需要一个快速简单的方法来知道在一个给定的目录中有多少DLL是32位的,有多少是64位的。当我想到一个更简单的解决方案时,我正准备写一个PowerShell脚本。我在下面展示了我的想法可以工作,但我需要一点正则表达式的帮助才能使它正常工作。
已经证明,可以在记事本中打开dll文件以显示位(32或64)。字母“L”和“d”分别表示32位和64位reference。记事本或十六进制编辑器将更准确地显示“PE”之间实际上有2个空字符。下图中所示的另一个字符是从Notepad复制的。

不幸的是,我的一些目录包含数百个DLL,所以用记事本或其他工具一次打开一个DLL是不现实的。有一些强大的“grep功能”文件搜索工具可以搜索包含指定搜索字符串的文件目录。此外,其中一些可以执行regular expression(regex)搜索。因为我知道区分32位和64位DLL的唯一字符串(如上所示),这样的文件搜索工具应该能够快速清点任何目录中的DLL类型,在我看来,最好的此类文件搜索工具是grepWin,它可以免费下载和安装。
我的第一个尝试是regex搜索字符串“.PE(“\x00”)*”,它可以分解如下。

下图显示了使用grepWin和搜索字符串“.PE”进行搜索的结果(“\x00”)*”查找包含276个dll文件的指定目录。它显示找到的276个dll中有276个包含“PE”,后跟多个空字符。它还显示实际上找到了数千个匹配项。这是因为正则表达式搜索在第一个匹配后继续,并在不可避免地“随机”出现的较大文件中找到了更多的匹配。

下表显示了O-O-O建议的正则表达式字符串“PE.{2}L”和“PE.{2}d”的搜索结果。这些搜索字符串可以找到所有文件,但遗憾的是,某些dll文件被计算了两次,因为32位和64位dll的总和超过了目录中dll文件的总数。

下面使用“PE.{2}L”和“PE.{2}d”搜索结果的屏幕截图显示,匹配项超过了找到的文件数,这意味着正则表达式搜索超出了第一个匹配项。

因此,我只需要知道如何修改这些正则表达式搜索字符串,以停止搜索3个字符后,第一个“PE”被发现。我知道这可以做到使用“.*?”修饰符,但我还没有能够让它工作。这里是我的问题。
·如何修改这些搜索字符串,使其在找到第一个“PE”后停止阅读3个字符?
任何正则表达式搜索字符串都可以通过使用grepWin搜索任何dll目录来验证。要确保正确,搜索字符串必须生成与文件数量相等的匹配项,这与上面显示的示例不同。这将验证搜索是否在找到第一个匹配项后停止。

rta7y2nd

rta7y2nd1#

这不可能是真的:
1.正则表达式.PE("\x00")*将搜索:
1.任何字符(为什么?排除在文件开头找到它?)
1.字符P
1.字符E
1.下列国家集团:
1.字符"
1.对应于字节值00的字符
1.字符"
......按照*,匹配次数从没有到无数(为什么不希望正好是2?)
1.搜索PE\x00\x00不是更好吗?除非 * grepWin * 自带正则表达式的风格,其中引号在组中有特殊的含义。但我对此表示高度怀疑。
1.正则表达式PE.{2}LPE.{2}d就像没有人会使用的短语,为什么不直接写PE..L呢?

从技术Angular 来看

我们可以进一步限制正则表达式,使其不过度匹配太多的误报,也不忽略我们应该检查的内容(这有助于了解可移植可执行文件的布局):

  • 每个可执行文件都以DOS header开头,它总是64字节长,几乎总是**以MZ**开头(在罕见/历史案例中也有ZMNE,但不适用于我们的案例)。
  • NT header始终以PE\0\0开头(或十六进制50 45 00 00,或正则表达式PE\x00\x00),则为followed by\x64\x86(对于64位)或\x4c\x01(对于32位)。这个头可以稍后开始,但是我们可以安全地假设在文件的前2048个字节**内找到它(很可能已经在240个字节之后)。

此外,18 bytes later我们最有可能有字节\x0b\x01\x0b\x02(或在极少数情况下\x07\x01)。

更好的正则表达式

  • 对于x64(64位),搜索^MZ.{62,2046}PE\x00\x00\x64\x86.{18}\x0b[\x01\x02]
  • 对于x86(32位),搜索^MZ.{62,2046}PE\x00\x00\x4c\x01.{18}\x0b[\x01\x02]

如果您的目标软件崩溃(尽管它称赞其regex支持,如grepWin),那么

  • 完全忽略匹配DOS标头(删除^MZ.{62,2046}
  • 或者尝试将重复减少到较小的重复,例如{62,280}

说明:
1.从文件的开头开始(实际上只是"行"的开头)
1.字符MZM标记Zbikowski)
1.任何字符至少62次,但最多2046次(像 * Notepad ++* 这样的文本编辑器可能会抱怨我们的正则表达式太复杂,这就是为什么我们也定义了一个最大值)
1.字符PEP可排序E可执行)
1.字节00 00

  • CPU架构:
  • 字节\x64\x86(对于64位(AMD)),或
  • 字节\x4c\x01表示32位(Intel 386或更高版本)。

不要只依赖于光学器件(dL),因为这样你就忽略了一半的价值,只会冒更多误报的风险。

  • 任意字符,精确18次
  • 字节0b
  • 字节0102

测试成功

  • 使用 * Notepad++ 8.4.8 * x64(确保勾选 * .匹配换行符 *)
  • C:\Windows\System32\quartz.dll
  • 使用Windows 7 x64(因此DLL应为64位):

这里最大的优势是这个正则表达式最有可能只匹配一次而不是多次,特别是在DLL中。然而,由于可执行文件没有"结束"标记,它们可以在之后携带任何格式的数据。不受意图的约束(好=自解压存档,坏=病毒),几乎没有办法排除这些-如果我们幸运的话,我们的^可以帮助我们。

相关问题