c# – 通过直接读取PE确定dll是否为.valid CLR dll(64位问题)
发布时间:2020-12-15 04:10:11 所属栏目:百科 来源:网络整理
导读:我正在努力将32位Web应用程序迁移到64位,并且我的插件加载器代码存在一些问题. 在32位版本中,我们扫描所有.net dll的webapps bin目录,然后使用Assembly.Load加载它们以检查我们的插件属性是否存在. 我们使用公共域代码以相当漂亮的方式完成了这项工作: ///
我正在努力将32位Web应用程序迁移到64位,并且我的插件加载器代码存在一些问题.
在32位版本中,我们扫描所有.net dll的webapps bin目录,然后使用Assembly.Load加载它们以检查我们的插件属性是否存在. 我们使用公共域代码以相当漂亮的方式完成了这项工作: /// <summary> /// Returns true if the file specified is a real CLR type,/// otherwise false is returned. /// False is also returned in the case of an exception being caught /// </summary> /// <param name="file">A string representing the file to check for /// CLR validity</param> /// <returns>True if the file specified is a real CLR type,/// otherwise false is returned. /// False is also returned in the case of an exception being /// caught</returns> public static bool IsDotNetAssembly(String file) { Stream fs = new FileStream(@file,FileMode.Open,FileAccess.Read); try { BinaryReader reader = new BinaryReader(fs); //PE Header starts @ 0x3C (60). Its a 4 byte header. fs.Position = 0x3C; uint peHeader = reader.ReadUInt32(); //Moving to PE Header start location... fs.Position = peHeader; uint peHeaderSignature = reader.ReadUInt32(); ushort machine = reader.ReadUInt16(); ushort sections = reader.ReadUInt16(); uint timestamp = reader.ReadUInt32(); uint pSymbolTable = reader.ReadUInt32(); uint noOfSymbol = reader.ReadUInt32(); ushort optionalHeaderSize = reader.ReadUInt16(); ushort characteristics = reader.ReadUInt16(); // PE Optional Headers // To go directly to the datadictionary,we'll increase the stream's current position to with 96 (0x60). // 28 bytes for Standard fields // 68 bytes for NT-specific fields // 128 bytes DataDictionary // DataDictionay has 16 directories // 8 bytes per directory (4 bytes RVA and 4 bytes of Size.) // 15th directory consist of CLR header! (if its 0,it is not a CLR file ) uint[] dataDictionaryRVA = new uint[16]; uint[] dataDictionarySize = new uint[16]; ushort 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) { fs.Close(); return false; } else { fs.Close(); return true; } } catch (Exception) { return false; } finally { fs.Close(); } } 现在问题是我们现在必须处理64位或平台独立的dll,并且偏移量似乎已经改变,并且此代码失败.有没有人知道对上述代码的正确修改,对于有效的64位唯一OR平台无关的dll返回true? 解决方法
您的代码不适用于x64-Bit DLL的原因是
因为图像可选的头部大小为x64-Bit DLL和 x86-Bit DLL是不同的.你必须采取不同的方式 图像可选的标题大小考虑在内以便确定 是否给定的DLL是.Net DLL. 3.4节(可选标题)中的PE file format specification describes >对于PE32(x86)图像,偏移量为0x60(就像在代码中一样)和 为了确定给定的DLL是否是x64位DLL >值0x20b表示PE32, 我扩展了你的例子: Stream fs = new FileStream(@file,FileAccess.Read); try { BinaryReader reader = new BinaryReader(fs); //PE Header starts @ 0x3C (60). Its a 4 byte header. fs.Position = 0x3C; uint peHeader = reader.ReadUInt32(); //Moving to PE Header start location... fs.Position = peHeader; uint peHeaderSignature = reader.ReadUInt32(); ushort machine = reader.ReadUInt16(); ushort sections = reader.ReadUInt16(); uint timestamp = reader.ReadUInt32(); uint pSymbolTable = reader.ReadUInt32(); uint noOfSymbol = reader.ReadUInt32(); ushort optionalHeaderSize = reader.ReadUInt16(); ushort characteristics = reader.ReadUInt16(); long posEndOfHeader = fs.Position; ushort magic = reader.ReadUInt16(); int off = 0x60; // Offset to data directories for 32Bit PE images // See section 3.4 of the PE format specification. if (magic == 0x20b) //0x20b == PE32+ (64Bit),0x10b == PE32 (32Bit) { off = 0x70; // Offset to data directories for 64Bit PE images } fs.Position = posEndOfHeader; uint[] dataDictionaryRVA = new uint[16]; uint[] dataDictionarySize = new uint[16]; ushort dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + off); fs.Position = dataDictionaryStart; for (int i = 0; i < 15; i++) { dataDictionaryRVA[i] = reader.ReadUInt32(); dataDictionarySize[i] = reader.ReadUInt32(); } if (dataDictionaryRVA[14] == 0) { fs.Close(); return false; } else { fs.Close(); return true; } } catch (Exception) { return false; } finally { fs.Close(); } 在Windows SDK中,还为PE32 / PE32可选标头定义了结构. 希望这可以帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |