Windows 10 x86/wow64用户态堆管理深度解析

本文深入分析了Windows 10 x86/wow64环境下的用户态堆管理机制,包括后端分配器行为、LFH激活条件、堆布局操控技术及精确堆喷洒方法,通过实际测试验证了与Windows 7的异同。

Windows 10 x86/wow64用户态堆

引言

近期收到多起紧急求助,发现用户计算机被强制升级至Windows 10。随着市场占有率提升,Windows 10已成为值得深入研究的操作系统版本。本文记录了32位进程在Windows 10用户态堆管理器的行为特征,重点分析其与Windows 7的异同,并探讨如何通过堆操作提高行为可预测性。

核心研究问题:

  • 后端分配器的行为特征
  • 激活LFH(低碎片堆)的条件
  • Win7与Win10的LFH行为差异
  • 创建特定堆布局的技术方案
  • 实现可靠精确堆喷洒的方法

测试环境

  • Windows 10 Enterprise x64(VirtualBox虚拟机)
  • Visual Studio Express 2015
  • WinDBG for Windows 10
  • 符号服务器配置:srv*c:\symbols*http://msdl.microsoft.com/download/symbols

测试代码库:https://github.com/corelan/win10_heap

堆结构分析

Windows 10堆基址受ASLR影响,头部包含以下关键字段(通过WinDBG的dt _HEAP命令查看):

  • EncodeFlagMask(0x4c)和Encoding(0x50):堆块头编码密钥
  • VirtualMemoryThreshold(0x5c):值为0xfe00(0x7F000字节),超过此值的分配将触发VirtualAllocdBlocks
  • FrontEndHeapType(0xd6):值为0x2表示使用LFH前端分配器

LFH堆头结构(dt _LFH_HEAP)包含桶管理、子段分配等信息。与Win7不同,Win10的LFH堆头通常位于首段之外。

后端分配器(BEA)行为

BEA_Alloc1测试

分配两个0x300字节块时,从段尾空闲块分割获得连续内存空间:

1
2
3
01561438 0061 0201 [00] 01561440 00300 - (busy)
01561740 0061 0061 [00] 01561748 00300 - (busy) 
01561a48 00b3 0061 [00] 01561a50 00590 - (free)

BEA_Alloc2测试

分配10个0x300字节块后释放最后一个,该块与相邻空闲空间合并为0x12c8字节大块。后续0x100字节分配优先复用精确匹配的空闲块(009b2b08),其次使用较大空闲块(009bc338)。

BEA_Alloc3测试

通过包围策略控制堆布局:

  1. 分配0x100字节围栏块
  2. 分配填充’A’的0x58字节目标块
  3. 分配另一个0x100字节围栏块 释放目标块后,新0x58字节分配成功复用原地址(内容变为’B’)。

BEA_Alloc4测试

尝试通过不同尺寸块覆盖目标内存:

  • 使用0x80字节块覆盖0x58字节块的前4双字
  • 需要精确计算偏移量(实际测试存在8字节偏差)
  • 证明通过尺寸差异实现内存控制的可行性

前端分配器(LFH)行为

LFH激活条件测试

  • 标准触发:连续18次同尺寸分配后激活LFH(第18次分配显示LFH;busy标志)
  • 干扰测试:插入不同尺寸分配/释放操作不影响18次阈值
  • 同桶释放:释放同尺寸块不影响激活计数

LFH分配特性

  • 最大尺寸:仍限制为0x4000字节
  • LIFO行为:不再严格遵循后进先出,回收时间在0-50次分配间波动
  • 地址随机化:同子段内块不再连续排列

LFH回收测试(LFH_TakeBack2)

通过释放整个子段的所有块,可以实现跨桶尺寸的内存复用:

  • 原0x58字节块被释放
  • 分配0x88字节块成功覆盖原内存区域
  • 验证了子段级回收的可行性

大块分配与堆喷洒

VirtualAllocdBlocks分配

分配超过0x7F000字节的块会触发独立虚拟内存分配:

1
00c48018 10000 0004 [00] 00c48020 7ffb0 - (busy VirtualAlloc)

与Win7相比,分配间隔更大且不可预测,降低了堆喷洒可靠性。

精确堆喷洒技术

关键避免LFH和VirtualAllocdBlocks,使用对齐尺寸(如0x1fff8字节)在普通段内实现连续分配:

  • 前几个分配可能未对齐
  • 新段首分配实现页对齐(地址结尾为0048)
  • 通过每0x1000字节重复结构(垃圾数据+ROP+shellcode)实现地址无关性

测试成功在0x0c0c0c0c地址放置标记值:

1
0c0c0c0c  24 24 24 24 20 20 20 20-20 20 20 20 20 20 20 20  $$$$            

结论

Windows 10堆管理在保持基础架构的同时引入重要变化:

  1. LFH激活阈值保持18次但分配随机性增强
  2. 后端分配器行为基本一致,可通过包围策略控制布局
  3. 大块分配间距增大,需要调整堆喷洒策略
  4. 精确堆喷洒仍可通过段内对齐分配实现

建议在实际利用前进行针对性测试,并考虑多线程环境中的噪声影响。通过预分配大块再释放的策略可以隔离堆喷洒区域。

免责声明:本文仅用于安全研究目的,请勿用于非法用途。

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