堆地址计算

逆向工程 视窗 记忆 过程 地址
2021-07-03 12:39:29

我可以在windbg反汇编中看到进程堆的句柄,由Windows(WINDOWS 10)为我的进程分配:

0:000> dt nt!_PEB 0106c000
ntdll!_PEB
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0x1 ''
   +0x003 BitField         : 0x4 ''
   +0x003 ImageUsesLargePages : 0y0
   +0x003 IsProtectedProcess : 0y0
   +0x003 IsImageDynamicallyRelocated : 0y1
   +0x003 SkipPatchingUser32Forwarders : 0y0
   +0x003 IsPackagedProcess : 0y0
   +0x003 IsAppContainer   : 0y0
   +0x003 IsProtectedProcessLight : 0y0
   +0x003 IsLongPathAwareProcess : 0y0
   +0x004 Mutant           : 0xffffffff Void
   +0x008 ImageBaseAddress : 0x00840000 Void
   +0x00c Ldr              : 0x77a4ebe0 _PEB_LDR_DATA
   +0x010 ProcessParameters : 0x03b885e0 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : (null) 
   +0x018 ProcessHeap      : 0x03b70000 Void

现在我想检查堆头,并应用dt !_HEAPProcessHeap:0x03b70000,但我可以看到我在结果得到完全以无效数据。!heap -s给了我完全不同的堆结果,

LFH Key                   : 0xd5ec6951
Termination on corruption : ENABLED
  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                    (k)     (k)    (k)     (k) length      blocks cont. heap 
-----------------------------------------------------------------------------
05e90000 00000002    1020      4   1020      2     1     1    0      0      
00ff0000 00001002      60      4     60      2     1     1    0      0     

我明白,必须从这个句柄ProcessHeap : 0x03b70000 Void计算堆头开始的地址,但我不明白它是如何计算的。它不是 va,因为 00840000 + 03b70000 != 05e90000 ,那么如何从堆句柄获取到 _HEAP 结构头的实际地址?

2个回答

这是来自 win7 但这应该没什么关系

ProcessHeap 来自当前进程的 Peb

0:000> dt ntdll!_PEB ProcessHeap @$proc 
   +0x018 ProcessHeap : 0x00430000 Void

heap Stat 相同

0:000> !heap -s @$proc->ProcessHeap


****************************************************************************
                                              NT HEAP STATS BELOW
****************************************************************************
NtGlobalFlag enables following debugging aids for new heaps:
    tail checking
    free checking
    validate parameters
LFH Key                   : 0x20cb0363
Termination on corruption : ENABLED
  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                    (k)     (k)    (k)     (k) length      blocks cont. heap 
-----------------------------------------------------------------------------
00430000 40000062    1024     24   1024      3     7     1    0      0      
00010000 40008060      64      4     64      2     1     1    0      0      
-----------------------------------------------------------------------------

堆入口结构

0:000> dt nt!_Heap Entry.* @@(@$proc->ProcessHeap)
ntdll!_HEAP
   +0x000 Entry  : 
      +0x000 Size   : 0xda5a
      +0x002 Flags  : 0x5b '['
      +0x003 SmallTagIndex : 0xa9 ''
      +0x000 SubSegmentCode : 0xa95bda5a Void
      +0x004 PreviousSize : 0x2d79
      +0x006 SegmentOffset : 0 ''
      +0x006 LFHFlags : 0 ''
      +0x007 UnusedBytes : 0x1 ''
      +0x000 FunctionIndex : 0xda5a
      +0x002 ContextValue : 0xa95b
      +0x000 InterceptorValue : 0xa95bda5a
      +0x004 UnusedBytesLength : 0x2d79
      +0x006 EntryOffset : 0 ''
      +0x007 ExtendedBlockSignature : 0x1 ''
      +0x000 Code1  : 0xa95bda5a
      +0x004 Code2  : 0x2d79
      +0x006 Code3  : 0 ''
      +0x007 Code4  : 0x1 ''
      +0x000 AgregateCode : 0x01002d79`a95bda5a

问题是由于页面堆验证,由Gflags. 我忘记了这一点,堆验证器弄乱了堆句柄。当我禁用它时,PEB 上的句柄变为有效。