sch*_*tbi 17 c# dll .net-assembly
检查DLL文件是Win32 DLL还是CLR程序集的最佳方法是什么?目前我使用此代码
try
{
this.currentWorkingDirectory = Path.GetDirectoryName(assemblyPath);
//Try to load the assembly.
assembly = Assembly.LoadFile(assemblyPath);
return assembly != null;
}
catch (FileLoadException ex)
{
exception = ex;
}
catch (BadImageFormatException ex)
{
exception = ex;
}
catch (ArgumentException ex)
{
exception = ex;
}
catch (Exception ex)
{
exception = ex;
}
if (exception is BadImageFormatException)
{
return false;
}
Run Code Online (Sandbox Code Playgroud)
但我喜欢在加载前检查,因为我不想要那些例外(时间).
有没有更好的办法?
Mit*_*eat 18
检查PE头:
DOS标头从0x0开始,0x3c的DWORD包含指向PE签名的指针(通常为0x80),为4字节,接下来的20个字节为COFF标头,然后是PE标头(在0x9处.PE标头为224)字节并包含数据目录(96字节到PE头= 0xf.第15个条目(在0x16是CLR头描述符(有时称为COM描述符,但这与COM没有任何关系).如果这是空(即从0x168到0x16f的8个字节中的0)然后该文件不是.NET程序集.如果要检查它是否是COM DLL,那么您应该查看它是否导出GetClassObject.
更新:有一种更".NET"的方式来完成这个:
使用Module.GetPEKind方法并检查PortableExecutableKinds枚举:
NotAPortableExecutableImage该文件不是可移植可执行(PE)文件格式.
ILOnly可执行文件仅包含Microsoft中间语言(MSIL),因此对于32位或64位平台而言是中立的.
Required32Bit可执行文件可以在32位平台上运行,也可以在64位平台上的32位Windows Windows(WOW)环境中运行.
PE32Plus可执行文件需要64位平台.
Unmanaged32Bit可执行文件包含纯非托管代码.
如果一个程序集被加载,例如Assembly.LoadFile(dotNetDllorExe)并且没有抛出任何异常,那么它就是一个有效的.NET程序集.如果不是那么它将抛出"BadImageFormatException".
通过加载和检查是否抛出异常来检查文件的天气是否装配的想法; 看起来不太干净.在异常使用所有异常之后.
它验证文件头以检查它是否是托管程序集.在ECMA规范分区II - 随.NET SDK一起提供的元数据中,您会看到PE格式中有一个单独的CLI标头.它是PE可选标头中的第15个数据目录.所以,简单来说,如果我们在这个数据目录中有价值,那么这意味着这是一个有效的.NET程序集,否则就不是.
internal static class PortableExecutableHelper
{
internal static bool IsDotNetAssembly(string peFile)
{
uint peHeader;
uint peHeaderSignature;
ushort machine;
ushort sections;
uint timestamp;
uint pSymbolTable;
uint noOfSymbol;
ushort optionalHeaderSize;
ushort characteristics;
ushort dataDictionaryStart;
uint[] dataDictionaryRVA = new uint[16];
uint[] dataDictionarySize = new uint[16];
Stream fs = new FileStream(peFile, FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(fs);
//PE Header starts @ 0x3C (60). Its a 4 byte header.
fs.Position = 0x3C;
peHeader = reader.ReadUInt32();
//Moving to PE Header start location...
fs.Position = peHeader;
peHeaderSignature = reader.ReadUInt32();
//We can also show all these value, but we will be
//limiting to the CLI header test.
machine = reader.ReadUInt16();
sections = reader.ReadUInt16();
timestamp = reader.ReadUInt32();
pSymbolTable = reader.ReadUInt32();
noOfSymbol = reader.ReadUInt32();
optionalHeaderSize = reader.ReadUInt16();
characteristics = reader.ReadUInt16();
/*
Now we are at the end of the PE Header and from here, the
PE Optional Headers starts...
To go directly to the datadictionary, we'll increase the
stream’s current position to with 96 (0x60). 96 because,
28 for Standard fields
68 for NT-specific fields
From here DataDictionary starts...and its of total 128 bytes. DataDictionay has 16 directories in total,
doing simple maths 128/16 = 8.
So each directory is of 8 bytes.
In this 8 bytes, 4 bytes is of RVA and 4 bytes of Size.
btw, the 15th directory consist of CLR header! if its 0, its not a CLR file :)
*/
dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + 0x60);
fs.Position = dataDictionaryStart;
for (int i = 0; i < 15; i++)
{
dataDictionaryRVA[i] = reader.ReadUInt32();
dataDictionarySize[i] = reader.ReadUInt32();
}
if (dataDictionaryRVA[14] == 0)
{
Console.WriteLine("This is NOT a valid CLR File!!");
return false;
}
else
{
Console.WriteLine("This is a valid CLR File..");
return true;
}
fs.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11666 次 |
| 最近记录: |