HeapEntry解码过程

来源:互联网 发布:mac word 转pdf 不成功 编辑:程序博客网 时间:2024/04/18 14:08

在调试堆时对HeapEntry解码的过程,记录下来以便以后学习用到。
在Win7上调试堆时,会发现_HEAP 增加了两个标志,一个是EncodeFlagMask,另一个是Encoding,其中EncodeFlagMask标明了堆头部是否经过了编码,这个字段的初值为0x100000,由RtlpCreateHeapEncoding()函数设置。而Encoding是一个_HEAP_ENTRY结构体的指针。


举一个例子来说:


0:005>!heap -a 1

Index   Address  Name      Debugging options enabled

  1:   003d0000

    Segment at 003d0000 to 004d0000 (00100000 bytes committed)

    Segment at 02c70000 to 02d70000 (00020000 bytes committed)

    Flags:                00000002

    ForceFlags:           00000000

    Granularity:          8 bytes

    Segment Reserve:      00200000

    Segment Commit:       00002000

    DeCommit Block Thres: 00000800

    DeCommit Total Thres: 00002000

    Total Free Size:      00002433

    Max. Allocation Size: 7ffdefff

    Lock Variable at:     003d0138

    Next TagIndex:        0000

    Maximum TagIndex:     0000

    Tag Entries:          00000000

    PsuedoTag Entries:    00000000

    Virtual Alloc List:   003d00a0

    Uncommitted ranges:   003d0090

            02c90000: 000e0000  (917504 bytes)

    FreeList[ 00 ] at 003d00c4: 02c81fe8 . 004537a8 

        004537a0: 00108 . 00010 [100] - free

        004a7fc0: 00190 . 00010 [100] - free

        00453678: 00098 . 00010 [100] - free

        0044b0e8: 000c8 . 00010 [100] - free

        00418bd8: 00068 . 00010 [100] - free

        00413230: 00040 . 00010 [100] - free

        00403b48: 00040 . 00010 [100] - free

        0046f620: 00130 . 00018 [100] - free

        00440e50: 000f0 . 00018 [100] - free

        0044bb50: 001c8 . 00018 [100] - free

        0043dc10: 00140 . 00018 [120] - free

        0043ca78: 00128 . 00018 [100] - free

        00474be0: 000e8 . 00018 [100] - free

        00452358: 00070 . 00018 [100] - free

        0042ebc8: 00090 . 00018 [100] - free

        004178c0: 00070 . 00018 [100] - free

        00414e40: 00040 . 00018 [100] - free

        004323e0: 00088 . 00020 [120] - free

        0041a608: 00040 . 00020 [100] - free

        004158a8: 00070 . 00020 [100] - free

        0040ff50: 00128 . 00020 [100] - free

        004a2280: 00160 . 00028 [100] - free

        00415ef0: 00068 . 00028 [100] - free

        0047b748: 00678 . 00030 [100] - free


可以看到-a列出了所有的Heap Entries,这里只截取了其中的一部分,接下来以第一个Entry为例进行说明,先看下_heap_entry的结构:

ntdll!_HEAP_ENTRY

   +0x000 Size             : Uint2B

   +0x002 Flags            : UChar

   +0x003 SmallTagIndex    : UChar

   +0x000 SubSegmentCode   : Ptr32 Void

   +0x004 PreviousSize     : Uint2B

   +0x006 SegmentOffset    : UChar

   +0x006 LFHFlags         : UChar

   +0x007 UnusedBytes      : UChar

   +0x000 FunctionIndex    : Uint2B

   +0x002 ContextValue     : Uint2B

   +0x000 InterceptorValue : Uint4B

   +0x004 UnusedBytesLength : Uint2B

   +0x006 EntryOffset      : UChar

   +0x007 ExtendedBlockSignature : UChar

   +0x000 Code1            : Uint4B

   +0x004 Code2            : Uint2B

   +0x006 Code3            : UChar

   +0x007 Code4            : UChar

   +0x000 AgregateCode     : Uint8B

 

再来看下实际数据:

0:005> dd 004537a0

004537a0  61329aa1 00007314 004a7fc8 003d00c4

004537b0  7e339abf 08007337 7606479c 76064b78

004537c0  00000002 760647ec 00000001 00000000

004537d0  00449890 ffffffff 00000000 00000000

004537e0  00000000 00000000 00000000 00000000

004537f0  760647e0 00000001 00000002 004498b8

00453800  ffffffff 00000000 00000000 00000000

00453810  00000000 0046e848 00000000 00452420

 

接下来定位到Encoding处,进行解码操作:

