Chinaunix首页 | 论坛 | 博客
  • 博客访问: 413617
  • 博文数量: 168
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-09 13:46
文章分类

全部博文(168)

文章存档

2015年(51)

2014年(30)

2013年(87)

我的朋友

分类: WINDOWS

2014-01-28 17:57:01

原文地址:windows 堆管理调试 作者:kanghtta

之前的笔记。放出来备案。

实验环境: Win7 OEM 旗舰版 + windbg 

由于windows 调试堆的支持,内部的数据管理结构有一定差异,
因此,使用附加的方式调试.这里有一个问题要注意.

在windbg,OD中,附加后可能无法调试,原因应该是int 3后进入异常处理
流程,等待debug 事件的接收,如果此时强行g或run,将无法中断在int 3 
断点指令上,替代的一个办法是使用输入流函数(getchar(),cin等),但是
该方法旨在调试有source的情况下可用.


@注意: 在int 3 中断时,家里的机器和公司的表现有差异,目前尚不清楚具体
原因,公司能附加,但只有调试和关闭按钮,家里的多一个错误报告按钮,附加
后调试会话不可用.


由于默认的即时调试器是OD,这里用windbg时需要设置一下: 
进入windbg 目录: windbg -I 


代码使用0day 上的:
 
#include
main()
{
HLOCAL h1,h2,h3,h4,h5,h6;
HANDLE hp;
hp = HeapCreate(0,0x1000,0x10000);
__asm int 3


h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,3);
h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,5);
h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,6);
h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
h5 = HeapAlloc(hp,HEAP_ZERO_MEMORY,19);
h6 = HeapAlloc(hp,HEAP_ZERO_MEMORY,24);

//free block and prevent coaleses
HeapFree(hp,0,h1); //free to freelist[2] 
HeapFree(hp,0,h3); //free to freelist[2] 
HeapFree(hp,0,h5); //free to freelist[4]

HeapFree(hp,0,h4); //coalese h3,h4,h5,link the large block to freelist[8]



return 0;
}




调试器中断后看下堆栈: 
0:000> k
ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
0012ff88 766ced6c heap_debug+0x101b
0012ff94 77a7377b kernel32!BaseThreadInitThunk+0xe
0012ffd4 77a7374e ntdll!__RtlUserThreadStart+0x70
0012ffec 00000000 ntdll!_RtlUserThreadStart+0x1b


接下来看下hp的值: 
0:000> r
eax=004f0000 ebx=7ffd8000 ecx=77a72dfa edx=77ae7500 esi=004f0000 edi=00000000
eip=0040101c esp=0012ff2c ebp=0012ff88 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
heap_debug+0x101c:
0040101c 8b3d04804000    mov     edi,dword ptr [heap_debug+0x8004 (00408004)] ds:0023:00408004={ntdll!RtlAllocateHeap (77a62d66)}


由于函数返回值存放于eax中,这里看寄存器的值就可以:
也可用使用如下命令: 
r eax ; or  r @eax 


先看下该进程的堆:
0:000> !heap
Index   Address  Name      Debugging options enabled
  1:   001d0000                
  2:   00010000                
  3:   00020000                
  4:   00360000                
  5:   004f0000       


也可以从PEB结构中找到进程的堆信息:
 
0:000> dt nt!_PEB Heap* @$PEB
ntdll!_PEB
   +0x078 HeapSegmentReserve : 0x100000
   +0x07c HeapSegmentCommit : 0x2000
   +0x080 HeapDeCommitTotalFreeThreshold : 0x10000
   +0x084 HeapDeCommitFreeBlockThreshold : 0x1000
   +0x240 HeapTracingEnabled : 0y0
   
0:000> dt nt!_PEB ProcessHeaps @$PEB
ntdll!_PEB
   +0x090 ProcessHeaps : 0x77ae7500  -> 0x001d0000 
   
   
0:000> dd 0x77ae7500 l8
77ae7500  001d0000 00010000 00020000 00360000
77ae7510  004f0000 00000000 00000000 00000000


和我们用!heap 扩展命令看到的结果是一致的.


堆块的创建:
1.HeapCreate 函数内部会依据传入的参数,在RtlCreateHeap使用PEB中的堆管理数据
初始化堆管理结构的一些字段.如保留提交大小等.
2.其次,在ntdll中RtlCreateHeap函数会调用ZwQueryVirtualMemory或
ZwAllocateVirtualMemory 从虚拟内存管理器得到一个内存块,
这个内存块的地址就是HeapCreate 成功后返回的堆块地址.
3.在2成功后,RtlCreateHeap内部会初始化HEAP结构体的各个成员.包括
FreeList的初始化.
4.这之后的堆分配或堆释放都基于HEAP堆管理的数据结构.






首先看一下HEAP开头的数据结构有哪些: 
0:000> dt ntdll!_HEAP_*
          ntdll!_HEAP_LIST_LOOKUP
          ntdll!_HEAP_ENTRY
          ntdll!_HEAP_TAG_ENTRY
          ntdll!_HEAP_PSEUDO_TAG_ENTRY
          ntdll!_HEAP_LOCK
          ntdll!_HEAP_COUNTERS
          ntdll!_HEAP_TUNING_PARAMETERS
          ntdll!_HEAP_SEGMENT
          ntdll!_HEAP_FREE_ENTRY
          ntdll!_HEAP_FAILURE_TYPE
          ntdll!_HEAP_SUBSEGMENT
          ntdll!_HEAP_LOCAL_SEGMENT_INFO
          ntdll!_HEAP_USERDATA_HEADER
          ntdll!_HEAP_USERDATA_HEADER
          ntdll!_HEAP_BUCKET_COUNTERS
          ntdll!_HEAP_LOCAL_DATA
          ntdll!_HEAP_LOCAL_DATA
          ntdll!_HEAP_BUCKET_RUN_INFO
          ntdll!_HEAP_BUCKET
          ntdll!_HEAP_BUCKET
          ntdll!_HEAP_FAILURE_INFORMATION
          ntdll!_HEAP_UCR_DESCRIPTOR
          ntdll!_HEAP_ENTRY_EXTRA
          ntdll!_HEAP_DEBUGGING_INFORMATION
 
下面,我们来看一下堆管理的几个重要的数据结构.
HEAP   堆管理器用HEAP结构来记录和维护堆的管理信息.
HEAP_SEGMENT 堆段和HEAP部分字段重叠,一个堆可能有多个堆段.
在win7种原来的segments 结构由数组变为链表.
HEAP_ENTRY 堆块,程序中真正能使用的部分.
HEAP_ENTRY_FREE 以及其它堆管理数据结构,但这里重要介绍上面几种.


我们看一下HeapCreate 创建的堆块最开始是什么样?


