简体   繁体   English

C#中如何区分普通exe文件和自解压文件?

[英]How to distinguish between normal exe file and self-extracting file in C#?

I want to detect exe file that created with zip tools?我想检测使用 zip 工具创建的exe文件? like 7z or WinRAR or ..., I mean SFX (self-extracting executable) files7zWinRAR或 ...,我的意思是 SFX(自解压可执行文件)文件

So I have to find a way to distinguish between normal exe files and SFX files in C#?所以我必须找到一种方法来区分C#中的普通exe文件和SFX文件?
Are there any ways to detect them in C#?有什么方法可以在 C# 中检测它们吗?

I don't know about other utilities, but the "classic" self-extractor from Nico Mak Computing creates executables containing a _winzip_ section.我不知道其他实用程序,但来自 Nico Mak Computing 的“经典”自_winzip_器创建了包含_winzip_部分的可执行文件。 These could be detected by reading the section table of the executable, which is an array of IMAGE_SECTION_HEADER structures.这些可以通过读取可执行文件的节表来检测,它是一个IMAGE_SECTION_HEADER结构数组。

To access it without using specialized libraries, you would need to:要在不使用专门库的情况下访问它,您需要:

  • Open a stream on the file在文件上打开一个流
  • Read the 64-byte IMAGE_DOS_HEADER structure读取 64 字节的IMAGE_DOS_HEADER结构
  • Take its last member (four bytes) as the offset of the next header取其最后一个成员(四个字节)作为下一个头部的偏移量
  • Seek to this offset寻求这个偏移
  • Read the 4-byte PE magic读取 4 字节 PE 魔术
  • Read the 20-byte IMAGE_FILE_HEADER structure读取 20 字节的 IMAGE_FILE_HEADER 结构
  • Take its member SizeOfOptionalHeader (second-to-last WORD)取其成员SizeOfOptionalHeader (倒数第二个字)
  • Skip that many bytes跳过那么多字节
  • The stream is now pointing at the section table流现在指向节表

Then it's just a matter of reading the section table (the IMAGE_FILE_HEADER structure has a member NumberOfSections ), and seeing if any one of them is named _winzip_ .然后只需读取部分表(IMAGE_FILE_HEADER 结构有一个成员NumberOfSections ),并查看其中是否有任何一个名为_winzip_

The approach to take if you want to detect a self-extractor varies depending on whether you want to detect self-extractors within a known set of formats with 100% reliability or whether you want to detect unfamiliar self-extractors with less reliability.如果您想检测自解压器,所采用的方法会有所不同,具体取决于您是要检测一组已知格式中的自解压器并具有 100% 的可靠性,还是要检测不熟悉的可靠性较低的自解压器。

(Both approaches have their uses. The latter is good for calling in a human for a second opinion, for example.) (这两种方法都有其用途。例如,后者非常适合请人征求第二意见。)

Option A would be to use the same approach archival tools use.选项 A 将使用与存档工具相同的方法。

A self-extracting archive is just a regular archive, concatenated onto an EXE file, with the offsets fixed up.自解压存档只是一个常规存档,连接到一个 EXE 文件中,并固定了偏移量。 (For Zip files, you can do that manually by using zip -A from Info-ZIP ), so open the file and scan through, looking for valid RAR/Zip/etc. (对于 Zip 文件,您可以使用Info-ZIP 中的zip -A手动执行此操作),因此打开文件并扫描,寻找有效的 RAR/Zip/等。 header/trailers.标头/拖车。 (To do it efficiently, use an algorithm like Aho-Corasick to search for all candidate strings in a single pass.) (要有效地做到这一点,请使用像Aho-Corasick这样的算法在一次通过中搜索所有候选字符串。)

For extra reliability, parse the MZ and NE or PE header to figure out how many bytes to skip to get past any potential matching strings within the EXE itself.为了获得额外的可靠性,解析 MZ 和 NE 或 PE 标头以确定跳过多少字节以跳过 EXE 本身内的任何潜在匹配字符串。

Option B would be to parse the MZ header as described by Medinoc but then, instead of looking for a specific section in the PE header, calculate the total length of the NE or PE binary (Win16 self-extractors do exist, as created by tools like WinZIP 6.3 SR-1 and below) and skip it all.选项 B 将按照 Medinoc 的描述解析 MZ 标头,但随后不是在 PE 标头中查找特定部分,而是计算 NE 或 PE 二进制文件的总长度(Win16 自解压器确实存在,由工具创建)像 WinZIP 6.3 SR-1 及以下)并跳过它。

Then, do some heuristic check, such as comparing the size of the skipped EXE portion to the size of the file overall and deciding whether the smallness of the EXE portion and the largeness of the stuff concatenated onto it look characteristic of a self-extractor.然后,进行一些启发式检查,例如将跳过的 EXE 部分的大小与整个文件的大小进行比较,并确定 EXE 部分的小和连接到它的内容的大是否看起来是自解压器的特征。

