ListDLLs Handle 学习笔记(8.11):谁注入了 DLL?谁占着文件不放?一篇教你全搞定
ListDLLs & Handle 学习笔记(8.11):谁注入了 DLL?谁占着文件不放?一篇教你全搞定
- ListDLLs & Handle 学习笔记(8.11):谁注入了 DLL?谁占着文件不放?一篇教你全搞定
- 1. DLL、句柄,这俩为什么这么关键?
- DLL:模块注入的真相
- 句柄:资源被占用的真相
- 2. ListDLLs:快速枚举进程加载的 DLL
- 基本能力
- 常见用法示例
- 1)列出某个进程加载的 DLL
- 2)查某个 DLL 被谁加载了
- 3)导出信息用于比对
- 3. Handle:谁在锁文件?谁阻止你删/弹/改?
- 它主要做三件大事:
- 3.1 基本体检式用法:直接列句柄
- 3.2 经典诊断:哪个进程锁住了某个文件?
- 3.3 暴力解决方案:关闭句柄
- 4. ListDLLs vs Handle:什么时候用谁?
- 5. 典型实战剧本(你可以直接照抄)
- 剧本 A:客户机器总弹广告。怀疑浏览器被注入插件
- 剧本 B:Windows 服务器上某个 .log 无法轮转,影响磁盘,业务喊救命
- 剧本 C:怀疑内核级 Rootkit 或奇怪驱动
- 6. 风险 & 注意事项
- 7. 总结
ListDLLs & Handle 学习笔记(8.11):谁注入了 DLL?谁占着文件不放?一篇教你全搞定
适用读者:
- 运维 / 桌面支持:客户说“删不掉,说文件正被占用”,你总不能一直说“重启一下”。
- 安全 / 取证:怀疑有恶意 DLL 注入、内存驻留模块、幽灵驱动在搞事情。
- 开发 / 测试:想确认目标进程到底加载了哪些模块、有没有把测试版 DLL 误带进生产。
- 游戏 / 反外挂 / 反Hook:想知道谁把奇怪的 DLL 注入到我们进程里。
这一篇我们把 Sysinternals 里两个常用但经常被忽略的狠角色拉上台:
- ListDLLs:列出进程加载的 DLL、模块路径、内存基址等
- Handle:枚举系统中所有打开的句柄(文件句柄、注册表句柄、同步对象、Section 对象等),并支持按目标名搜索,甚至强制关闭句柄
说人话:
- ListDLLs → “这个进程吃了哪些动态库?”
- Handle → “是谁卡着这个资源不放?”
1. DLL、句柄,这俩为什么这么关键?
DLL:模块注入的真相
任何一个用户态进程都不是“它自己一个 EXE 在跑”——它通常还会加载几十上百个 DLL:系统库(如 kernel32.dll)、第三方库(如显卡驱动注入的 overlay)、安全/杀软的 hook DLL、甚至是恶意软件植入的假冒模块。
很多行为劫持、键盘记录、API hook 都是通过“把我这段 DLL 注入到你的进程里”来完成的。
→ 如果你能看到“谁被塞了什么 DLL”,你就能定位一大批可疑行为。
这正是 ListDLLs 做的第一件事。
句柄:资源被占用的真相
Windows 里一切资源几乎都“包成了句柄”(Handle):
- 一个打开的文件 = 一个句柄
- 正在占用的 COM 端口 = 一个句柄
- 某个仍在持有的服务管道、注册表键、同步互斥体,全是句柄
当你遇到这些经典抱怨:
- “这个 .log 删不了,说正在被占用”
- “这个 U 盘弹不出去”
- “这个驱动程序卸载不了,说目标正在使用中”
问题往往是:哪个进程还在握着这个资源对应的句柄?
Handle 工具就能告诉你——并且还能(在你足够清楚后果时)强制掰开它的手指。
2. ListDLLs:快速枚举进程加载的 DLL
基本能力
- 列出指定进程(或系统中所有进程)所加载的 DLL / 映射模块
- 显示模块的内存基址、大小、路径
- 支持过滤某个特定 DLL,看它被注入到了哪些进程里
这种信息能直接用于:
- 查内存劫持(“怎么我的浏览器里有个奇怪的 overlayhook.dll?”)
- 双开/外挂检测
- 兼容性排查(“客户机器上到底加载的是我们发布的 release.dll 还是他们自己魔改的测试 DLL?”)
常见用法示例
1)列出某个进程加载的 DLL
listdlls notepad.exe
含义:枚举 notepad.exe 进程中所有已加载模块。
也可以用 PID(更精确):
listdlls -p 4321
输出里通常会包含:
- 模块名
- 基址 (Base)
- 大小 (Size)
- 模块完整路径(非常关键,用来判断是否被劫持到奇怪目录)
2)查某个 DLL 被谁加载了
listdlls yourhook.dll
含义:告诉你“哪些进程加载了名为 yourhook.dll 的模块”。
这个用法在安全分析场景非常炸裂,比如你怀疑有键鼠劫持 DLL、广告注入 DLL、甚至外挂模块 —— 直接反查所有进程谁吃了它。
3)导出信息用于比对
运维/排障时可以把输出重定向到文件留档:
listdlls chrome.exe > chrome_modules.txt
之后可和“健康机器”的对比结果做 diff,就能肉眼看出异常模块。
3. Handle:谁在锁文件?谁阻止你删/弹/改?
Handle 是 Sysinternals 里最常实用主义的武器之一。
它主要做三件大事:
-
枚举全系统的句柄
- 哪个进程持有哪些句柄(文件句柄、注册表句柄、Section、Mutant、Pipe…)
-
按关键字搜索
- “给我查所有句柄里包含
report.xlsx的那一个,告诉我是哪个进程占着” - 典型用于“删不掉/改不了/弹不出”的排障
- “给我查所有句柄里包含
-
可选地关闭句柄
- 是的,暴力手段
- 这就像用手把某进程从文件上掰开
- 但注意:可能导致进程崩溃、数据损坏,必须谨慎
3.1 基本体检式用法:直接列句柄
handle
不带参数直接执行 = 列出全系统句柄(会很多)。
输出字段通常包含:
- PID
- 进程名
- 句柄值
- 句柄类型(File、Key、Mutant、Section…)
- 目标路径(如文件全路径、注册表键路径等)
这个列表平时太大,所以我们几乎总是结合搜索。
3.2 经典诊断:哪个进程锁住了某个文件?
比如你删不掉 D:\logs\app.log,系统说“正在被使用”。
直接搜:
handle app.log
or 更精确:
handle "D:\logs\app.log"
输出大概会长这样(示例结构):
notepad.exe pid: 4820 38C: File (RW-) D:\logs\app.log
翻译一下:
- 进程名
notepad.exe(PID 4820)还在占用app.log - 句柄号是
38C
所以你就知道:是谁锁了它。这比“重启电脑再试”高到不知道哪里去了。
同理,这个技巧可以用在:
- 网络驱动器无法弹出
- U 盘“此设备正在使用中”
- 注册表项无法删除(是哪个安全代理还占着)
- 某软件说“请关闭所有 Office 应用后继续安装”,但你根本没开 Word
3.3 暴力解决方案:关闭句柄
警告先说前面:
强行关别人的句柄可能会让那个进程直接炸死,甚至蓝屏(尤其是系统/驱动关键句柄)。
只有在你确认目标进程可以被终止、或数据不再重要的情况下用它。
步骤是两步式:
第一步,定位句柄(获取 PID 和句柄值):
handle "D:\logs\app.log"
假设输出告诉你:
是 notepad.exe PID 4820,句柄号 38C
第二步,执行关闭(需要管理员):
handle -p 4820 -c 38C
-p指定目标进程的 PID-c指定要关闭的句柄值
Handle 会询问你是否确认关闭,除非你还加了 /y 等自动确认参数(不同版本语法有细微差别,核心思想一致:指定 PID + 句柄值 → 关闭)。
什么时候会这么用?
- 发布/升级脚本里批量替换日志文件、DLL 文件,而老版本进程没正常释放资源
- 应急情况下被锁的驱动/日志/临时文件必须立刻释放
- 清理“幽灵占用”的共享文件句柄以解锁共享目录
再强调一遍:
关闭句柄 = 手术刀,不是日常保养。
4. ListDLLs vs Handle:什么时候用谁?
可以把这俩工具想成“进程做了什么”的两个观察角度。
| 需求场景 | 用哪个 |
|---|---|
| 我想知道这个进程里都加载了哪些 DLL? | ListDLLs |
| 我怀疑某个进程内被注入了恶意 DLL / hook DLL | ListDLLs |
| 我想知道是谁还在持有这个文件 / 注册表键 / 命名管道 | Handle |
| 我想直接把这个资源从进程手里抢回来 | Handle (带 -c) |
| 我怀疑是某个第三方插件导致崩溃 | 先用 ListDLLs 确认是否加载了这类插件,再结合 Dump/Procmon 等分析 |
| 我遇到“文件无法删除”/“设备正被使用” | Handle |
实际排障时,这两个工具经常和 Procmon、LiveKd 联动使用:
- Procmon:看“行为历史”(谁什么时候访问了什么)
- Handle:看“现在谁在占用它”
- LiveKd:看“内核底层现场是怎样的”
- ListDLLs:看“进程里到底混进了哪些模块”
这是完整的三维视角:时间线(Procmon)、现场占用(Handle)、进程注入面(ListDLLs)、内核现场(LiveKd)。
5. 典型实战剧本(你可以直接照抄)
剧本 A:客户机器总弹广告。怀疑浏览器被注入插件
-
远程上机 / 要求客户运行:
listdlls chrome.exe > chrome_dlls.txt -
你对比正常环境的 chrome_dlls.txt
- 如果看到陌生的 DLL,尤其是来自奇怪路径(比如用户临时目录、AppData 里形如随机字符串的路径),基本可以锁定它。
-
后续就可以结合
taskkill、启动项排查、注册表 Run 项排查,甚至配合安全团队封堵。
剧本 B:Windows 服务器上某个 .log 无法轮转,影响磁盘,业务喊救命
-
在服务器上执行:
handle "D:\prod\app\run.log" -
得到结果例如:
java.exe pid: 9124 2A0: File D:\prod\app\run.log -
如果你准备重启这个 Java 服务,先优雅 stop;
如果 stop 不掉、但磁盘要爆了,可以:handle -p 9124 -c 2A0然后立刻做日志切分和清理(⚠ 之后建议重启对应服务,恢复干净状态)
剧本 C:怀疑内核级 Rootkit 或奇怪驱动
- 先用 LiveKd 抓一个 dump / 或直接开交互调试(我们在上一篇详讲)
- 再用 ListDLLs / Handle 确认高权限进程里加载了哪些模块、还占了哪些对象
- 三者信息交叉起来,可以定位可疑驱动 or 用户态 Loader
6. 风险 & 注意事项
-
Handle 关闭句柄 = 破坏性手段
你是在强制把资源从进程嘴里扣出来。生产上请先走停服务/回收进程,只有在“已经坏了”“必须释放资源”时用它兜底。 -
ListDLLs 看到的模块路径非常敏感
这些路径能暴露三方插件、内网私有模块、甚至商业反作弊/反篡改组件。别随手把输出贴到公网工单或论坛。 -
管理员权限很关键
要想枚举别的进程的 DLL 或句柄,往往需要管理员(或者 SYSTEM)级访问权限。标准用户看到的信息是有限的。 -
杀软可能拦截
某些安全产品会把 Handle / ListDLLs 归类为“高权限诊断工具”,可能会弹框或阻止。企业环境要和安全团队打个招呼。
7. 总结
这篇的重点可以压成四句话背走👇
-
ListDLLs 解决“进程里现在都注入/加载了哪些 DLL 模块?”
- 定位异常插件、外挂、Hook、兼容性污染。
-
Handle 解决“谁锁着这个资源不让我动?”
- 快速找出无法删除/无法弹出/无法卸载的罪魁进程。
-
Handle 还能 —— 在你充分理解风险后 —— 强制关闭那个句柄,等于手动解锁资源。
-
它们和 Procmon、LiveKd、DebugView 形成了生产排障的“武器库四件套”:
- Procmon 看行为历史
- DebugView 听调试输出
- LiveKd 看内核现场
- ListDLLs / Handle 看模块注入 & 句柄占用
下一步我们会把这些工具和前面章节的 VMMap / DebugView / LiveKd 串起来,给出一套“现场 → 采证 → 复盘”的应急响应流程模板,让你在碰到线上的 CPU 飙高、资源锁死、劫持注入、疑似木马、服务卡死事件时,能跑一套标准动作,而不是手忙脚乱地猜。