0:000> dt _HEAP 004f0000
ntdll!_HEAP
   +0x000 Entry            : _HEAP_ENTRY  用于存放堆管理数据结构的堆块结构
   +0x008 SegmentSignature : 0xffeeffee    堆段结构签名
   +0x00c SegmentFlags     : 0   堆段标志
   +0x010 SegmentListEntry : _LIST_ENTRY [ 0x4f00a8 - 0x4f00a8 ] 堆段链表,这里是和win2003 ,nt 有区别的地方
   +0x018 Heap             : 0x004f0000 _HEAP  
   +0x01c BaseAddress      : 0x004f0000 
   +0x020 NumberOfPages    : 0x10    堆块占用的内存页数
   +0x024 FirstEntry       : 0x004f0588 _HEAP_ENTRY   第一个堆块
   +0x028 LastValidEntry   : 0x00500000 _HEAP_ENTRY
   +0x02c NumberOfUnCommittedPages : 0xf   尚未提交的内存页数
   +0x030 NumberOfUnCommittedRanges : 1    UnCommittedRanges 数组元素数
   +0x034 SegmentAllocatorBackTraceIndex : 0   初始化段的UST 记录序号
   +0x036 Reserved         : 0
   +0x038 UCRSegmentList   : _LIST_ENTRY [ 0x4f0ff0 - 0x4f0ff0 ]
   +0x040 Flags            : 0x1000   堆的标志,标示该堆段的属性,是否可增长,是否启用堆检查。
   +0x044 ForceFlags       : 0   强制标志,和堆释放有关
   +0x048 CompatibilityFlags : 0
   +0x04c EncodeFlagMask   : 0x100000 是否启用编码功能
   +0x050 Encoding         : _HEAP_ENTRY 编码后的HEAP_ENTRY结构,这个很重要,win7的一个变化也在此,后面会讲下。
   +0x058 PointerKey       : 0x77c065cf
   +0x05c Interceptor      : 0
   +0x060 VirtualMemoryThreshold : 0xfe00   以分配粒度为单位的堆块阀值 (508K )
   +0x064 Signature        : 0xeeffeeff
   +0x068 SegmentReserve   : 0x100000 堆段保留大小
   +0x06c SegmentCommit    : 0x2000 堆段提交大小
   +0x070 DeCommitFreeBlockThreshold : 0x200   和释放堆内存有关,本次释放堆块阀值
   +0x074 DeCommitTotalFreeThreshold : 0x2000  堆释放有关,总空闲空间阀值
   +0x078 TotalFreeSize    : 0x14b 堆块空闲空间
   +0x07c MaximumAllocationSize : 0x7ffdefff
   +0x080 ProcessHeapsListIndex : 5 PEB中ProcessHaaps的索引
   +0x082 HeaderValidateLength : 0x138
   +0x084 HeaderValidateCopy : (null) 
   +0x088 NextAvailableTagIndex : 0
   +0x08a MaximumTagIndex  : 0
   +0x08c TagEntries       : (null) 
   +0x090 UCRList          : _LIST_ENTRY [ 0x4f0fe8 - 0x4f0fe8 ]
   +0x098 AlignRound       : 0xf
   +0x09c AlignMask        : 0xfffffff8   用于地址对齐的掩码
   +0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0x4f00a0 - 0x4f00a0 ]   虚拟内存分配块链表,超过堆块阀值将在此分配
   +0x0a8 SegmentList      : _LIST_ENTRY [ 0x4f0010 - 0x4f0010 ]      堆段链表,win2003 为数组。
   +0x0b0 AllocatorBackTraceIndex : 0
   +0x0b4 NonDedicatedListLength : 0
   +0x0b8 BlocksIndex      : 0x004f0150 
   +0x0bc UCRIndex         : (null) 
   +0x0c0 PseudoTagEntries : (null) 
   +0x0c4 FreeLists        : _LIST_ENTRY [ 0x4f0590 - 0x4f0590 ]   空闲堆块链表,堆分配用 (后端堆)
   +0x0cc LockVariable     : 0x004f0138 _HEAP_LOCK   控制线程系列化
   +0x0d0 CommitRoutine    : 0x77c065cf     long  +77c065cf       
   +0x0d4 FrontEndHeap     : (null)  用于快速释放堆块的前端堆
   +0x0d8 FrontHeapLockCount : 0    前端堆锁定计数
   +0x0da FrontEndHeapType : 0 ''
   +0x0dc Counters         : _HEAP_COUNTERS
   +0x130 TuningParameters : _HEAP_TUNING_PARAMETERS


堆段数据结构,参考HEAP前面的说明:
0:000> dt _HEAP_SEGMENT 004f0000
ntdll!_HEAP_SEGMENT
   +0x000 Entry            : _HEAP_ENTRY
   +0x008 SegmentSignature : 0xffeeffee
   +0x00c SegmentFlags     : 0
   +0x010 SegmentListEntry : _LIST_ENTRY [ 0x4f00a8 - 0x4f00a8 ]
   +0x018 Heap             : 0x004f0000 _HEAP
   +0x01c BaseAddress      : 0x004f0000 
   +0x020 NumberOfPages    : 0x10
   +0x024 FirstEntry       : 0x004f0588 _HEAP_ENTRY
   +0x028 LastValidEntry   : 0x00500000 _HEAP_ENTRY
   +0x02c NumberOfUnCommittedPages : 0xf
   +0x030 NumberOfUnCommittedRanges : 1
   +0x034 SegmentAllocatorBackTraceIndex : 0
   +0x036 Reserved         : 0
   +0x038 UCRSegmentList   : _LIST_ENTRY [ 0x4f0ff0 - 0x4f0ff0 ]


 
