c# - 确定程序集的 PEFileKind 的好方法吗?

标签 c# .net vb.net reflection portable-executable

在 C# 或 VB.NET 中,我想知道哪种方法是确定 PEFileKinds 的最佳方法通过反射加载的程序集。换句话说,确定程序集是 WinExe、控制台应用程序还是动态链接库。

我找到了this解决方案(该问题中的其他建议解决方案无效),但如果我没有错的话,我认为这意味着假设加载的文件是.NET程序集,并且手动解析PE header 似乎有点整洁.

我还发现了this other解决方案,但阅读评论,它在某些情况下似乎无效。

出于这些原因,我想知道是否存在一种真正安全的托管方式(最好通过反射)来确定加载程序集的 PE 文件类型。

我确信 System.Reflection.Emit.PEFileKinds 枚举不只是为了装饰目的而存在,如果该枚举存在,那么它的逻辑是认为可能存在我的成员/函数在内部使用该枚举返回 Assembly 对象的 PE 文件类型的 Reflection 命名空间中错过了,但是,我设法查看了 的私有(private)成员通过 Reflection 和其他相关类的 Assembly 类,我发现没有任何相关内容。

最佳答案

根据a search of the reference sourcePEFileKinds 枚举仅在 AssemblyBuilderModuleBuilder(以及它们的非公共(public)帮助器类型)中使用。这个枚举和类可以在 System.Reflection.Emit namespace 中找到。 - 例如,它们用于编写程序集,而不是读取。

但是,the official System.Reflection.Metadata NuGet package在其 System.Reflection.PortableExecutable namespace 中公开程序集 PE header 的相关值。您可以使用这些 header 对等效的 PEFileKinds 值进行逆向工程。下面是一个 C# 示例:

using (var stream = File.OpenRead(filenameAndExtension))
{
    using (var peFile = new PEReader(stream))
    {
        var headers = peFile.PEHeaders;
        Console.WriteLine($"Reading {filenameAndExtension} with System.Reflection.Metadata");
        Console.WriteLine($"  IsDll: {headers.IsDll}");
        Console.WriteLine($"  IsExe: {headers.IsExe}");
        Console.WriteLine($"  IsConsoleApplication: {headers.IsConsoleApplication}");

        PEFileKinds reverseEngineeredKind;

        // NOTE: the header values cause IsConsoleApplication to return
        //       true for DLLs, so we need to check IsDll first
        if (headers.IsDll)
        {
            reverseEngineeredKind = PEFileKinds.Dll;
        }
        else if (headers.IsConsoleApplication)
        {
            reverseEngineeredKind = PEFileKinds.ConsoleApplication;
        }
        else
        {
            reverseEngineeredKind = PEFileKinds.WindowApplication;
        }
        Console.WriteLine($"  Reverse-engineered kind: {reverseEngineeredKind}");
    }
}

我在使用 System.Reflection.Emit 生成的程序集上运行了此代码,以确保其准确性。完整的程序在 this gist .

您或许还可以通过第三方库获取此信息,例如 Mono.Cecil或者,正如 Lex Li 提到的,PeNet .

关于c# - 确定程序集的 PEFileKind 的好方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52230763/

相关文章:

c# - ThreadPool.QueueUserWorkItem 所需的用户

c# - SQLCLR 程序集部署失败,因为程序集验证失败

javascript - asp.net - 客户端控制更改在服务器端看不到

vb.net - 如何禁用.NET WebBrowser控件中的缓存?

javascript - 如何在.Net中获取javascript的Date.parse()?

c# - .net - 棘手的 sql 事务(SQL Server,但也考虑到 Oracle,稍后再讲)

c# - Windows 应用商店 WebView 替代方案

c# - 字符串总是 Little Endian Unicode 吗?

.net - VB stringbuilder 包含

.net - 底层连接已关闭 : Could not establish trust relationship for the SSL/TLS secure channel