确定程序集的 PEFileKind 的好方法?
Good approach to determine the PEFileKind of an assembly?
在 C# 或 VB.NET 中,我想知道哪种方法是确定通过 反射 加载的程序集的 PEFileKinds 的最佳方法。换句话说,确定程序集是 WinExe、控制台应用程序还是动态 link 库。
我找到了 解决方案(该问题中提出的其他解决方案无效),但如果我没记错的话,我认为这意味着假设加载的文件是 .NET 程序集,并且, 手动解析 PE header 似乎有点整洁。
我也找到了 this other 解决方案,但阅读评论似乎在某些情况下无效。
出于这些原因,我想知道是否存在一种真正安全的托管方式,最好是通过 反射 来确定加载程序集的 PE 文件类型。
我确定 System.Reflection.Emit.PEFileKinds
枚举不只是为了装饰目的而存在,如果该枚举存在,那么它的逻辑就是认为 member/function 可能是我在 [= 中遗漏的26=]Reflection 内部使用该枚举的命名空间 return PE 文件类型的 Assembly
对象,但是,我设法查看 [=11= 的私有成员] class 通过 Reflection 和其他相关的 classes,我没有发现任何相关的东西。
根据 a search of the reference source, the PEFileKinds
enum is only used in AssemblyBuilder
and ModuleBuilder
(and the non-public helper types for them). This enum and the classes are found in the System.Reflection.Emit
namespace - 例如,它们旨在用于编写程序集,而不是阅读。
然而,the official System.Reflection.Metadata
NuGet package exposes the relevant values of an assembly's PE header in its System.Reflection.PortableExecutable
namespace。您可以使用这些 headers 来反向工程等效的 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.
您可能还可以通过 third-party 库获取此信息,例如 Mono.Cecil or, as Lex Li mentioned, PeNet。
在 C# 或 VB.NET 中,我想知道哪种方法是确定通过 反射 加载的程序集的 PEFileKinds 的最佳方法。换句话说,确定程序集是 WinExe、控制台应用程序还是动态 link 库。
我找到了
我也找到了 this other 解决方案,但阅读评论似乎在某些情况下无效。
出于这些原因,我想知道是否存在一种真正安全的托管方式,最好是通过 反射 来确定加载程序集的 PE 文件类型。
我确定 System.Reflection.Emit.PEFileKinds
枚举不只是为了装饰目的而存在,如果该枚举存在,那么它的逻辑就是认为 member/function 可能是我在 [= 中遗漏的26=]Reflection 内部使用该枚举的命名空间 return PE 文件类型的 Assembly
对象,但是,我设法查看 [=11= 的私有成员] class 通过 Reflection 和其他相关的 classes,我没有发现任何相关的东西。
根据 a search of the reference source, the PEFileKinds
enum is only used in AssemblyBuilder
and ModuleBuilder
(and the non-public helper types for them). This enum and the classes are found in the System.Reflection.Emit
namespace - 例如,它们旨在用于编写程序集,而不是阅读。
然而,the official System.Reflection.Metadata
NuGet package exposes the relevant values of an assembly's PE header in its System.Reflection.PortableExecutable
namespace。您可以使用这些 headers 来反向工程等效的 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.
您可能还可以通过 third-party 库获取此信息,例如 Mono.Cecil or, as Lex Li mentioned, PeNet。