我们来看一下刚分配的堆结构信息:
0:000> !heap -a 004f0000
Index   Address  Name      Debugging options enabled
  5:   004f0000 
    Segment at 004f0000 to 00500000 (00001000 bytes committed)
    Flags:                00001000
    ForceFlags:           00000000
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      0000014b
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     004f0138
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   004f00a0
    Uncommitted ranges:   004f0090
            004f1000: 0000f000  (61440 bytes)
    FreeList[ 00 ] at 004f00c4: 004f0590 . 004f0590  
        004f0588: 00588 . 00a58 [100] - free


    Segment00 at 004f0000:
        Flags:           00000000
        Base:            004f0000
        First Entry:     004f0588
        Last Entry:      00500000
        Total Pages:     00000010
        Total UnCommit:  0000000f
        Largest UnCommit:00000000
        UnCommitted Ranges: (1)


    Heap entries for Segment00 in Heap 004f0000
        004f0000: 00000 . 00588 [101] - busy (587)
        004f0588: 00588 . 00a58 [100]
        004f0fe0: 00a58 . 00020 [111] - busy (1d)
        004f1000:      0000f000      - uncommitted bytes.


windows堆管理器,将从虚拟内存管理器中申请来的内存划分为一系列的堆块。
每个堆块的起始处都是8字节的HEAP_ENTRY结构,随后是该堆块的用户区,
而HEAP结构中包含了最大的堆块长度,如果申请的堆大小超过该阀值,并且
该堆为可增长的,那么,堆管理器将直接向虚拟内存管理器申请。故此一个
堆也可以看作堆块的链表.


我们看第一个HEAP_ENTRY : 
0:000> dt _HEAP_ENTRY 004f0000
ntdll!_HEAP_ENTRY
   +0x000 Size             : 0x93b8     堆块的大小,已分配粒度为单位
   +0x002 Flags            : 0x1e '' 堆块状态标志
   +0x003 SmallTagIndex    : 0xf3 '' 用于检查堆溢出的cookie 
   +0x000 SubSegmentCode   : 0xf31e93b8 
   +0x004 PreviousSize     : 0xbfa 前一堆块大小
   +0x006 SegmentOffset    : 0 ''
   +0x006 LFHFlags         : 0 '' 低碎片堆标志
   +0x007 UnusedBytes      : 0x1 '' 对齐用,
   +0x000 FunctionIndex    : 0x93b8
   +0x002 ContextValue     : 0xf31e
   +0x000 InterceptorValue : 0xf31e93b8
   +0x004 UnusedBytesLength : 0xbfa
   +0x006 EntryOffset      : 0 '' 堆块偏移
   +0x007 ExtendedBlockSignature : 0x1 ''
   +0x000 Code1            : 0xf31e93b8
   +0x004 Code2            : 0xbfa
   +0x006 Code3            : 0 ''
   +0x007 Code4            : 0x1 ''
   +0x000 AgregateCode     : 0x1000bfa`f31e93b8


Flags:
|------------------------------------------------------------------------
| 标志 | 值   | 含义 |
|------------------------------------------------------------------------
|HEAP_ENTRY_BUSY         |       01        |     堆块处于占用状态 |
|------------------------------------------------------------------------
|HEAP_ENTRY_EXTRY_PRESENT   | 02  |   存在额外描述 |
|------------------------------------------------------------------------
|HEAP_ENTRY_FILL_PATTERN    | 03  |   使用固定模式填充堆块|
|------------------------------------------------------------------------
|HEAP_ENTRY_VIRTUAL_ALLOC   | 04  |   虚拟分配 |
|------------------------------------------------------------------------
|HEAP_ENTRY_LAST_ENTRY      | 0x10  |   这是最后一个块 |
|------------------------------------------------------------------------


我们上面通过!haap堆扩展显示的第一个堆块大小为00588这里是0x93b8 ,why?


这要回到我们HEAP中Encoding,当启用了编码功能,其实就是将一个堆块和编码
的堆块模板作异或操作,我们要还原真实的大小,得先找到Encoding 对应的HEAP_ENTRY结构


0:000> dt _HEAP Encoding 004f0000
ntdll!_HEAP
   +0x050 Encoding : _HEAP_ENTRY
   
0:000> dt _HEAP Encoding. 004f0000
ntdll!_HEAP
   +0x050 Encoding  : 
      +0x000 Size      : 0x9309
      +0x002 Flags     : 0x1f ''
      +0x003 SmallTagIndex : 0x43 'C'
      +0x000 SubSegmentCode : 0x431f9309 
      +0x004 PreviousSize : 0xbfa
      +0x006 SegmentOffset : 0 ''
      +0x006 LFHFlags  : 0 ''
      +0x007 UnusedBytes : 0 ''
      +0x000 FunctionIndex : 0x9309
      +0x002 ContextValue : 0x431f
      +0x000 InterceptorValue : 0x431f9309
      +0x004 UnusedBytesLength : 0xbfa
      +0x006 EntryOffset : 0 ''
      +0x007 ExtendedBlockSignature : 0 ''
      +0x000 Code1     : 0x431f9309
      +0x004 Code2     : 0xbfa
      +0x006 Code3     : 0 ''
      +0x007 Code4     : 0 ''
      +0x000 AgregateCode : 0xbfa`431f9309
 