(Bearing in mind that this might also catch DPMI-based DOS applications if you don't do additional checking for non-NE/non-PE files to rule them out, since they also use that "stub plus stuff concatenated on" structure.) (请记住,如果您不对非 NE/非 PE 文件进行额外检查以排除它们,这也可能会捕获基于 DPMI 的 DOS 应用程序,因为它们也使用“存根和连接的内容”结构。 )

The most reliable solution would be to combine both approaches:最可靠的解决方案是结合两种方法:

  1. Use option A and check for the identifying headers/trailers for all modern or historically common EXE-based self-extractor formats ( 7z , RAR , ACE , Zip , ARJ , ARC , Lha/LZH , Zoo , InnoSetup installer, NSIS installer, single-file InstallShield installers from the pre- .msi era, or an EXE containing a .cab or .msi bundle.)使用选项 A 并检查所有现代或历史上常见的基于 EXE 的自解压器格式( 7zRARACEZipARJARCLha/LZHZooInnoSetup安装程序、 NSIS安装程序、单-file InstallShield安装程序来自.msi时代,或包含.cab.msi包的 EXE。)

  2. If you didn't get a match, use option A to rule out .NET EXE files, common DPMI extenders, and other common bulk content that might have been concatenated onto the EXE as a poor man's resource bundle.如果您没有找到匹配项,请使用选项 A 排除 .NET EXE 文件、常见 DPMI 扩展程序和其他可能作为穷人资源包连接到 EXE 的常见批量内容。 (eg. images, audio, video, etc.) (例如图像、音频、视频等)

    To create test files for DPMI EXEs, just compile a "Hello, World!"要为 DPMI EXE 创建测试文件,只需编译一个“Hello, World!” to the DPMI target using djgpp ( Linux ) and Open Watcom C/C++ ( 1.9 , 2.0 ).使用djgpp ( Linux ) 和 Open Watcom C/C++ ( 1.9 , 2.0 ) 到 DPMI 目标。 djgpp will get you CWSDPMI, while OpenWatcom C/C++ includes the DOS/4GW, PMODE/W, DOS/32A, and CauseWay DPMI extenders, the Win386 windows extender, and is compatible with the other free/freed extenders . djgpp 将为您提供 CWSDPMI,而 OpenWatcom C/C++ 包括 DOS/4GW、PMODE/W、DOS/32A 和 CauseWay DPMI 扩展器、 Win386 windows 扩展器,并且与其他免费/释放的扩展器兼容。 (PharLap's extenders, which Microsoft licensed for inclusion with with Microsoft C/C++, are the only notable ones I'm aware of which didn't get freed, but I believe Open Watcom can at least generate the binary that they're supposed to be prepended onto.) (PharLap 的扩展程序,Microsoft 授权包含在 Microsoft C/C++ 中,是我所知道的唯一没有被释放的值得注意的扩展程序,但我相信 Open Watcom 至少可以生成他们应该生成的二进制文件放在前面。)

    You may also need to rule out executable packers, since they use a stub-based system.您可能还需要排除可执行加壳程序,因为它们使用基于存根的系统。 UPX is pretty much the only one in use today but, historically, there were a lot of them . UPX几乎是今天唯一使用的,但从历史上看,有 很多

  3. As a fallback, parse the MZ and LE , NE , or PE headers to properly count embedded resources (eg. icons) as part of the EXE portion and then, if the file is more than some percentage "extra data", it's likely to be a self-extractor.作为后备,解析MZLENEPE标头以正确计算嵌入资源(例如图标)作为 EXE 部分的一部分,然后,如果文件超过一定百分比的“额外数据”,则很可能做一个自解压者。

You can just make the .exe format into .rar format and double-click to open(NOT extract) it up to view the contents, most likely it would be a self-extracting file if your WinRAR or 7z manages to open it up for you.您可以将.exe格式转换为.rar格式并双击打开(而不是解压)它以查看内容,如果您的WinRAR7z设法打开它,它很可能是一个自解压文件你。 But if you get an error while trying to view the contents in the .rar file, then most likely it would be be a normal .exe file.但是,如果您在尝试查看.rar文件中的内容时遇到错误,那么它很可能是一个普通的.exe文件。

I believe there are other methods but this is the one that I commonly use since its quite simple.我相信还有其他方法,但这是我常用的方法,因为它非常简单。

With that being said, what you need to let the C# do is this :话虽如此,您需要让 C# 做的是:

  1. Change the file's format to .rar将文件格式更改为.rar
  2. Open up the file using WinRAR or 7z使用 WinRAR 或 7z 打开文件
  3. Using try-catch block, give an error message if fails to open , otherwise, give a positive message if opening is successful.使用try-catch块,如果打开失败给出错误信息,否则如果打开成功给出肯定信息。

If you need help with changing the file format , you can look up on this : Change File Extension Using C#如果您在更改文件格式方面需要帮助,可以查看此内容: 使用 C# 更改文件扩展名

If you need help with opening the file : How do I launch files in C#如果您在打开文件时需要帮助: 如何在 C# 中启动文件

if it is SFX from any compression it will be a standard executable file for sure..如果它是来自任何压缩的 SFX,它肯定会是一个标准的可执行文件。

so you can take approach to validate executable or not所以你可以采取方法来验证可执行文件与否

How to find if a file is an exe? 如何判断文件是否为exe?

check answer of Chris Schmich检查 Chris Schmich 的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM