Maslinin
Maslinin

Reputation: 81

How do I get the DLL name/path from the DLLImport attribute using PEReader from System.Reflection?

I am writing a utility that disassembles dll/exe files written in c#, and then scans all types inside this file for the presence of methods imported from an unmanaged DLL. I need to get information about each imported method, including the name/path of the DLL from which this method is imported, that is, the value of the first argument of the DllImport attribute. Let's assume that there is such a function declaration in the dll/exe file:

[DllImport("C:\\TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void HelloWorld();

I am new to reflection and am trying to use PEReader to view all types and search for functions imported from DLL. I'm calling GetImport() from the System.Reflection.Metadata.MethodDefinition to determine whether the current MethodDefinition is an imported method. Via GetImport().Attributes I hope to get all the DllImport parameters, including the path of this DLL, but this does not give the desired result:

using (var fileStream = new FileStream(pathToBinary, FileMode.Open, FileAccess.Read))
{
    using (var peReader = new PEReader(fileStream))
    {
        var mdReader = peReader.GetMetadataReader();

        foreach (var typeHandler in mdReader.TypeDefinitions)
        {
            var typeDef = mdReader.GetTypeDefinition(typeHandler);

            foreach (var methodHandler in typeDef.GetMethods())
            {
                var methodDef = mdReader.GetMethodDefinition(methodHandler);
                var import = methodDef.GetImport();
                if(import.Module.IsNil)
                {
                    continue;
                }

                //Returns "CallingConventionCdecl" but not ""C:\\TestDll.dll," CallingConventionCdecl":
                var dllImportParameters = import.Attributes.ToString();
            }
        }
    }
}

That is, GetMethod().Attributes returns all DLLImport parameters except the library name/path from which the method is imported.

How do I get the DLL path from the first argument of DllImport?

Upvotes: 1

Views: 693

Answers (1)

Maslinin
Maslinin

Reputation: 81

I found a solution to my problem. So import has a Module property that returns an instance of System.Reflection.Metadata.ModuleReferenceHandle. With MetaDataReader.GetModuleReference(moduleReferenceHandle) it can be converted to System.Reflection.Metadata.ModuleReference. In turn, an instance of ModuleReference has a Name property that returns StringHandle and can also be converted to string using MetaDataReader.GetString(stringHandle). This is the name/path of the DLL.

Full resolution of the issue:

string dllPath = mdReader.GetString(mdReader.GetModuleReference(import.Module).Name);

Upvotes: 2

Related Questions