我们将对应的字段异或:


0:000> ?(9309^93b8)
Evaluate expression: 177 = 000000b1
0:000> ?b1*8
Evaluate expression: 1416 = 00000588
0:000> ?(0x1f ^ 0x1e)
Evaluate expression: 1 = 00000001


可以看出,大小和之前的一致.


我们在一路pc 到释放第一个堆块处:
0:000> dt _HEAP FreeLists. 004f0000
ntdll!_HEAP
   +0x0c4 FreeLists  :  [ 0x4f0590 - 0x4f0610 ]
      +0x000 Flink      : 0x004f0590 _LIST_ENTRY [ 0x4f0610 - 0x4f00c4 ]
      +0x004 Blink      : 0x004f0610 _LIST_ENTRY [ 0x4f00c4 - 0x4f0590 ]
 
0:000> pc ;p ;!heap -a 004f0000 ;
Index   Address  Name      Debugging options enabled
  5:   004f0000 
    Segment at 004f0000 to 00500000 (00001000 bytes committed)
    Flags:                00001000
    ForceFlags:           00000000
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      0000013d
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     004f0138
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   004f00a0
    Uncommitted ranges:   004f0090
            004f1000: 0000f000  (61440 bytes)
    FreeList[ 00 ] at 004f00c4: 004f0610 . 004f0590  
        004f0588: 00588 . 00010 [100] - free
        004f0608: 00020 . 009d8 [100] - free


    Segment00 at 004f0000:
        Flags:           00000000
        Base:            004f0000
        First Entry:     004f0588
        Last Entry:      00500000
        Total Pages:     00000010
        Total UnCommit:  0000000f
        Largest UnCommit:00000000
        UnCommitted Ranges: (1)


    Heap entries for Segment00 in Heap 004f0000
        004f0000: 00000 . 00588 [101] - busy (587)
        004f0588: 00588 . 00010 [100]   ;free
        004f0598: 00010 . 00010 [101] - busy (5)
        004f05a8: 00010 . 00010 [101] - busy (6)
        004f05b8: 00010 . 00010 [101] - busy (8)
        004f05c8: 00010 . 00020 [101] - busy (13)
        004f05e8: 00020 . 00020 [101] - busy (18)
        004f0608: 00020 . 009d8 [100] ;free
        004f0fe0: 009d8 . 00020 [111] - busy (1d)
        004f1000:      0000f000      - uncommitted bytes.

0:000> !list "-t _LIST_ENTRY.Flink -e -x \"dd @$extret l2 ;dt _LIST_ENTRY @$extret\" 004f00c4"
dd @$extret l2 ;dt _LIST_ENTRY @$extret 
004f00c4  004f0590 004f0610
ntdll!_LIST_ENTRY
 [ 0x4f0590 - 0x4f0610 ]
   +0x000 Flink            : 0x004f0590 _LIST_ENTRY [ 0x4f0610 - 0x4f00c4 ]
   +0x004 Blink            : 0x004f0610 _LIST_ENTRY [ 0x4f00c4 - 0x4f0590 ]


dd @$extret l2 ;dt _LIST_ENTRY @$extret 
004f0590  004f0610 004f00c4
ntdll!_LIST_ENTRY
 [ 0x4f0610 - 0x4f00c4 ]
   +0x000 Flink            : 0x004f0610 _LIST_ENTRY [ 0x4f00c4 - 0x4f0590 ]
   +0x004 Blink            : 0x004f00c4 _LIST_ENTRY [ 0x4f0590 - 0x4f0610 ]



0:000> !list "-t _LIST_ENTRY.Flink -e -x \"dd @$extret l2 ;dt _LIST_ENTRY @$extret\" 004f0590"
dd @$extret l2 ;dt _LIST_ENTRY @$extret 
004f0590  004f0610 004f00c4
ntdll!_LIST_ENTRY
 [ 0x4f0610 - 0x4f00c4 ]
   +0x000 Flink            : 0x004f0610 _LIST_ENTRY [ 0x4f00c4 - 0x4f0590 ]
   +0x004 Blink            : 0x004f00c4 _LIST_ENTRY [ 0x4f0590 - 0x4f0610 ]


dd @$extret l2 ;dt _LIST_ENTRY @$extret 
004f0610  004f00c4 004f0590
ntdll!_LIST_ENTRY
 [ 0x4f00c4 - 0x4f0590 ]
   +0x000 Flink            : 0x004f00c4 _LIST_ENTRY [ 0x4f0590 - 0x4f0610 ]
   +0x004 Blink            : 0x004f0590 _LIST_ENTRY [ 0x4f0610 - 0x4f00c4 ]




接下来我们释放大小为6的结点: 
0:000> pc ;p ;!heap -a 004f0000 ;
Index   Address  Name      Debugging options enabled
  5:   004f0000 
    Segment at 004f0000 to 00500000 (00001000 bytes committed)
    Flags:                00001000
    ForceFlags:           00000000
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      0000013f
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     004f0138
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   004f00a0
    Uncommitted ranges:   004f0090
            004f1000: 0000f000  (61440 bytes)
    FreeList[ 00 ] at 004f00c4: 004f0610 . 004f05b0  
        004f05a8: 00010 . 00010 [100] - free
        004f0588: 00588 . 00010 [100] - free
        004f0608: 00020 . 009d8 [100] - free


    Segment00 at 004f0000:
        Flags:           00000000
        Base:            004f0000
        First Entry:     004f0588
        Last Entry:      00500000
        Total Pages:     00000010
        Total UnCommit:  0000000f
        Largest UnCommit:00000000
        UnCommitted Ranges: (1)


    Heap entries for Segment00 in Heap 004f0000
        004f0000: 00000 . 00588 [101] - busy (587)
        004f0588: 00588 . 00010 [100]
        004f0598: 00010 . 00010 [101] - busy (5)
        004f05a8: 00010 . 00010 [100]
        004f05b8: 00010 . 00010 [101] - busy (8)
        004f05c8: 00010 . 00020 [101] - busy (13)
        004f05e8: 00020 . 00020 [101] - busy (18)
        004f0608: 00020 . 009d8 [100]
        004f0fe0: 009d8 . 00020 [111] - busy (1d)
        004f1000:      0000f000      - uncommitted bytes.

0:000> !list "-t _LIST_ENTRY.Flink -e -x \"dd @$extret l2 ;dt _LIST_ENTRY @$extret\" 004f00c4"
dd @$extret l2 ;dt _LIST_ENTRY @$extret 
004f00c4  004f05b0 004f0610
ntdll!_LIST_ENTRY
 [ 0x4f05b0 - 0x4f0610 ]
   +0x000 Flink            : 0x004f05b0 _LIST_ENTRY [ 0x4f0590 - 0x4f00c4 ]
   +0x004 Blink            : 0x004f0610 _LIST_ENTRY [ 0x4f00c4 - 0x4f0590 ]


