如何使用来自 System.Reflection 的 PEReader 从 DLLImport 属性获取 DLL name/path?
How do I get the DLL name/path from the DLLImport attribute using PEReader from System.Reflection?
我正在编写一个实用程序来反汇编用 c# 编写的 dll/exe 文件,然后扫描此文件中的所有类型以查找是否存在从非托管 DLL 导入的方法。我需要获取每个导入方法的信息,包括从中导入该方法的 DLL 的 name/path,即 DllImport 属性的第一个参数的值。假设在dll/exe文件中有这样一个函数声明:
[DllImport("C:\TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void HelloWorld();
我是反射的新手,我正在尝试使用 PEReader
查看所有类型并搜索从 DLL 导入的函数。我从 System.Reflection.Metadata.MethodDefinition
调用 GetImport()
以确定当前 MethodDefinition 是否是导入方法。通过GetImport().Attributes
我希望得到所有的DllImport参数,包括这个DLL的路径,但是这样并没有给出想要的结果:
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();
}
}
}
}
也就是说,GetMethod().Attributes
returns 除了从中导入方法的库 name/path 之外的所有 DLLImport 参数。
如何从 DllImport 的第一个参数获取 DLL 路径?
我找到了解决问题的办法。所以 import
有一个 Module
属性,returns 是 System.Reflection.Metadata.ModuleReferenceHandle
的一个实例。用MetaDataReader.GetModuleReference(moduleReferenceHandle)
可以转换成System.Reflection.Metadata.ModuleReference
。反过来,ModuleReference
的实例有一个 Name
属性 即 returns StringHandle
并且也可以使用 MetaDataReader.GetString(stringHandle)
转换为字符串。这是DLL的name/path。
问题的完整解决方案:
string dllPath = mdReader.GetString(mdReader.GetModuleReference(import.Module).Name);
我正在编写一个实用程序来反汇编用 c# 编写的 dll/exe 文件,然后扫描此文件中的所有类型以查找是否存在从非托管 DLL 导入的方法。我需要获取每个导入方法的信息,包括从中导入该方法的 DLL 的 name/path,即 DllImport 属性的第一个参数的值。假设在dll/exe文件中有这样一个函数声明:
[DllImport("C:\TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void HelloWorld();
我是反射的新手,我正在尝试使用 PEReader
查看所有类型并搜索从 DLL 导入的函数。我从 System.Reflection.Metadata.MethodDefinition
调用 GetImport()
以确定当前 MethodDefinition 是否是导入方法。通过GetImport().Attributes
我希望得到所有的DllImport参数,包括这个DLL的路径,但是这样并没有给出想要的结果:
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();
}
}
}
}
也就是说,GetMethod().Attributes
returns 除了从中导入方法的库 name/path 之外的所有 DLLImport 参数。
如何从 DllImport 的第一个参数获取 DLL 路径?
我找到了解决问题的办法。所以 import
有一个 Module
属性,returns 是 System.Reflection.Metadata.ModuleReferenceHandle
的一个实例。用MetaDataReader.GetModuleReference(moduleReferenceHandle)
可以转换成System.Reflection.Metadata.ModuleReference
。反过来,ModuleReference
的实例有一个 Name
属性 即 returns StringHandle
并且也可以使用 MetaDataReader.GetString(stringHandle)
转换为字符串。这是DLL的name/path。
问题的完整解决方案:
string dllPath = mdReader.GetString(mdReader.GetModuleReference(import.Module).Name);