Windows进程内部结构:PEB与LDR双向链表解析(内存取证基础第二部分)

admin 2026-03-31 11:53:39 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档深入解析Windows进程内存取证基础,详细阐述PEB与LDR双向链表结构,涵盖InLoadOrder、InMemoryOrder及InInitializationOrder三个关键链表。通过内核调试实例演示手动遍历数据结构获取DLL信息的过程,解释了InInitializationOrder列表通常不含进程可执行文件的原因,为理解Volatility插件底层机制与检测DLL隐藏注入提供了关键理论与实战指导。 综合评分: 89 文章分类: 逆向分析,应急响应,恶意软件,安全工具


cover_image

Windows 进程内部结构:PEB 与 LDR 双向链表解析(内存取证基础 第二部分)

imp hash imp hash

securitainment

2026年3月26日 13:37 中国香港

| 原文链接 | 作者 | | — | — | | https://imphash.medium.com/windows-process-internals-a-few-concepts-to-know-before-jumping-on-memory-forensics-part-2-4f45022fb1f8 | imp hash |

ldrmodules是 Volatility 工具套件中广受信赖的插件之一,专门用于检测进程内存中 DLL 隐藏或注入等可疑活动。相信大多数使用 Volatility 做内存分析来检测恶意软件的安全人员,对 “ldrmodules” 这个插件都不会陌生。

今天我们要探讨的是内存中的进程数据结构——ldrmodules 和 dlllist 等插件正是从这些结构中提取数据。

如果你回顾本系列文章第一部分中的表 1(Volatility 插件与操作系统数据结构的映射关系),就会发现 ldrmodules 和 dlllist 等插件依赖 _EPROCESS 块中的进程环境块(PEB)结构来获取已加载 DLL 的列表。

_PEB 通过其结构中的 ldr字段,进一步指向另一个名为 _PEB_LDR_DATA 的数据结构。_PEB_LDR_DATA 结构中包含三个双向链表的指针,这些链表记录了该进程所加载的 DLL 信息。

简而言之,_PEB 指向三个不同的链表,它们分别记录着进程内存中已加载 DLL 的信息。请参考下图来了解这些结构之间是如何关联的。

ldrmodules 从以下 3 个链表中获取已加载 DLL 的信息。这 3 个链表的名称分别为:

  • InLoadOrderModuleList
  • InMemoryOrderModuleList
  • InInitializationOrderModuleList

这 3 个链表根据 DLL 的加载方式和在内存中的位置,分别追踪特定进程已加载的 DLL。

图 1. 各内存结构之间的逻辑连接关系

接下来,我们通过实时内核调试来逐一查看这些数据结构的实际样貌。

首先,枚举当前已加载的进程,并选择一个用于后续分析的目标进程。

确定了进程的偏移量之后,我们需要通过枚举 _EPROCESS 结构来找到 _PEB 的偏移量,因为 _EPROCESS 中包含指向 _PEB 的指针。下面我们来枚举 _EPROCESS 结构,并从中筛选出指向 _PEB 结构的指针。

dt nt!_eprocess ffffe0814bb4d080 -y peb

图 2. 获取指向 _PEB 的指针

我们得到了 _PEB 结构,其偏移量为 0x000000ea'83178000。现在,继续枚举 _PEB 结构以获取指向 _PEB_LDR_DATA 结构的指针——该结构包含三个双向链表,用于追踪进程内存中已加载的 DLL。如前文所述,_PEB 通过其 ldr 字段存储这一信息,ldr 字段指向的正是包含这 3 个双向链表的 _PEB_LDR_DATA 数据结构。

图 3. 获取指向 ldr(_PEB_LDR_DATA)的指针

现在来枚举 _PEB_LDR_DATA 结构。

图 4. 获取各模块链表的指针

可以看到前文讨论的三个双向链表的指针。每个双向链表通过指向内存中的 DLL 结构体(_LDR_DATA_TABLE_ENTRY),记录了进程内存中已加载 DLL 的信息。下面我们取 InLoadOrderModuleList 的 Flink 指针,看看它指向的是哪个 DLL。

图 5. 枚举 InLoadOrder 模块列表中的第一个条目

可以看到它指向的是 dwm.exe。请注意,我们当前查看的是 InLoadOrder列表,该列表按照 DLL 被加载到进程内存中的先后顺序来追踪它们。进程的可执行文件是进程加载时最先被载入的,因此它通常是列表中的第一个条目。

我们可以沿着链表的指针依次遍历整个列表。下面来实际操作一下。

图 6. 枚举完整的 InLoadOrder 模块列表

同样地,我们也可以遍历其他 2 个链表,但需要注意它们各自指向 _LDR_DATA_TABLE_ENTRY 结构体内部的不同偏移位置。我们需要将该偏移量计算在内,并从地址中减去相应偏移量,才能定位到结构体的起始位置,如上图所示。

下面以 InInitializationOrder为例,其指针地址为 0x000002c7'410d26c0,我们从该内存地址中减去偏移量后,再遍历整个链表。

图 7. 枚举 InInitializationOrder 模块列表

你可能已经注意到,InInitializationOrder列表中并不包含进程可执行文件(.exe)的条目,而该条目在另外两个列表中通常都存在。

原因在于,InInitializationOrder 是按照进程调用 DllMain 函数的顺序来追踪 DLL 的。由于进程可执行文件本身没有 DllMain 函数,且其加载方式与普通 DLL 不同,InInit 列表中不包含进程可执行文件的条目——这是系统的设计行为。因此,在 ldrmodules 输出中,.exe对应的 “InInit” 列显示为 “false” 属于正常现象。

本篇内容就到这里了!祝各位分析顺利!


免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:securitainment imp hash imp hash《Windows 进程内部结构:PEB 与 LDR 双向链表解析(内存取证基础 第二部分)》

这次被罗技搞很烦了。 网络安全文章

这次被罗技搞很烦了。

文章总结: 作者作为罗技二十余年的忠实用户,因不满品牌营销文案中嘲讽等等党的言论而感到被抛弃,遂决定抵制该品牌产品并不接受道歉。文章列举大量购买记录佐证忠诚度,
评论:0   参与:  0