内核池安全解链技术解析

本文深入探讨Windows 7 RC引入的内核池安全解链机制,通过双向链表完整性校验有效防御池溢出漏洞利用,分析其安全价值、可靠性提升及性能影响,为内核级内存防护提供关键技术方案。

内核池安全解链机制

用户模式堆内存内置了多种防护措施以增加堆溢出漏洞利用难度。Windows 7 RC首次在发布版本中启用了内核池的完整性校验机制,这些检查此前仅存在于调试版本中用于驱动调试。

技术背景

随着影响Windows内核的安全公告比例从2007年的不足5%上升至2008年的10%以上(如MS07-017、MS08-001等池溢出漏洞),微软安全团队开始研究内核层缓解措施。内核池作为高性能动态内存管理器,分为两类:

  • 非分页池:常驻物理内存,可在任意IRQL级别访问
  • 分页池:支持页面交换,禁止在Dispatch级别及以上访问

内存分配策略根据请求块大小差异:

  • ≤256字节:使用单链表结构的Lookaside列表
  • 256-4080字节:采用双链表结构(8字节粒度)
  • 4080字节:直接分配整页

每个内存块包含8字节头部(记录块大小、前驱块类型等信息),空闲块额外包含LIST_ENTRY结构(含前后向指针)。

池溢出攻击原理

池溢出通常源于整数溢出等算术错误,攻击者通过操控空闲块合并时的解链操作实现任意写入:

1
2
3
4
5
6
7
BOOLEAN RemoveEntryList(IN PLIST_ENTRY Entry) {
   PLIST_ENTRY Blink = Entry->Blink; 
   PLIST_ENTRY Flink = Entry->Flink;
   Blink->Flink = Flink;  // 任意地址写入
   Flink->Blink = Blink;  // 二次写入
   return (Flink == Blink);
}

安全解链实现

通过验证双向链表完整性可提前检测内存破坏:

1
2
3
4
5
6
7
8
9
BOOLEAN SafeRemoveEntryList(IN PLIST_ENTRY Entry) {
   PLIST_ENTRY Blink = Entry->Blink;
   PLIST_ENTRY Flink = Entry->Flink;
   if (Flink->Blink != Entry || Blink->Flink != Entry) 
       KeBugCheckEx(...); // 触发蓝屏
   Blink->Flink = Flink;
   Flink->Blink = Blink;
   return (Flink == Blink);
}

技术优势

  1. 安全性:有效阻断常见池溢出利用技术,迫使攻击者开发针对性利用方案
  2. 可靠性:在首次检测到内存破坏时立即终止,避免后续不可预测的损坏
  3. 性能:仅增加8条指令且不引发额外分页操作,实测无性能损耗
  4. 兼容性:内存破坏始终被视为致命错误,不存在例外场景

该技术继承自用户模式堆(XP SP2引入),其防护价值已在Windows Vista的堆增强机制中得到验证。微软安全科学家Peter Beck指出:“安全解链使得池溢出漏洞的利用难度呈数量级提升”。

本文档"按原样"提供,不附带任何担保

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计