ntdll!_HEAP

   +0x000 Entry            : _HEAP_ENTRY

   +0x008 SegmentSignature : 0xffeeffee

   +0x00c SegmentFlags     : 0

   +0x010 SegmentListEntry : _LIST_ENTRY [ 0x2c70010 - 0x3d00a8 ]

   +0x018 Heap             : 0x003d0000 _HEAP

   +0x01c BaseAddress      : 0x003d0000

   +0x020 NumberOfPages    : 0x100

   +0x024 FirstEntry       : 0x003d0588 _HEAP_ENTRY

   +0x028 LastValidEntry   : 0x004d0000 _HEAP_ENTRY

   +0x02c NumberOfUnCommittedPages : 0

   +0x030 NumberOfUnCommittedRanges : 1

   +0x034 SegmentAllocatorBackTraceIndex : 0

   +0x036 Reserved         : 0

   +0x038 UCRSegmentList   : _LIST_ENTRY [ 0x4cfff0 - 0x4cfff0 ]

   +0x040 Flags            : 2

   +0x044 ForceFlags       : 0

   +0x048 CompatibilityFlags : 0

   +0x04c EncodeFlagMask   : 0x100000

   +0x050 Encoding         : _HEAP_ENTRY

   +0x058 PointerKey       : 0x1ff34c7d

   +0x05c Interceptor      : 0

   +0x060 VirtualMemoryThreshold : 0xfe00

   +0x064 Signature        : 0xeeffeeff

   +0x068 SegmentReserve   : 0x200000

   +0x06c SegmentCommit    : 0x2000

   +0x070 DeCommitFreeBlockThreshold : 0x800

   +0x074 DeCommitTotalFreeThreshold : 0x2000

   +0x078 TotalFreeSize    : 0x2433

   +0x07c MaximumAllocationSize : 0x7ffdefff

   +0x080 ProcessHeapsListIndex : 1

   +0x082 HeaderValidateLength : 0x138

   +0x084 HeaderValidateCopy : (null)

   +0x088 NextAvailableTagIndex : 0

   +0x08a MaximumTagIndex  : 0

   +0x08c TagEntries       : (null)

   +0x090 UCRList          : _LIST_ENTRY [ 0x2c8ffe8 - 0x2c8ffe8 ]

   +0x098 AlignRound       : 0xf

   +0x09c AlignMask        : 0xfffffff8

   +0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0x3d00a0 - 0x3d00a0 ]

   +0x0a8 SegmentList      : _LIST_ENTRY [ 0x3d0010 - 0x2c70010 ]

   +0x0b0 AllocatorBackTraceIndex : 0

   +0x0b4 NonDedicatedListLength : 0

   +0x0b8 BlocksIndex      : 0x003d0150

   +0x0bc UCRIndex         : 0x003d0590

   +0x0c0 PseudoTagEntries : (null)

   +0x0c4 FreeLists        : _LIST_ENTRY [ 0x4537a8 - 0x2c81fe8 ]

   +0x0cc LockVariable     : 0x003d0138 _HEAP_LOCK

   +0x0d0 CommitRoutine    : 0x1ff34c7d     long  +1ff34c7d

   +0x0d4 FrontEndHeap     : 0x003d66b0

   +0x0d8 FrontHeapLockCount : 0

   +0x0da FrontEndHeapType : 0x2 ''

   +0x0dc Counters         : _HEAP_COUNTERS

   +0x130 TuningParameters : _HEAP_TUNING_PARAMETERS

0:005> dd 003d0000+50

003d0050  63329aa3 00007335 1ff34c7d 00000000

003d0060  0000fe00 eeffeeff 00200000 00002000

003d0070  00000800 00002000 00002433 7ffdefff

003d0080  01380001 00000000 00000000 00000000

003d0090  02c8ffe8 02c8ffe8 0000000f fffffff8

003d00a0  003d00a0 003d00a0 003d0010 02c70010

003d00b0  00000000 00000000 003d0150 003d0590

003d00c0  00000000 004537a8 02c81fe8 003d0138

 堆块入口:

0:005> dd 004537a0

004537a0  61329aa1 00007314 004a7fc8 003d00c4

004537b0  7e339abf 08007337 7606479c 76064b78

004537c0  00000002 760647ec 00000001 00000000

004537d0  00449890 ffffffff 00000000 00000000

004537e0  00000000 00000000 00000000 00000000

004537f0  760647e0 00000001 00000002 004498b8

00453800  ffffffff 00000000 00000000 00000000

00453810  00000000 0046e848 00000000 00452420

 

进行异或操作:

0:005> ? 9aa1^9aa3

Evaluate expression: 2 = 00000002

将结果乘以粒度大小(8字节):

0:005> ?2*8

Evaluate expression: 16 = 00000010

最终得到正确的Size大小,这与!heap -a 1中显示的一致了。

原创粉丝点击