dd @$extret l2 ;dt _LIST_ENTRY @$extret 
004f05b0  004f0590 004f00c4
ntdll!_LIST_ENTRY
 [ 0x4f0590 - 0x4f00c4 ]
   +0x000 Flink            : 0x004f0590 _LIST_ENTRY [ 0x4f0610 - 0x4f05b0 ]
   +0x004 Blink            : 0x004f00c4 _LIST_ENTRY [ 0x4f05b0 - 0x4f0610 ]


dd @$extret l2 ;dt _LIST_ENTRY @$extret 
004f0590  004f0610 004f05b0
ntdll!_LIST_ENTRY
 [ 0x4f0610 - 0x4f05b0 ]
   +0x000 Flink            : 0x004f0610 _LIST_ENTRY [ 0x4f00c4 - 0x4f0590 ]
   +0x004 Blink            : 0x004f05b0 _LIST_ENTRY [ 0x4f0590 - 0x4f00c4 ]


 
ntdll!RtlAllocateHeap:
77a62d66 8bff            mov     edi,edi
77a62d68 55              push    ebp
77a62d69 8bec            mov     ebp,esp
77a62d6b 83ec60          sub     esp,60h
77a62d6e 53              push    ebx
77a62d6f 56              push    esi
77a62d70 33f6            xor     esi,esi
77a62d72 817d10ffffff7f  cmp     dword ptr [ebp+10h],7FFFFFFFh     ;比较分配的大小
77a62d79 57              push    edi
77a62d7a 8975f8          mov     dword ptr [ebp-8],esi
77a62d7d 0f87eeae0200    ja      ntdll!RtlAllocateHeap+0x79 (77a8dc71)
77a62d83 8b5d08          mov     ebx,dword ptr [ebp+8] ;ebx = heapHandle
77a62d86 8b4344          mov     eax,dword ptr [ebx+44h] ds:0023:004f0044=00000000 ; HEAP.ForceFlags
77a62d89 8b4b5c          mov     ecx,dword ptr [ebx+5Ch]   ;HEAP.Interceptor
77a62d8c 09450c          or      dword ptr [ebp+0Ch],eax   ;Flag or HEAP.ForceFlags
77a62d8f 894df4          mov     dword ptr [ebp-0Ch],ecx   ; [ebp-0ch ] is ntdll!_HEAP.Interceptor
77a62d92 3bce            cmp     ecx,esi ; 判断 Interceptor 是否为0 
77a62d94 0f858eae0200    jne     ntdll!RtlAllocateHeap+0x30 (77a8dc28) ;不为0则跳转
77a62d9a f7450c610f817d  test    dword ptr [ebp+0Ch],7D810F61h   ;Flags & 7D810f61h
77a62da1 0f85b12c0000    jne     ntdll!RtlAllocateHeap+0x222 (77a65a58)
77a62da7 397510          cmp     dword ptr [ebp+10h],esi   ;Size 是否为0.
77a62daa 0f8429210100    je      ntdll!RtlAllocateHeap+0x19a (77a74ed9)
77a62db0 8b4510          mov     eax,dword ptr [ebp+10h]
77a62db3 83c00f          add     eax,0Fh
77a62db6 83e0f8          and     eax,0FFFFFFF8h ;分配粒度计算
77a62db9 8bc8            mov     ecx,eax
77a62dbb 8945f8          mov     dword ptr [ebp-8],eax ;存储实际分配大小 AllocationSize
77a62dbe 8b83b8000000    mov     eax,dword ptr [ebx+0B8h]   ;ntdll!_HEAP.BlocksIndex 这里为0 


_Heap.BlocksIndex
004f0150  00000000 00000080 00000001 00000001
004f0160  00000001 00000000 004f00c4 004f0174
004f0170  004f0184 00000000 00000000 00000000
004f0180  80000000 00000000 00000000 00000000
004f0190  00000000 00000000 00000000 00000000
004f01a0  00000000 00000000 00000000 00000000
004f01b0  00000000 00000000 00000000 00000000
004f01c0  00000000 00000000 00000000 00000000


