Определение того, является ли dll .valid CLR dll путем прямого чтения PE (64-битная проблема)

Я работаю над переносом 32-разрядного веб-приложения в 64-разрядное и испытываю некоторые проблемы с нашим кодом загрузчика плагинов.

В 32-разрядной версии мы сканируем каталог bin webapps на наличие всех .net dll, затем загружаем их с помощью 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, а смещение, похоже, изменилось, и этот код не работает. Кто-нибудь знает, как правильно модифицировать вышеприведенный код, чтобы он возвращал true для корректных 64-битных или независимых от платформы dll?

6
задан Rob 21 December 2011 в 17:24
поделиться