如何获取WPF进程中已加载的所有DLL?模块检测异常排查
问题:检测WPF项目中已加载的自定义DLL并验证签名
项目信息
- 项目文件夹路径:
F:\workspace\VantageAddin\aiscreenshotaddin\src\AIScreenshotAddin\bin\x64\Release\AIScreenshot - 文件夹内文件:
- app.exe
- 1.dll
- 2.dll
- 3.dll
问题描述
在WPF项目文件夹中,存在app.exe和多个自定义DLL文件(如1.dll、2.dll、3.dll),app.exe会加载其中部分DLL到进程空间。所有EXE和DLL均已添加Windows数字签名,需要检测已加载的DLL并验证其签名,只有所有已加载DLL签名有效时才继续执行主函数(目的是防止DLL被替换或注入未签名文件,因此仅检测已加载的DLL,而非文件夹内所有文件)。
使用以下代码获取已加载模块:
Process myProcess = Process.GetCurrentProcess(); foreach (ProcessModule module in myProcess.Modules) { Logger.Debug(ClassName, $", dll module, FileName: {module.FileName}, BaseAddress: {module.BaseAddress}, ModuleName: {module.ModuleName}"); File.AppendAllText("D:\\111.txt", $"dll module, FileName: {module.FileName}, BaseAddress: {module.BaseAddress}, ModuleName: {module.ModuleName}"); File.AppendAllText("D:\\111.txt", Environment.NewLine); }
但输出结果中仅显示app.exe来自项目文件夹,自定义的1.dll、2.dll等已加载的DLL未被检测到。
输出结果示例
dll module, FileName: F:\workspace\VantageAddin\aiscreenshotaddin\src\AIScreenshotAddin\bin\x64\Release\AIScreenshot\app.exe, BaseAddress: 1790275420160, ModuleName: app.exe dll module, FileName: C:\windows\SYSTEM32\ntdll.dll, BaseAddress: 140723926794240, ModuleName: ntdll.dll dll module, FileName: C:\windows\SYSTEM32\MSCOREE.DLL, BaseAddress: 140723452182528, ModuleName: MSCOREE.DLL ...(其余系统模块省略)
补充说明
需要验证的是Windows文件属性中的数字签名(包含签名者、时间戳等信息,非.NET强名称签名)。
原因分析
- 模块类型差异:
Process.Modules仅返回由Windows原生加载器加载的模块(如系统DLL、EXE),而WPF项目中的自定义DLL是.NET托管程序集,由CLR(公共语言运行时)负责加载,这类模块不会出现在Process.Modules的结果中。 - 加载时机过早:如果检测代码执行时,自定义DLL还未被实际触发加载(比如延迟加载的程序集尚未被调用),也会导致无法检测到。
解决方案
1. 获取已加载的托管程序集
使用AppDomain.CurrentDomain.GetAssemblies()获取当前应用域中所有已加载的.NET托管程序集,示例代码:
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { string filePath = assembly.Location; if (!string.IsNullOrEmpty(filePath) && filePath.StartsWith(@"F:\workspace\VantageAddin\aiscreenshotaddin\src\AIScreenshotAddin\bin\x64\Release\AIScreenshot")) { Console.WriteLine($"已加载自定义程序集:{filePath}"); // 调用签名验证方法 if (!IsFileSigned(filePath)) { // 签名无效,终止程序或处理异常 Environment.Exit(1); } } } catch (NotSupportedException) { // 跳过动态生成的无文件路径的程序集 continue; } }
2. 验证Windows数字签名
使用X509Certificate2相关API验证文件的数字签名有效性,示例方法:
using System.Security.Cryptography.X509Certificates; public static bool IsFileSigned(string filePath) { try { // 从签名文件创建证书 using (X509Certificate2 cert = X509Certificate2.CreateFromSignedFile(filePath)) { // 构建证书链并验证有效性 using (X509Chain chain = new X509Chain()) { // 根据需求调整吊销检查策略,这里暂时关闭吊销检查 chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; // 验证证书链是否有效 return chain.Build(cert); } } } catch { // 文件无签名或签名无效时抛出异常,返回false return false; } }
3. 确保程序集已加载
如果部分程序集是延迟加载的,需要在执行检测前触发相关代码逻辑,确保目标DLL被CLR加载。也可以通过Assembly.Load显式加载必要的程序集后再进行检测。
内容的提问来源于stack exchange,提问作者Tom Xue
相关产品推荐
相关产品推荐