77a62dc4 c1e903          shr     ecx,3 ;AllocationIndex = AllocationSize >>  HEAP_GRANULARITY_SHIFT;
77a62dc7 3b4804          cmp     ecx,dword ptr [eax+4] ;[eax+4] HEAP_MAXIMUM_FREELISTS  AllocationIndex < 128 
77a62dca 0f834f3a0000    jae     ntdll!RtlAllocateHeap+0x1b3 (77a6681f)
77a62dd0 8b5004          mov     edx,dword ptr [eax+4] ;HEAP_MAXIMUM_FREELISTS to edx 
77a62dd3 4a              dec     edx
77a62dd4 3bca            cmp     ecx,edx ;if (AllocationIndex < edx-1)
77a62dd6 0f8323750000    jae     ntdll!RtlAllocateHeap+0x1ce (77a6a2ff)
77a62ddc 2b4814          sub     ecx,dword ptr [eax+14h]
77a62ddf 83780800        cmp     dword ptr [eax+8],0 ;判断[eax+8] 是否为0
77a62de3 7402            je      ntdll!RtlAllocateHeap+0x1e3 (77a62de7)
77a62de5 03c9            add     ecx,ecx ;AllocationIndex *2 
77a62de7 8b4020          mov     eax,dword ptr [eax+20h]
77a62dea 8d3488          lea     esi,[eax+ecx*4]   
77a62ded 85f6            test    esi,esi     ;测试是否相等
77a62def 0f84632c0000    je      ntdll!RtlAllocateHeap+0x222 (77a65a58)
77a62df5 8b4604          mov     eax,dword ptr [esi+4]
77a62df8 a801            test    al,1
77a62dfa 0f84582c0000    je      ntdll!RtlAllocateHeap+0x222 (77a65a58)
77a62e00 8b5510          mov     edx,dword ptr [ebp+10h]
77a62e03 8d48ff          lea     ecx,[eax-1]
77a62e06 c745f002000000  mov     dword ptr [ebp-10h],2
77a62e0d e842000000      call    ntdll!RtlpLowFragHeapAllocFromContext (77a62e54)
77a62e12 8bf8            mov     edi,eax
77a62e14 85ff            test    edi,edi
77a62e16 0f843c2c0000    je      ntdll!RtlAllocateHeap+0x222 (77a65a58)
77a62e1c f6450c08        test    byte ptr [ebp+0Ch],8
77a62e20 0f85d2bc0000    jne     ntdll!RtlAllocateHeap+0x212 (77a6eaf8)




77a62e26 85ff            test    edi,edi
77a62e28 0f8445ae0200    je      ntdll!RtlAllocateHeap+0x7b (77a8dc73)
77a62e2e 8b75f4          mov     esi,dword ptr [ebp-0Ch]
77a62e31 85f6            test    esi,esi
77a62e33 0f854eaf0200    jne     ntdll!RtlAllocateHeap+0x24f (77a8dd87)
77a62e39 803d8003fe7f00  cmp     byte ptr [SharedUserData+0x380 (7ffe0380)],0
77a62e40 0f858bae0200    jne     ntdll!RtlAllocateHeap+0xe1 (77a8dcd1)
77a62e46 8bc7            mov     eax,edi
77a62e48 5f              pop     edi
77a62e49 5e              pop     esi
77a62e4a 5b              pop     ebx
77a62e4b c9              leave
77a62e4c c20c00          ret     0Ch


后端堆: 
77a65a58 8b550c          mov     edx,dword ptr [ebp+0Ch] ss:0023:0012ff24=00000008 ;Size 
77a65a5b 8d45f0          lea     eax,[ebp-10h]
77a65a5e 50              push    eax
77a65a5f 56              push    esi ; ref: 77a62dea  lea     esi,[eax+ecx*4] 
77a65a60 ff75f8          push    dword ptr [ebp-8]  ; AllocateSize
77a65a63 83ca02          or      edx,2
77a65a66 ff7510          push    dword ptr [ebp+10h] ;Size
77a65a69 8bcb            mov     ecx,ebx ;ebx is heapHandle: _HEAP 
77a65a6b e80c000000      call    ntdll!RtlpAllocateHeap (77a65a7c)
77a65a70 8bf8            mov     edi,eax
77a65a72 e9afd3ffff      jmp     ntdll!RtlAllocateHeap+0x23c (77a62e26)




阅读(2737) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~