进程和诊断工具学习笔记(8.29):ListDLLs——一眼看清进程里加载了哪些 DLL,谁在偷偷注入

进程和诊断工具学习笔记(8.29):ListDLLs------一眼看清进程里加载了哪些 DLL,谁在偷偷注入

  • [进程和诊断工具学习笔记(8.29):ListDLLs------一眼看清进程里加载了哪些 DLL,谁在偷偷注入](#进程和诊断工具学习笔记(8.29):ListDLLs——一眼看清进程里加载了哪些 DLL,谁在偷偷注入)
    • [1. ListDLLs 是什么?](#1. ListDLLs 是什么?)
    • [2. 基本使用方法(命令直接抄)](#2. 基本使用方法(命令直接抄))
      • [2.1 列出指定进程加载的 DLL(按进程名)](#2.1 列出指定进程加载的 DLL(按进程名))
      • [2.2 指定 PID](#2.2 指定 PID)
      • [2.3 列出所有进程](#2.3 列出所有进程)
      • [2.4 只看加载了某个可疑模块的进程(非常好用)](#2.4 只看加载了某个可疑模块的进程(非常好用))
    • [3. 输出怎么看?哪些字段是真正有价值的?](#3. 输出怎么看?哪些字段是真正有价值的?)
      • [3.1 Path(路径)](#3.1 Path(路径))
      • [3.2 Base Address / Size](#3.2 Base Address / Size)
      • [3.3 进程名 + PID](#3.3 进程名 + PID)
    • [4. 典型实战场景](#4. 典型实战场景)
      • [场景 1:排查"劫持/注入"行为](#场景 1:排查“劫持/注入”行为)
      • [场景 2:定位错误版本 DLL / 旧库残留](#场景 2:定位错误版本 DLL / 旧库残留)
      • [场景 3:无法删除 / 无法重命名某个 DLL](#场景 3:无法删除 / 无法重命名某个 DLL)
      • [场景 4:安全审计 / 反外挂 / 反注入](#场景 4:安全审计 / 反外挂 / 反注入)
    • [5. ListDLLs vs Process Explorer vs Handle:我该用谁?](#5. ListDLLs vs Process Explorer vs Handle:我该用谁?)
    • [6. 现场操作小抄(可以直接塞进你的应急手册)](#6. 现场操作小抄(可以直接塞进你的应急手册))
    • [7. 小结 & 下一步](#7. 小结 & 下一步)

进程和诊断工具学习笔记(8.29):ListDLLs------一眼看清进程里加载了哪些 DLL,谁在偷偷注入

这一篇我们进入第 8 章后半段的另一个特别有用的排障/取证工具:ListDLLs(Sysinternals 家族成员之一)。

如果你想回答下面这些问题,它基本就是标准答案:

  • "这个进程到底加载了哪些 DLL?"
  • "有没有被可疑模块注入?"
  • "为什么同一台机器上的两台业务服结果不一样?是不是有人用了错版本的 DLL?"
  • "为什么删除不了某个 DLL 文件?是不是还有进程在占用它?"
  • "升级后还是调用旧版本库?到底谁还在用旧 DLL?"

ListDLLs 很轻、很直接、不需要内核调试技能,但在安全分析、兼容性故障定位、运维应急时,它的价值极高。

本篇内容包含:

  1. ListDLLs 是什么
  2. 怎么运行 & 最常用命令
  3. 输出怎么看(哪些字段值得盯)
  4. 典型排障/取证场景
  5. 和其他工具(Process Explorer / Handle)怎么配合

1. ListDLLs 是什么?

ListDLLs 是 Sysinternals 出的命令行工具,用来列出某个进程当前已经加载进内存的全部模块(DLL / 驱动型模块 / 插件式扩展等)。

更通俗地讲:

它可以瞬间告诉你,"这个进程的地址空间里现在塞了哪些代码库,每个库具体来自哪个路径、哪个版本、什么时候被加载的"。

为什么这很关键?因为:

  • Windows 进程并不是只运行一个 EXE。
    它会 LoadLibrary() 一堆 DLL:系统 API、运行库、第三方 SDK、浏览器控件、杀毒注入模块、Hook 库......
  • 恶意代码注入往往就是"把我自己的 DLL 塞进别人的进程",然后借宿在你这个进程里跑。ListDLLs 能把这种"住进来的人"翻出来。
  • 很多诡异兼容性 Bug 是"用错了 DLL 版本",尤其是同名 DLL 被其他目录覆盖 / Shadow Copy / 旧 COM 组件/野生插件残留。一旦你把加载路径拉出来,真凶往往就很明显了。

一句话:ListDLLs 是你用来回答『这个进程里都加载了谁』的放大镜。


2. 基本使用方法(命令直接抄)

2.1 列出指定进程加载的 DLL(按进程名)

cmd 复制代码
listdlls.exe notepad.exe

会显示所有名为 notepad.exe 的进程及其模块。

2.2 指定 PID

cmd 复制代码
listdlls.exe -p 2336

-p 后面接进程 ID(PID)。PID 通常可以通过任务管理器、tasklistpslist、Process Explorer、Procmon 过滤栏等方式获取。

2.3 列出所有进程

cmd 复制代码
listdlls.exe

不带参数直接跑,ListDLLs 会把全机上所有活跃进程都扫一遍,把每个进程的模块清单依次打印出来。

(在生产环境建议加重定向保存结果到文件,方便检索、diff)

cmd 复制代码
listdlls.exe > alldlls.txt

2.4 只看加载了某个可疑模块的进程(非常好用)

cmd 复制代码
listdlls.exe somehook.dll

这条不是"列出进程→看 DLL",而是颠倒过来:"给定某个 DLL 名,查是谁加载了它"。

用途:

  • 某个第三方组件占用了一个老版本 DLL,想知道到底是谁还在用。
  • 杀软/外挂模块注入了某个 Hook DLL,想知道被它"上身"的进程有哪些。
  • 某个 DLL 无法删除,系统说"正在被占用" → 直接搜这个 DLL 名,定位哪个进程占着它。

3. 输出怎么看?哪些字段是真正有价值的?

典型 ListDLLs 输出结构大致是这样的(示意):

text 复制代码
Process: notepad.exe PID: 2336
Base      Size      Path
0x7ff8... 0x1f000   C:\Windows\System32\kernel32.dll
0x7ff9... 0xa3000   C:\Windows\System32\USER32.dll
0x10000.. 0x25000   C:\Program Files\VendorX\OverlayHook.dll
...

核心关注点有三个:

3.1 Path(路径)

  • 这个 DLL 是从哪里被加载进来的?
  • 是官方系统目录(C:\Windows\System32)?
  • 是某个干净的签名版程序目录(C:\Program Files\VendorX\...)?
  • 还是来自某个诡异路径(临时目录、用户下载目录、可写共享目录)?

路径异常几乎就是安全隐患预警。

3.2 Base Address / Size

  • Base Address 是这个 DLL 映射到进程虚拟内存时的基址。
  • Size 是它的映射大小。

对一线运维来说,这两个字段通常不需要死盯,但对开发、逆向、应急响应人员,这是判断模块是否被重定位 / 是否有内存注入痕迹的线索。

例如,一些内存注入技术会将 DLL(甚至并非合法 PE 文件)手工映射到进程的私有内存区域,而不是标准 LoadLibrary() 路径。那种情况往往看起来就"不正常"(路径奇怪 / 签名缺失 / 大小可疑)。

3.3 进程名 + PID

非常重要,尤其是做证据留存时。

你要记下哪个 PID 对应哪个进程、在哪个时刻、加载了哪些 DLL。因为之后你可能要:

  • 交给开发:"你这个版本在 10:35 加载了两个同名不同路径的库,请解释为什么会发生 DLL Search Order Hijacking 风险。"
  • 交给安全:"RDP-Tcp 会话下的 explorer.exe 被注入了这两个奇怪模块,路径是用户临时目录,请核查是否是外挂/窃密模块。"

4. 典型实战场景

下面给几个 ListDLLs 最有价值的使用场景,基本都是现场超高频的真实需求。

场景 1:排查"劫持/注入"行为

症状:

  • 某台机器的浏览器/Office/游戏客户端/业务客户端经常崩溃、闪退、各种奇怪弹窗。

做法:

cmd 复制代码
listdlls.exe chrome.exe > chrome_dlls.txt

然后在输出里找:

  • 来自非系统目录的 Hook、Overlay、Inject、Monitor、Protection 之类的 DLL
  • 游戏辅助、输入法扩展、截屏水印、安全特辑之类厂商的模块

如果只在问题机上能看到某个 DLL,但在"干净对照机"上看不到,那你就抓到突破口了。

这就是**"DLL 差异取证"**,极其好用。


场景 2:定位错误版本 DLL / 旧库残留

很常见的一句话投诉:

"我们刚更新了 A 库的 v4.2,但应用还是在用旧版本 v4.1,所以新功能还是报错。"

ListDLLs 就是证据生成器。

  1. 在现场机器跑:

    cmd 复制代码
    listdlls.exe appservice.exe > after_upgrade.txt
  2. C:\Program Files\AppVendor\libA.dll 实际加载的版本是不是还在旧目录里,比如居然是:

    • C:\app_backup_old\libA.dll 被加载,而不是新目录
    • 或者从一个共享路径 / 临时目录加载

这类情况经常是:

  • PATH 顺序污染
  • DLL Search Order 被环境变量或目录遗留影响
  • 程序工作目录没变导致还在 LoadLibrary() 老路径

然后你可以非常具体地告诉研发/集成商:

"appservice.exe (PID 2336) 正在加载 C:\app_backup_old\libA.dll 而不是最新的 C:\Program Files\AppVendor\libA.dll。这台机器的搜索顺序被污染,导致调用了错误的实现版本。"

一句话比十张截图有用。


场景 3:无法删除 / 无法重命名某个 DLL

用户想替换某个 DLL,但资源管理器说"正在被使用,无法更改"。

你可以直接问系统:谁在占它?

cmd 复制代码
listdlls.exe target.dll

ListDLLs 会反查所有进程列表,并告诉你:

"是进程 X(PID 2336) 还在加载 target.dll"。

这比瞎猜靠谱多了。

接下来你可以:

  • 优雅停止那个进程/服务
  • 或在维护窗口里用 Handle.exe 去强制释放(高危,后面几篇我们会讲)

场景 4:安全审计 / 反外挂 / 反注入

在安全类场景里,ListDLLs 常被当做"轻量快扫"的第一步:

  • 把目标机常见高价值进程扫一遍(浏览器、shell、业务客户端、远程桌面 Session、敏感进程如 lsass.exe 不能随便附加调试,但可以观察其它用户进程)。
  • 找有没有加载陌生的监控 DLL、键盘记录 DLL、截屏 DLL、流量代理 DLL。

之后再决定是否需要:

  • Dump 内存
  • 用 Procmon 抓行为轨迹
  • 拉事件日志
  • 升级为应急响应

5. ListDLLs vs Process Explorer vs Handle:我该用谁?

这三个经常一起出现,我们区分一下职责:

ListDLLs

  • 输出结构化、可脚本化
  • 对单个进程详细列出 DLL + 路径
  • 支持"反查某 DLL 被谁加载了"
  • 适合集成进批处理/现场报告

Process Explorer

  • 图形界面版 + 实时刷新
  • 能直接在某个进程属性对话框里看"DLLs"分页,并且还能看到数字签名是否可信
  • 日常观测最舒服,但不方便批量保存差异对比

Handle

  • 针对的是"句柄",即进程对系统对象的打开引用
  • 不只是 DLL,它也能告诉你文件、注册表键、互斥量、命名管道等一切对象的占用情况
  • 能强制关闭句柄(非常危险但在救火时很关键)
  • 是调查"文件被锁""服务无法释放资源"的专用钳子

一句话总结:

  • 要知道谁加载了哪个 DLL → ListDLLs
  • 要知道哪个进程正占着哪个文件/互斥量 → Handle
  • 要图形化看进程内部细节+签名状态→ Process Explorer

6. 现场操作小抄(可以直接塞进你的应急手册)

下面是一套非常实用的"巡检模板",适合你在问题机上直接运行,之后把结果打包给研发/安全:

cmd 复制代码
:: 1. 记录当前时间 & 机器基本信息
echo === Snapshot %date% %time% === > evidence.txt
hostname >> evidence.txt
whoami >> evidence.txt
echo. >> evidence.txt

:: 2. 列出目标进程(例如 appservice.exe)的 DLL
listdlls.exe appservice.exe > dlls_appservice.txt

:: 3. 反查某个可疑模块是被谁加载的
listdlls.exe HookOverlay.dll > dlls_hookoverlay_usage.txt

:: 4. 合并快照元数据
type dlls_appservice.txt >> evidence.txt
echo. >> evidence.txt
echo --- HookOverlay usage --- >> evidence.txt
type dlls_hookoverlay_usage.txt >> evidence.txt

你交出去的 evidence.txt 里面就是:

  • 机器身份
  • 用户上下文
  • 哪个进程加载了哪些 DLL
  • 哪些进程加载了我们怀疑的 HookOverlay.dll

这个材料是能直接喂给开发、安全、第三方厂商的。


7. 小结 & 下一步

到这里你已经可以做到三件对日常运维/安全排障非常关键的事:

  1. 列清一个进程当前加载的所有模块(版本、路径一览无遗)。
  2. 识别不该出现的 DLL(排查注入、外挂、旧库残留)。
  3. 快速还原"为什么我删不掉这个 DLL"(因为某个进程还在用它)。

更重要的是:

你不需要现场装调试器,不需要休克系统,也不需要管理员之外的黑魔法。ListDLLs 是纯读型工具,非常适合一线排障和应急记录。


下一篇(8.30)我们会继续顺着第 8 章,把焦点从"谁加载了哪个 DLL"转向"谁还握着哪些句柄"。

也就是 Sysinternals 的另一个狠角:Handle.exe

它能告诉你:

  • 哪个进程正占着某个文件/注册表键/命名管道/同步对象
  • 甚至可以在救火场景下,强制把那个句柄断开

那就是从"看"问题,升级到"直接动手处理"问题了。

相关推荐
你的乔克叔叔2 小时前
四大组件-Activity
android
aqi002 小时前
FFmpeg开发笔记(九十二)基于Kotlin的开源Android推流器StreamPack
android·ffmpeg·kotlin·音视频·直播·流媒体
lkbhua莱克瓦242 小时前
集合进阶8——Stream流
java·开发语言·笔记·github·stream流·学习方法·集合
车载测试工程师2 小时前
CAPL学习-IP API函数-1
网络·学习·tcp/ip·capl·canoe·doip
爱学java的ptt2 小时前
jvm笔记
jvm·笔记
雾岛听蓝2 小时前
C++ 类和对象(一):从概念到实践,吃透类的核心基础
开发语言·c++·经验分享·笔记
一个平凡而乐于分享的小比特3 小时前
UCOSIII笔记(十四)时间戳
笔记·时间戳·ucosiii
YJlio4 小时前
ShareEnum 学习笔记(9.5):内网共享体检——开放共享、匿名访问与权限风险
大数据·笔记·学习
泽虞4 小时前
《STM32单片机开发》p7
笔记·stm32·单片机·嵌入式硬件