在调试堆时对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 |