个人主页杨利杰YJlio❄️个人专栏《Sysinternals实战教程》 《Windows PowerShell 实战》 《WINDOWS教程》 《IOS教程》《微信助手》 《锤子助手》 《Python》 《Kali Linux》《那些年未解决的Windows疑难杂症》让复杂的事情更简单让重复的工作自动化进程和诊断工具学习笔记8.26ListDLLs——模块枚举、DLL劫持排查与版本冲突定位问题背景进程名正常不代表进程内部干净ListDLLs 是什么进程模块清单的即时证据典型场景什么时候应该第一时间打开 ListDLLs版本冲突定位健康机器和异常机器要对比看DLL 劫持排查真正危险的是路径Handle ListDLLs锁文件定位和模块体检要一起看客户现场取证先保存再分析再留档最佳实践别只看名字别只看一台机器常见误区ListDLLs 不是万能裁判总结ListDLLs 是进程模块层面的证据提取器问题背景进程名正常不代表进程内部干净在 Windows 排障里有一类问题非常容易误判进程名看起来正常路径也像是正规程序但它就是崩溃、卡死、弹窗、加载失败甚至出现异常网络行为。这个时候如果只看任务管理器里的进程名基本看不出真相。原因很简单Windows 进程运行时会加载大量 DLL。一个程序真正执行时不只是一个 EXE 在工作而是系统 DLL、应用 DLL、第三方插件、运行库、COM 组件、安全软件 Hook 模块甚至可疑注入模块一起进入进程地址空间。ListDLLs.exe 的价值就是把这个进程当前加载的模块清单拉出来让我们看到模块名、路径、基址、大小和版本信息。它解决的问题不是“这个进程叫什么”而是“这个进程体内到底装了什么”。这张图展示的是 ListDLLs 的核心定位围绕一个目标进程识别系统 DLL、应用 DLL、第三方插件和注入模块并重点关注路径、基址、大小和版本这些关键字段。从图中可以看出ListDLLs 不只是列一个 DLL 名单。真正有价值的是它能告诉我们模块从哪里加载、版本是否正确、路径是否异常、是否存在非预期插件或注入模块。对企业桌面支持和安全取证来说这些信息比“程序崩了”四个字有用得多。ListDLLs 是什么进程模块清单的即时证据ListDLLs.exe 是 Sysinternals 工具集中一个很轻量的命令行工具用来列出系统中指定进程当前加载的 DLL 模块。它不像 Procmon 那样记录行为过程也不像 Process Explorer 那样提供完整图形化界面但它在“模块证据”这个点上非常直接。它通常会输出模块名、完整路径、基址、模块大小有些版本或场景下还能看到版本资源信息。对排障人员来说最关键的是路径和版本。路径告诉我们模块来自哪里版本告诉我们它是不是预期版本。我的经验是看 ListDLLs 输出第一眼不要盯模块名先看路径。因为 DLL 劫持、错误加载、旧版本运行库冲突很多时候名字都很正常真正异常的是加载位置。常用命令很简单按进程名查看listdlls.exe notepad.exe如果同名进程很多建议先确定 PID再按 PID 查询listdlls.exe -p 4321如果要做现场留证务必重定向到文件listdlls.exe app.exe C:\Temp\app_dll_snapshot.txt推荐做法是凡是遇到“只有某台机器异常”“某个程序反复崩溃”“热更新失败”“怀疑 DLL 劫持”这类问题先抓一份 ListDLLs 快照再做判断。典型场景什么时候应该第一时间打开 ListDLLs第一类场景是单机异常。比如同一个客户端程序在大多数机器上运行正常只有某一台机器闪退、卡死或者功能异常。这类问题往往不是主程序本体坏了而是这台机器上多加载了某个旧插件、旧运行库、输入法 Hook、杀软模块或者第三方组件。第二类场景是安全取证。像explorer.exe、svchost.exe、lsass.exe、winlogon.exe这类进程如果加载了来自临时目录、用户目录、下载目录或未知路径的 DLL就需要高度警惕。第三类场景是热更新失败。某个 DLL 无法替换系统提示正在使用。Handle 可以告诉你谁占用了这个 DLLListDLLs 则可以进一步告诉你这个进程到底加载了哪个版本、从哪个目录加载。第四类场景是版本冲突。老业务系统经常携带旧运行库例如旧版 VC Runtime、MFC、MSXML 或自研公共 DLL。系统升级后某些机器加载路径不同就可能出现“别人正常只有我崩”的情况。不要把 ListDLLs 当成“安全工具才会用”的东西。它在桌面支持、软件兼容性、补丁发布和客户现场排障里同样非常实用。版本冲突定位健康机器和异常机器要对比看很多软件兼容性问题单看异常机器并不明显。因为输出里所有 DLL 名字都像是正常的路径也未必一眼看出问题。真正有效的方法是拿一台健康机器做对比。例如客户反馈某个客户端只在机器 B 上崩溃机器 A 正常。你可以分别导出两台机器的模块清单listdlls.exe app.exe C:\Temp\app_dlls_healthy.txt listdlls.exe app.exe C:\Temp\app_dlls_problem.txt然后比较模块名、版本和加载路径。重点看三类差异第一异常机器多加载了哪些模块第二同名 DLL 的版本是否不同第三同名 DLL 是否来自不同路径。这张图展示的是版本冲突定位思路左侧是健康环境右侧是异常环境中间通过差异对比识别版本不同和加载路径不同。从图中可以看出异常环境并不一定是“缺 DLL”更多时候是“加载了不该加载的那一份 DLL”。比如运行库版本低、dbghelp.dll 来自应用目录而不是系统目录都可能导致只有某台机器异常。版本冲突排查的核心不是找“有没有这个 DLL”而是确认“实际加载的是哪一份 DLL”。名字一样路径不同后果可能完全不同版本差几个小版本也可能引发兼容性事故。如果要在 PowerShell 里做一个粗略比对可以先用文本方式保存再用对比命令查看差异Compare-Object(Get-ContentC:\Temp\app_dlls_healthy.txt)(Get-ContentC:\Temp\app_dlls_problem.txt)这不是最精细的模块分析方式但在现场很实用。先把差异拉出来再人工判断哪些差异有意义。DLL 劫持排查真正危险的是路径DLL 劫持最容易迷惑人的地方在于模块名往往看起来并不奇怪。比如version.dll、dbghelp.dll、winhttp.dll、msvcp140.dll这类名字本身都可能是正常文件。问题不在名字而在它从哪里被加载。正常情况下系统 DLL 应该主要来自C:\Windows\System32或C:\Windows\SysWOW64。应用自己的 DLL 应该来自应用安装目录。企业安全插件应该来自明确的软件目录。如果系统进程或关键业务进程加载了来自 Temp、AppData、Downloads、桌面、公共目录或共享盘的 DLL就要提高风险等级。这张图展示的是 DLL 劫持排查的关键逻辑同名 DLL 可能一边来自系统目录一边来自用户可写目录。真正要看的是实际加载路径。从图中可以看出合法 DLL 和可疑 DLL 的名称可以一样但路径、签名和发布者信息完全不同。攻击者常见做法就是把同名 DLL 放在程序优先搜索路径或用户可写路径中让目标进程加载错误版本。判断 DLL 是否可疑可以抓住三个信号异常路径、未签名模块、同名 DLL 错位加载。这里不要偷懒只看文件名会漏掉很多问题。如果已经从 ListDLLs 看到可疑路径下一步建议配合 Sigcheck 做签名检查sigcheck.exe -m C:\Users\user\AppData\Local\Temp\version.dll推荐形成一个固定判断顺序先看路径再看签名再看版本再看是否出现在高权限进程里。如果一个未签名 DLL 出现在高权限进程中并且路径还在用户可写目录基本就不能当普通兼容性问题处理了。Handle ListDLLs锁文件定位和模块体检要一起看在热更新失败、DLL 无法替换、旧插件残留这类问题里Handle 和 ListDLLs 是非常好的组合。Handle 回答“谁锁住了这个 DLL”ListDLLs 回答“这个进程到底加载了哪些模块”。只用 Handle可能只能知道某个 PID 占用了bar.dll但不知道它是否还加载了旧版本插件、旧公共库或异常模块。只用 ListDLLs能看到模块清单却未必知道文件为什么无法替换。两个工具结合判断才完整。这张图展示的是 Handle ListDLLs 的组合排障流程先用 Handle 找到谁锁住了bar.dll再用 ListDLLs 体检该进程最后决定停服务、重启组件或替换 DLL。从图中可以看出热更新失败时不能只问“哪个文件被占用”还要追问“占用它的进程内部加载了什么”。如果 ListDLLs 发现旧插件仍然存在就说明问题不只是文件锁而可能是组件卸载不干净或服务未完整重启。一个比较稳的排查流程可以这样写handle.exe bar.dll listdlls.exe -p 4528 C:\Temp\GameServer_dlls.txt然后根据结果决定动作。如果是服务进程优先停服务或重启组件如果是普通桌面应用通知用户保存退出如果是生产服务要进入变更窗口不要直接强杀。是否DLL 无法替换或热更新失败Handle 查询谁占用 DLL确认进程名和 PIDListDLLs 导出该 PID 模块清单是否存在旧模块/异常路径/版本冲突停服务或重启组件检查其他文件锁或部署流程替换 DLL 并重新验证记录变更证据和模块快照Handle 是资源占用视角ListDLLs 是模块加载视角。两个视角合起来才能解释“为什么更新失败”。客户现场取证先保存再分析再留档真实客户现场经常不允许你安装调试器也不一定能抓 Dump更不一定能长时间远程。这个时候ListDLLs 的优势就很明显它不需要复杂部署只要能运行工具并导出文本就能拿到进程模块清单。现场指令要写得非常清楚不要让对方自由发挥。比如listdlls.exe app.exe C:\Temp\listdlls_app_20260521_143000.txt如果是崩溃或卡死问题最好让对方在“卡住当下”或“崩溃前可复现阶段”执行而不是重启后再跑。因为重启后模块状态可能已经变了。这张图展示的是现场取证的最佳实践客户端导出 ListDLLs 输出发送快照给工程师工程师再对比健康基线、关注差异项并做签名校验。从图中可以看出现场取证的核心不是“让客户发一堆截图”而是让模块清单进入工单和知识库。带时间戳保存、对比健康样本、关注路径、配合签名校验这四步比反复远程看界面更有效。ListDLLs 输出可能包含客户敏感路径、业务目录名、用户名和内部组件名称不要无差别转发。如果要发给供应商或外部支持建议先做必要脱敏只保留模块名、版本、关键路径结构和异常结论。最佳实践别只看名字别只看一台机器第一所有 ListDLLs 输出都建议保存为文件并带时间戳。控制台里看一眼很容易漏后续也没法复盘。第二一定要和健康样本对比。单机模块清单只能说明“它加载了什么”对比后才能看出“它比正常机器多了什么、少了什么、版本哪里不同”。第三路径优先级高于名称。名字像系统文件不代表它就是系统文件路径在用户可写目录就不能轻易放过。第四安全场景必须配合签名校验。未签名 DLL 出现在高权限进程里是值得升级处理的信号。第五输出要进入工单或知识库。比如“某版本水印插件导致 Word 崩溃”“某旧运行库导致客户端闪退”“某 DLL 从 AppData 加载导致风险”这些都是后续复用价值很高的知识。推荐沉淀一个固定模板问题现象、目标进程、采集时间、ListDLLs 输出文件、异常模块、路径判断、签名结果、处理动作、验证结果。常见误区ListDLLs 不是万能裁判第一个误区是看到第三方 DLL 就认为它有问题。企业终端中输入法、安全软件、DLP、水印工具、打印插件、浏览器扩展都可能注入或加载模块。是否异常要结合路径、签名、版本、白名单和故障现象判断。第二个误区是只看异常机器不看健康机器。没有对照样本很多差异没有意义也容易误判。第三个误区是把 ListDLLs 当成行为分析工具。它看到的是当前加载了什么不负责告诉你这个 DLL 做了什么。行为证据仍然需要 Procmon、事件日志、网络连接、Dump 或 EDR 日志来补足。第四个误区是忽略权限问题。系统关键进程可能需要管理员权限才能枚举模块。没有权限时输出不完整不要直接得出“没有异常模块”的结论。ListDLLs 给你的是模块清单不是最终定罪书。它的价值在于缩小范围、提取证据、指导下一步验证。总结ListDLLs 是进程模块层面的证据提取器ListDLLs.exe 的命令很简单但它背后的排障价值很大。它可以帮我们回答几个关键问题这个进程加载了哪些模块模块来自哪里版本是不是预期的有没有异常路径有没有旧插件残留有没有可能被 DLL 劫持在桌面支持中它适合定位单机崩溃、插件冲突和版本差异。在服务运维中它适合处理热更新失败和模块占用。在安全取证中它适合识别异常路径 DLL、未签名模块和同名 DLL 错位加载。Handle 看“谁占着资源”ListDLLs 看“进程加载了什么”。这两个工具配合起来就能把很多“看起来玄学”的 Windows 问题拆成可以验证的证据链。以后再遇到“只有这台机器崩”“DLL 替换不上”“怀疑进程被注入”“功能异常但进程名正常”这类问题不要只看进程名。先用 ListDLLs 看清进程体内到底装了什么模块。 返回顶部点击回到顶部