windows kernel pool

本文介绍了Windows内核中的KernelPool概念,包括Non-PagedPool、PagedPool和SessionPools等不同类型的内存池及其管理机制。详细解释了这些内存池如何被定义、使用及维护,并概述了它们的数据结构和操作流程。

kernel pool 基础

kernel pools 被分为 Non-Paged Pools, Paged Pools, Session Pools, etc. 被定义在POOL_TYPE 中

Non-Paged Pool

  • 不可分页的系统内存
  • 保证在任何时候都驻留在物理内存中
  • pools 的数量储存于 nt!ExpNumberOfNonPagedPools
  • 在单处理器系统中,nt!PoolVector 数组的第一个节点指向 non-paged pool 描述符
kd> dt nt!_POOL_DESCRIPTOR poi(nt!PoolVector)
   +0x000 PoolType         : 0 ( NonPagedPool )
   +0x004 PagedLock        : _KGUARDED_MUTEX
   +0x004 NonPagedLock     : 0
   +0x040 RunningAllocs    : 0n769209
   +0x044 RunningDeAllocs  : 0n679297
   +0x048 TotalBigPages    : 0n2518
   +0x04c ThreadsProcessingDeferrals : 0n0
   +0x050 TotalBytes       : 0x12a3618
   +0x080 PoolIndex        : 0
   +0x0c0 TotalPages       : 0n3184
   +0x100 PendingFrees     : 0x866582c0  -> 0x8688cb40 Void
   +0x104 PendingFreeDepth : 0n14
   +0x140 ListHeads        : [512] _LIST_ENTRY [ 0x8414cfc0 - 0x8414cfc0 ]
  • 在多处理器中,每个节点又它自己的 non-paed pool 秒素符, 指针保存在 nt!ExpNunPagedPoolDescriptor 数组中

Paged Pool

  • 分页系统内存
  • 在IRQL < DPC/Dispatch level 时才可以被访问
  • pools 的数量保存于 nt!ExpNumberOfPagedPools
  • 在单处理器系统中,有4 pages pool 描述符, 从1-4 在 nt!ExpPagedPoolDescriptor
  • 在多处理器系统中,在每个节点有1个paged pool 描述符
  • 为原型池/整页分配定义了一个额外的paged pool 描述符, 下标0 的 nt!ExpPagedPoolDescriptor

Session Paged Pool

  • 会话空间的可分页系统内存, 每个登录用户都是唯一的
  • 初始化在 nt!MilnitializeSessionPool
  • 在Vista, pool 描述符保存在 nt!ExpSessionPoolDescriptor(session space)
  • 在win7, 使用从当前线程指向池描述符的指针,
    KTHREAD->Process->Session.PagedPool
  • Non-paged session 分配使用全局 non-paged pools

每个kernel pool 由 POOL_DESCRIPTOR 结构定义,

-可以用于追踪 分配/释放的数量,使用中的pages ,etc,

  • 维持free pool chunks 列表

paged 和 non-paged pool 的初始描述符在nt!PoolVector数组中定义

  • 每个索引都指向一个或多个描述符的数组

win7 x86

kd> dt nt!_POOL_DESCRIPTOR
   +0x000 PoolType         : _POOL_TYPE
   +0x004 PagedLock        : _KGUARDED_MUTEX
   +0x004 NonPagedLock     : Uint4B
   +0x040 RunningAllocs    : Int4B
   +0x044 RunningDeAllocs  : Int4B
   +0x048 TotalBigPages    : Int4B
   +0x04c ThreadsProcessingDeferrals : Int4B
   +0x050 TotalBytes       : Uint4B
   +0x080 PoolIndex        : Uint4B
   +0x0c0 TotalPages       : Int4B
   +0x100 PendingFrees     : Ptr32 Ptr32 Void
   +0x104 PendingFreeDepth : Int4B
   +0x140 ListHeads        : [512] _LIST_ENTRY

每个pool chunk 有8字节的pool header,空闲的chunks 根据block size 放到ListHeads 中
1405424-20180530175551265-245605016.png

x86

kd> dt nt!_POOL_HEADER
   +0x000 PreviousSize     : Pos 0, 9 Bits
   +0x000 PoolIndex        : Pos 9, 7 Bits
   +0x002 BlockSize        : Pos 0, 9 Bits
   +0x002 PoolType         : Pos 9, 7 Bits
   +0x000 Ulong1           : Uint4B
   +0x004 PoolTag          : Uint4B
   +0x004 AllocatorBackTraceIndex : Uint2B
   +0x006 PoolTagHash      : Uint2B

PreviousSize: 上一个cunk 的blocksize
PoolIndex: 在pool 描述符中的索引
BlockSize: (NumberOfBytes + 0xF) >> 3
PoolType: Free = 0, Allocated = (PoolType|2) PoolTag;4

x64
BlockSize: (NumberOfBytes + 0x1F) >> 4 (256 ListHeads entries due to 16 byte block size)
ProcessBilled: 指向为池分配收取的过程对象的指针(用于配额管理)

释放

当pool chunk 被释放加入到ListHeads 中,头部将又LIST_ENTRY 结构

kd> dt nt!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY
   +0x004 Blink            : Ptr32 _LIST_ENTRY

1405424-20180530181931028-743557495.png

Lookaside Lists

  • 内核使用lookaside lists 来 申请/释放 小的pool chunks
  • 独立的每处理器lookaside列表为可分页和不可分页的分配
  • 在KPRCB(Processor Control Block) 中定义
  • 最大blocksize 为0x20 ( 256 bytes)
  • 单向

1405424-20180530182712835-1209442575.png

Large Pool Allocations

  • 分配超过0xff0 (4080) bytes
  • 由nt!ExpAllocateBigPool 处理
  • 每个处理器又4 个单向lookaside lists for big pool allocations
  • 1 paged 分配一个页面
  • 3 non-paged 分配页面计数为1,2,3
  • 如果不能分配lookaside list, 使用bitmap 来获取请求的pool pages
  • 在位图中搜索包含所请求数量的未使用页面的第一个索引
  • bitmap 使用它自己的memory 来定义主要的pool type
  • bits 数组位于pool 内存范围的开始

分配算法

  • Lookaside list
  • ListHeads List
  • Pool page allocator

1405424-20180530185410939-1745210342.png

释放

ExFreePoolWithTag
相邻的free chunk 可能会被会被合并

1405424-20180530190018766-1018733605.png

利用

https://www.blackhat.com/docs/us-14/materials/us-14-Tarakanov-Data-Only-Pwning-Microsoft-Windows-Kernel-Exploitation-Of-Kernel-Pool-Overflows-On-Microsoft-Windows-8.1.pdf

参考

http://www.nosuchcon.org/talks/2013/D3_02_Nikita_Exploiting_Hardcore_Pool_Corruptions_in_Microsoft_Windows_Kernel.pdf
https://infiltratecon.com/archives/kernelpool_infiltrate2011.pdf
https://www.cnblogs.com/flycat-2016/p/5449738.html

转载于:https://www.cnblogs.com/yizhanlvcha/p/9105947.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值