티스토리 뷰

본 문서는 원문 저자인 Massimiliano Tomassoli의 허락 하에 번역이 되었으며, 원문과 관련된 모든 저작물에 대한 저작권은 원문 저자인 Massimiliano Tomassoli에 있음을 밝힙니다. 


http://expdev-kiuhnm.rhcloud.com


최신 윈도우즈 익스플로잇 개발 04. 힙 (Heap)


hackability.kr (김태범)

hackability_at_naver.com or ktb88_at_korea.ac.kr

2016.07.19



프로세스가 시작이 되면 힙 관리자는 기본 프로세스 힙 (default process heap) 이라는 새로운 힙을 생성합니다. C/C++ 응용 프로그램들은 new/delete, malloc/free에서 사용하는 CRT 힙 이라는 것을 생성합니다이 힙은 HeapCreate API 함수를 이용해서 생성할 수도 있습니다윈도우즈 힙 관리자는 Front End Allocator  Back End Allocator 로 구성되어 있습니다.



Front End Allocator


Front end allocator  back end allocator를 위해 최적화 레이어를 추상화 합니다여기에는 최적화 방식에 따라 서로 다른 종류의 front end allocator 들이 존재합니다.

  1. Look aside list (LAL) front end allocator
  2. Low fragmentation (LF) front end allocator

LAL 128 개의 단일 링크드 리스트의 테이블 입니다각각의 리스트는 16 바이트 이상의 특정 크기를 갖는 free block 들을 갖습니다각각의 블록 크기에는 블록을 관리하기 위해 8 바이트 메타데이터를 포함합니다크기가 주어졌을 때테이블에서 색인 (index)을 결정하는 공식은 다음과 같습니다.


index = ceil( (size + 8) / 8 ) – 1, +8은 메타 데이터이며 index는 항상 양수


윈도우즈 Vista 부터는 LAL front end allocator가 더 이상 사용되지 않고 LFH front end allocator 가 사용됩니다. LFH front end allocator 는 매우 복합하긴 하지만 주 아이디어는 할당 요청 받은 사이즈를 충분히 담을 수 있을 메모리 블럭에서 가장 작은 메모리 블럭들로 할당을 하여 힙 단편화 (fragmentation)을 줄이는 것 입니다.



Back End Allocator


만약 front end allocator 요청에 부합되지 않는다면 해당 요청은 back end allocator 로 전달됩니다.

 

윈도우즈 XP 에서는 back end allocator front end allocator 와 비슷한 테이블 형태로 사용되었습니다테이블의 인덱스 0  1016 바이트 보다 크거나 가상 할당 제한 (virtual allocation limit) 0x7FFF0 크기 이하인 free block 을 가지고 있습니다리스트의 블록들은 크기 순으로 오름차순으로 정렬되어 있습니다인덱스 1은 사용되지 않고 일반적으로 인덱스 x  8x 사이즈인 free block 을 가지고 있습니다만약 특정 크기의 블록이 필요한데 유효하지 않다면 back end allocator는 필요한 크기의 블록에 더 큰 블록들로 나눕니다다른 방식으로는 heap coalescing 이라는 것이 있는데 이는 힙 관리자가 인접한 2개의 free block 을 확인하여 둘 다 해제 상태 일 시 하나의 블록으로 coalesce (병합하는 것 입니다이를 통해 힙 단편화를 줄일 수 있습니다. 0x7FFF0 보다 큰 크기를 할당 할 때힙 관리자는 가상 메모리 관리자에게 명시적으로 요청을 전달하고 가상 할당 리스트 (virtual allocation list)라 불리는 리스트에서 관리하게 됩니다.

 

윈도우즈 7에서는 특정 크기에 대한 free lists 를 더이상 관여하지 않습니다윈도우즈 7에서는 단일 free list 를 사용하며 이는 모든 크기의 블록에 대해 크기에 대해 오름차순으로 가지고 있으며 노드들의 (ListHint 타입리스트는 free list 를 가리키고 이는 할당 요청에 대한 적합한 크기의 노드를 찾는데 사용됩니다.



Heap segments


힙 관리자에서 사용되는 모든 메모리는 윈도우즈 가상 메모리 관리자(Windows virtual memory manager)에서 요청됩니다힙 관리자는 세그먼트(segment )라 불리는 가상 메모리 청크(chunk)를 요청합니다이런 세그먼트들은 힙 관리자에 의해 블록들이나 internal bookkeeping structure 를 할당하는데 사용됩니다새로운 세그먼트가 생성되었을 때해당 메모리는 단지 예약으로만 되어 있으며 할당된 자그마한 영역만 주어집니다더 큰 메모리가 필요할 때 다른 영역이 할당됩니다마지막으로 현재 세그먼트에서 할당 되지 않은 공간이 부족할 때기존 보다 2배 큰 새로운 세그먼트가 생성됩니다만약 메모리가 부족하여 새로운 할당이 불가능 하다면 작은 세그먼트를 생성하게 됩니다만약 더 작은 세그먼트 조차 할당이 불가능 하다면 에러를 반환하게 됩니다.



힙 분석


힙 리스트는 PEB (Process Environment Block) 0x90 에 위치해 있습니다.


0:001> dt _PEB @$peb

 ntdll!_PEB

 +0x000 InheritedAddressSpace : 0 ''

 +0x001 ReadImageFileExecOptions : 0 ''

 +0x002 BeingDebugged    : 0x1 ''

 +0x003 BitField         : 0x8 ''

 +0x003 ImageUsesLargePages : 0y0

 +0x003 IsProtectedProcess : 0y0

 +0x003 IsLegacyProcess  : 0y0

 +0x003 IsImageDynamicallyRelocated : 0y1

 +0x003 SkipPatchingUser32Forwarders : 0y0

 +0x003 SpareBits        : 0y000

 +0x004 Mutant           : 0xffffffff Void

 +0x008 ImageBaseAddress : 0x004a0000 Void

 +0x00c Ldr              : 0x77eb0200 _PEB_LDR_DATA

 +0x010 ProcessParameters : 0x002d13c8 _RTL_USER_PROCESS_PARAMETERS

 +0x014 SubSystemData    : (null)

 +0x018 ProcessHeap      : 0x002d0000 Void

 +0x01c FastPebLock      : 0x77eb2100 _RTL_CRITICAL_SECTION

 +0x020 AtlThunkSListPtr : (null)

 +0x024 IFEOKey          : (null)

 +0x028 CrossProcessFlags : 0

 +0x028 ProcessInJob     : 0y0

 +0x028 ProcessInitializing : 0y0

 +0x028 ProcessUsingVEH  : 0y0

 +0x028 ProcessUsingVCH  : 0y0

 +0x028 ProcessUsingFTH  : 0y0

 +0x028 ReservedBits0    : 0y000000000000000000000000000 (0)

 +0x02c KernelCallbackTable : 0x760eb9f0 Void

 +0x02c UserSharedInfoPtr : 0x760eb9f0 Void

 +0x030 SystemReserved   : [1] 0

 +0x034 AtlThunkSListPtr32 : 0

 +0x038 ApiSetMap        : 0x00040000 Void

 +0x03c TlsExpansionCounter : 0

 +0x040 TlsBitmap        : 0x77eb4250 Void

 +0x044 TlsBitmapBits    : [2] 0x1fffffff

 +0x04c ReadOnlySharedMemoryBase : 0x7efe0000 Void

 +0x050 HotpatchInformation : (null)

 +0x054 ReadOnlyStaticServerData : 0x7efe0a90  -> (null)

 +0x058 AnsiCodePageData : 0x7efb0000 Void

 +0x05c OemCodePageData  : 0x7efc0228 Void

 +0x060 UnicodeCaseTableData : 0x7efd0650 Void

 +0x064 NumberOfProcessors : 8

 +0x068 NtGlobalFlag     : 0x70

 +0x070 CriticalSectionTimeout : _LARGE_INTEGER 0xffffe86d`079b8000

 +0x078 HeapSegmentReserve : 0x100000

 +0x07c HeapSegmentCommit : 0x2000

 +0x080 HeapDeCommitTotalFreeThreshold : 0x10000

 +0x084 HeapDeCommitFreeBlockThreshold : 0x1000

 +0x088 NumberOfHeaps    : 7

 +0x08c MaximumNumberOfHeaps : 0x10

 +0x090 ProcessHeaps     : 0x77eb4760  -> 0x002d0000 Void

 +0x094 GdiSharedHandleTable : (null)

 +0x098 ProcessStarterHelper : (null)

 +0x09c GdiDCAttributeList : 0

 +0x0a0 LoaderLock       : 0x77eb20c0 _RTL_CRITICAL_SECTION

 +0x0a4 OSMajorVersion   : 6

 +0x0a8 OSMinorVersion   : 1

 +0x0ac OSBuildNumber    : 0x1db1

 +0x0ae OSCSDVersion     : 0x100

 +0x0b0 OSPlatformId     : 2

 +0x0b4 ImageSubsystem   : 2

 +0x0b8 ImageSubsystemMajorVersion : 6

 +0x0bc ImageSubsystemMinorVersion : 1

 +0x0c0 ActiveProcessAffinityMask : 0xff

 +0x0c4 GdiHandleBuffer  : [34] 0

 +0x14c PostProcessInitRoutine : (null)

 +0x150 TlsExpansionBitmap : 0x77eb4248 Void

 +0x154 TlsExpansionBitmapBits : [32] 1

 +0x1d4 SessionId        : 1

 +0x1d8 AppCompatFlags   : _ULARGE_INTEGER 0x0

 +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER 0x0

 +0x1e8 pShimData        : (null)

 +0x1ec AppCompatInfo    : (null)

 +0x1f0 CSDVersion       : _UNICODE_STRING "Service Pack 1"

 +0x1f8 ActivationContextData : 0x00060000 _ACTIVATION_CONTEXT_DATA

 +0x1fc ProcessAssemblyStorageMap : 0x002d4988 _ASSEMBLY_STORAGE_MAP

 +0x200 SystemDefaultActivationContextData : 0x00050000 _ACTIVATION_CONTEXT_DATA

 +0x204 SystemAssemblyStorageMap : (null)

 +0x208 MinimumStackCommit : 0

 +0x20c FlsCallback      : 0x002d5cb8 _FLS_CALLBACK_INFO

 +0x210 FlsListHead      : _LIST_ENTRY [ 0x2d5a98 - 0x2d5a98 ]

 +0x218 FlsBitmap        : 0x77eb4240 Void

 +0x21c FlsBitmapBits    : [4] 0x1f

 +0x22c FlsHighIndex     : 4

 +0x230 WerRegistrationData : (null)

 +0x234 WerShipAssertPtr : (null)

 +0x238 pContextData     : 0x00070000 Void

 +0x23c pImageHeaderHash : (null)

 +0x240 TracingFlags     : 0

 +0x240 HeapTracingEnabled : 0y0

 +0x240 CritSecTracingEnabled : 0y0

 +0x240 SpareTracingBits : 0y000000000000000000000000000000 (0)


우리가 관심 있는 부분은 다음과 같습니다.



+0x088 NumberOfHeaps    : 7

.

+0x090 ProcessHeaps     : 0x77eb4760  -> 0x002d0000 Void


ProcessHeaps Heap 구조를 가리키는 포인터 배열을 가리키고 있습니다. (힙 당 포인터 1개)

 

포인터 배열을 살펴 보면 다음과 같습니다.


0:001> dd 0x77eb4760

 77eb4760  002d0000 005b0000 01e30000 01f90000

 77eb4770  02160000 02650000 02860000 00000000

 77eb4780  00000000 00000000 00000000 00000000

 77eb4790  00000000 00000000 00000000 00000000

 77eb47a0  00000000 00000000 00000000 00000000

 77eb47b0  00000000 00000000 00000000 00000000

 77eb47c0  00000000 00000000 00000000 00000000

 77eb47d0  00000000 00000000 00000000 00000000


첫 번째 힙 구조를 보면 다음과 같습니다.


0:001> dt _HEAP 2d0000

 ntdll!_HEAP

 +0x000 Entry            : _HEAP_ENTRY

 +0x008 SegmentSignature : 0xffeeffee

 +0x00c SegmentFlags     : 0

 +0x010 SegmentListEntry : _LIST_ENTRY [ 0x2d00a8 - 0x2d00a8 ]

 +0x018 Heap             : 0x002d0000 _HEAP

 +0x01c BaseAddress      : 0x002d0000 Void

 +0x020 NumberOfPages    : 0x100

 +0x024 FirstEntry       : 0x002d0588 _HEAP_ENTRY

 +0x028 LastValidEntry   : 0x003d0000 _HEAP_ENTRY

 +0x02c NumberOfUnCommittedPages : 0xd0

 +0x030 NumberOfUnCommittedRanges : 1

 +0x034 SegmentAllocatorBackTraceIndex : 0

 +0x036 Reserved         : 0

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

 +0x040 Flags            : 0x40000062

 +0x044 ForceFlags       : 0x40000060

 +0x048 CompatibilityFlags : 0

 +0x04c EncodeFlagMask   : 0x100000

 +0x050 Encoding         : _HEAP_ENTRY

 +0x058 PointerKey       : 0x7d37bf2e

 +0x05c Interceptor      : 0

 +0x060 VirtualMemoryThreshold : 0xfe00

 +0x064 Signature        : 0xeeffeeff

 +0x068 SegmentReserve   : 0x100000

 +0x06c SegmentCommit    : 0x2000

 +0x070 DeCommitFreeBlockThreshold : 0x200

 +0x074 DeCommitTotalFreeThreshold : 0x2000

 +0x078 TotalFreeSize    : 0x1b01

 +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 [ 0x2fffe8 - 0x2fffe8 ]

 +0x098 AlignRound       : 0x17

 +0x09c AlignMask        : 0xfffffff8

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

 +0x0a8 SegmentList      : _LIST_ENTRY [ 0x2d0010 - 0x2d0010 ]

 +0x0b0 AllocatorBackTraceIndex : 0

 +0x0b4 NonDedicatedListLength : 0

 +0x0b8 BlocksIndex      : 0x002d0150 Void

 +0x0bc UCRIndex         : 0x002d0590 Void

 +0x0c0 PseudoTagEntries : (null)

 +0x0c4 FreeLists        : _LIST_ENTRY [ 0x2f0a60 - 0x2f28a0 ]

 +0x0cc LockVariable     : 0x002d0138 _HEAP_LOCK

 +0x0d0 CommitRoutine    : 0x7d37bf2e     long  +7d37bf2e

 +0x0d4 FrontEndHeap     : (null)

 +0x0d8 FrontHeapLockCount : 0

 +0x0da FrontEndHeapType : 0 ''

 +0x0dc Counters         : _HEAP_COUNTERS

 +0x130 TuningParameters : _HEAP_TUNING_PARAMETERS


mona.py 를 이용하면 유용한 정보들을 얻을 수 있습니다먼저 일반적인 정보를 살펴 보면 다음과 같습니다.


0:003> !py mona heap

Hold on...

[+] Command used:

!py mona.py heap

Peb : 0x7efde000, NtGlobalFlag : 0x00000070

Heaps:

------

0x005a0000 (1 segment(s) : 0x005a0000) * Default process heap  Encoding key: 0x171f4fc1

0x00170000 (2 segment(s) : 0x00170000,0x045a0000)   Encoding key: 0x21f9a301

0x00330000 (1 segment(s) : 0x00330000)   Encoding key: 0x1913b812

0x001d0000 (2 segment(s) : 0x001d0000,0x006a0000)   Encoding key: 0x547202aa

0x020c0000 (1 segment(s) : 0x020c0000)   Encoding key: 0x0896f86d

0x02c50000 (1 segment(s) : 0x02c50000)   Encoding key: 0x21f9a301

0x02b10000 (2 segment(s) : 0x02b10000,0x04450000)   Encoding key: 0x757121ce


Please specify a valid searchtype -t

Valid values are :

   lal

   lfh

   all

   segments

   chunks

   layout

   fea

   bea


[+] This mona.py action took 0:00:00.012000


보시다시피 7개의 힙이 있음을 보여주며 mona 에서는 각각의 힙에 대한 세그먼트들을 보여줍니다.

 

이는 !heap 명령을 통해서도 확인할 수 있습니다.


0:003> !heap -m

 Index   Address  Name      Debugging options enabled

 1:   005a0000

 Segment at 005a0000 to 006a0000 (0005f000 bytes committed)

 2:   00170000

 Segment at 00170000 to 00180000 (00010000 bytes committed)

 Segment at 045a0000 to 046a0000 (0000b000 bytes committed)

 3:   00330000

 Segment at 00330000 to 00370000 (00006000 bytes committed)

 4:   001d0000

 Segment at 001d0000 to 001e0000 (0000b000 bytes committed)

 Segment at 006a0000 to 007a0000 (0002e000 bytes committed)

 5:   020c0000

 Segment at 020c0000 to 02100000 (00001000 bytes committed)

 6:   02c50000

 Segment at 02c50000 to 02c90000 (00025000 bytes committed)

 7:   02b10000

 Segment at 02b10000 to 02b20000 (0000e000 bytes committed)

 Segment at 04450000 to 04550000 (00033000 bytes committed)


옵션 –m  세그먼트들을 포함하여 보여줍니다.

 

특정 힙 (0x5a0000)의 세그먼트를 확인하고 싶다면 다음과 같이 입력하면 됩니다.


0:003> !py mona heap -h 5a0000 -t segments

Hold on...

[+] Command used:

!py mona.py heap -h 5a0000 -t segments

Peb : 0x7efde000, NtGlobalFlag : 0x00000070

Heaps:

------

0x005a0000 (1 segment(s) : 0x005a0000) * Default process heap  Encoding key: 0x171f4fc1

0x00170000 (2 segment(s) : 0x00170000,0x045a0000)   Encoding key: 0x21f9a301

0x00330000 (1 segment(s) : 0x00330000)   Encoding key: 0x1913b812

0x001d0000 (2 segment(s) : 0x001d0000,0x006a0000)   Encoding key: 0x547202aa

0x020c0000 (1 segment(s) : 0x020c0000)   Encoding key: 0x0896f86d

0x02c50000 (1 segment(s) : 0x02c50000)   Encoding key: 0x21f9a301

0x02b10000 (2 segment(s) : 0x02b10000,0x04450000)   Encoding key: 0x757121ce



[+] Processing heap 0x005a0000

Segment List for heap 0x005a0000:

---------------------------------

Segment 0x005a0588 - 0x006a0000 (FirstEntry: 0x005a0588 - LastValidEntry: 0x006a0000): 0x000ffa78 bytes


[+] This mona.py action took 0:00:00.014000


mona 에서는 우리가 요청한 특정 정보에 대해 모든 힙들에 대한 정보를 요약해줍니다모든 힙들의 세그먼트 리스트를 얻기 위해서는 –h 5a0000을 빼도 가능합니다.


0:003> !py mona heap -t segments

Hold on...

[+] Command used:

!py mona.py heap -t segments

Peb : 0x7efde000, NtGlobalFlag : 0x00000070

Heaps:

------

0x005a0000 (1 segment(s) : 0x005a0000) * Default process heap  Encoding key: 0x171f4fc1

0x00170000 (2 segment(s) : 0x00170000,0x045a0000)   Encoding key: 0x21f9a301

0x00330000 (1 segment(s) : 0x00330000)   Encoding key: 0x1913b812

0x001d0000 (2 segment(s) : 0x001d0000,0x006a0000)   Encoding key: 0x547202aa

0x020c0000 (1 segment(s) : 0x020c0000)   Encoding key: 0x0896f86d

0x02c50000 (1 segment(s) : 0x02c50000)   Encoding key: 0x21f9a301

0x02b10000 (2 segment(s) : 0x02b10000,0x04450000)   Encoding key: 0x757121ce



[+] Processing heap 0x005a0000

Segment List for heap 0x005a0000:

---------------------------------

Segment 0x005a0588 - 0x006a0000 (FirstEntry: 0x005a0588 - LastValidEntry: 0x006a0000): 0x000ffa78 bytes


[+] Processing heap 0x00170000

Segment List for heap 0x00170000:

---------------------------------

Segment 0x00170588 - 0x00180000 (FirstEntry: 0x00170588 - LastValidEntry: 0x00180000): 0x0000fa78 bytes

Segment 0x045a0000 - 0x046a0000 (FirstEntry: 0x045a0040 - LastValidEntry: 0x046a0000): 0x00100000 bytes


[+] Processing heap 0x00330000

Segment List for heap 0x00330000:

---------------------------------

Segment 0x00330588 - 0x00370000 (FirstEntry: 0x00330588 - LastValidEntry: 0x00370000): 0x0003fa78 bytes


[+] Processing heap 0x001d0000

Segment List for heap 0x001d0000:

---------------------------------

Segment 0x001d0588 - 0x001e0000 (FirstEntry: 0x001d0588 - LastValidEntry: 0x001e0000): 0x0000fa78 bytes

Segment 0x006a0000 - 0x007a0000 (FirstEntry: 0x006a0040 - LastValidEntry: 0x007a0000): 0x00100000 bytes


[+] Processing heap 0x020c0000

Segment List for heap 0x020c0000:

---------------------------------

Segment 0x020c0588 - 0x02100000 (FirstEntry: 0x020c0588 - LastValidEntry: 0x02100000): 0x0003fa78 bytes


[+] Processing heap 0x02c50000

Segment List for heap 0x02c50000:

---------------------------------

Segment 0x02c50588 - 0x02c90000 (FirstEntry: 0x02c50588 - LastValidEntry: 0x02c90000): 0x0003fa78 bytes


[+] Processing heap 0x02b10000

Segment List for heap 0x02b10000:

---------------------------------

Segment 0x02b10588 - 0x02b20000 (FirstEntry: 0x02b10588 - LastValidEntry: 0x02b20000): 0x0000fa78 bytes

Segment 0x04450000 - 0x04550000 (FirstEntry: 0x04450040 - LastValidEntry: 0x04550000): 0x00100000 bytes


[+] This mona.py action took 0:00:00.017000


mona.py 는 메모리 청크들의 할당된 블록을 호출합니다사용되고 있는 힙에 대한 세그먼트들의 청크를 보고 싶다면 다음과 같이 입력하면 됩니다.


0:003> !py mona heap -h 5a0000 -t chunks

Hold on...

[+] Command used:

!py mona.py heap -h 5a0000 -t chunks

Peb : 0x7efde000, NtGlobalFlag : 0x00000070

Heaps:

------

0x005a0000 (1 segment(s) : 0x005a0000) * Default process heap  Encoding key: 0x171f4fc1

0x00170000 (2 segment(s) : 0x00170000,0x045a0000)   Encoding key: 0x21f9a301

0x00330000 (1 segment(s) : 0x00330000)   Encoding key: 0x1913b812

0x001d0000 (2 segment(s) : 0x001d0000,0x006a0000)   Encoding key: 0x547202aa

0x020c0000 (1 segment(s) : 0x020c0000)   Encoding key: 0x0896f86d

0x02c50000 (1 segment(s) : 0x02c50000)   Encoding key: 0x21f9a301

0x02b10000 (2 segment(s) : 0x02b10000,0x04450000)   Encoding key: 0x757121ce


[+] Preparing output file 'heapchunks.txt'

    - (Re)setting logfile heapchunks.txt

[+] Generating module info table, hang on...

    - Processing modules

    - Done. Let's rock 'n roll.


[+] Processing heap 0x005a0000

Segment List for heap 0x005a0000:

---------------------------------

Segment 0x005a0588 - 0x006a0000 (FirstEntry: 0x005a0588 - LastValidEntry: 0x006a0000): 0x000ffa78 bytes

    Nr of chunks : 2237 

    _HEAP_ENTRY  psize   size  unused  UserPtr   UserSize

       005a0588  00000  00250   00001  005a0590  0000024f (591) (Fill pattern,Extra present,Busy) 

       005a07d8  00250  00030   00018  005a07e0  00000018 (24) (Fill pattern,Extra present,Busy) 

       005a0808  00030  00bb8   0001a  005a0810  00000b9e (2974) (Fill pattern,Extra present,Busy) 

       005a13c0  00bb8  01378   0001c  005a13c8  0000135c (4956) (Fill pattern,Extra present,Busy) 

       005a2738  01378  00058   0001c  005a2740  0000003c (60) (Fill pattern,Extra present,Busy) 

       005a2790  00058  00048   00018  005a2798  00000030 (48) (Fill pattern,Extra present,Busy) 

       005a27d8  00048  00090   00018  005a27e0  00000078 (120) (Fill pattern,Extra present,Busy) 

       005a2868  00090  00090   00018  005a2870  00000078 (120) (Fill pattern,Extra present,Busy) 

       005a28f8  00090  00058   0001c  005a2900  0000003c (60) (Fill pattern,Extra present,Busy) 

       005a2950  00058  00238   00018  005a2958  00000220 (544) (Fill pattern,Extra present,Busy) 

       005a2b88  00238  00060   0001e  005a2b90  00000042 (66) (Fill pattern,Extra present,Busy) 

       <snip>

       005ec530  00038  00048   0001c  005ec538  0000002c (44) (Fill pattern,Extra present,Busy) 

       005ec578  00048  12a68   00000  005ec580  00012a68 (76392) (Fill pattern) 

       005fefe0  12a68  00020   00003  005fefe8  0000001d (29) (Busy) 

       0x005feff8 - 0x006a0000 (end of segment) : 0xa1008 (659464) uncommitted bytes


Heap : 0x005a0000 : VirtualAllocdBlocks : 0 

    Nr of chunks : 0 


[+] This mona.py action took 0:00:02.804000


또는 !heap 을 통해서도 볼 수 있습니다.


0:003> !heap -h 5a0000

Index   Address  Name      Debugging options enabled

1:   005a0000

Segment at 005a0000 to 006a0000 (0005f000 bytes committed)

Flags:                40000062

ForceFlags:           40000060

Granularity:          8 bytes

Segment Reserve:      00100000

Segment Commit:       00002000

DeCommit Block Thres: 00000200

DeCommit Total Thres: 00002000

Total Free Size:      00002578

Max. Allocation Size: 7ffdefff

Lock Variable at:     005a0138

Next TagIndex:        0000

Maximum TagIndex:     0000

Tag Entries:          00000000

PsuedoTag Entries:    00000000

Virtual Alloc List:   005a00a0

Uncommitted ranges:   005a0090

FreeList[ 00 ] at 005a00c4: 005ec580 . 005e4f28   (18 blocks)


Heap entries for Segment00 in Heap 005a0000

address: psize . size  flags   state (requested size)

005a0000: 00000 . 00588 [101] - busy (587)

005a0588: 00588 . 00250 [107] - busy (24f), tail fill

005a07d8: 00250 . 00030 [107] - busy (18), tail fill

005a0808: 00030 . 00bb8 [107] - busy (b9e), tail fill

005a13c0: 00bb8 . 01378 [107] - busy (135c), tail fill

005a2738: 01378 . 00058 [107] - busy (3c), tail fill

005a2790: 00058 . 00048 [107] - busy (30), tail fill

005a27d8: 00048 . 00090 [107] - busy (78), tail fill

005a2868: 00090 . 00090 [107] - busy (78), tail fill

005a28f8: 00090 . 00058 [107] - busy (3c), tail fill

005a2950: 00058 . 00238 [107] - busy (220), tail fill

005a2b88: 00238 . 00060 [107] - busy (42), tail fill

<snip>

005ec530: 00038 . 00048 [107] - busy (2c), tail fill

005ec578: 00048 . 12a68 [104] free fill

005fefe0: 12a68 . 00020 [111] - busy (1d)

005ff000:      000a1000      - uncommitted bytes.


-stat 옵션을 이용하면 몇몇 통계를 확인할 수 있습니다.


0:003> !py mona heap -h 5a0000 -t chunks -stat

Hold on...

[+] Command used:

!py mona.py heap -h 5a0000 -t chunks -stat

Peb : 0x7efde000, NtGlobalFlag : 0x00000070

Heaps:

------

0x005a0000 (1 segment(s) : 0x005a0000) * Default process heap  Encoding key: 0x171f4fc1

0x00170000 (2 segment(s) : 0x00170000,0x045a0000)   Encoding key: 0x21f9a301

0x00330000 (1 segment(s) : 0x00330000)   Encoding key: 0x1913b812

0x001d0000 (2 segment(s) : 0x001d0000,0x006a0000)   Encoding key: 0x547202aa

0x020c0000 (1 segment(s) : 0x020c0000)   Encoding key: 0x0896f86d

0x02c50000 (1 segment(s) : 0x02c50000)   Encoding key: 0x21f9a301

0x02b10000 (2 segment(s) : 0x02b10000,0x04450000)   Encoding key: 0x757121ce


[+] Preparing output file 'heapchunks.txt'

    - (Re)setting logfile heapchunks.txt

[+] Generating module info table, hang on...

    - Processing modules

    - Done. Let's rock 'n roll.


[+] Processing heap 0x005a0000

Segment List for heap 0x005a0000:

---------------------------------

Segment 0x005a0588 - 0x006a0000 (FirstEntry: 0x005a0588 - LastValidEntry: 0x006a0000): 0x000ffa78 bytes

    Nr of chunks : 2237 

    _HEAP_ENTRY  psize   size  unused  UserPtr   UserSize

    Segment Statistics:

    Size : 0x12a68 (76392) : 1 chunks (0.04 %)

    Size : 0x3980 (14720) : 1 chunks (0.04 %)

    Size : 0x135c (4956) : 1 chunks (0.04 %)

    Size : 0x11f8 (4600) : 1 chunks (0.04 %)

    Size : 0xb9e (2974) : 1 chunks (0.04 %)

    Size : 0xa28 (2600) : 1 chunks (0.04 %)

    <snip>

    Size : 0x6 (6) : 1 chunks (0.04 %)

    Size : 0x4 (4) : 15 chunks (0.67 %)

    Size : 0x1 (1) : 1 chunks (0.04 %)

    Total chunks : 2237



Heap : 0x005a0000 : VirtualAllocdBlocks : 0 

    Nr of chunks : 0 

Global statistics

  Size : 0x12a68 (76392) : 1 chunks (0.04 %)

  Size : 0x3980 (14720) : 1 chunks (0.04 %)

  Size : 0x135c (4956) : 1 chunks (0.04 %)

  Size : 0x11f8 (4600) : 1 chunks (0.04 %)

  Size : 0xb9e (2974) : 1 chunks (0.04 %)

  Size : 0xa28 (2600) : 1 chunks (0.04 %)

  <snip>

  Size : 0x6 (6) : 1 chunks (0.04 %)

  Size : 0x4 (4) : 15 chunks (0.67 %)

  Size : 0x1 (1) : 1 chunks (0.04 %)

  Total chunks : 2237


[+] This mona.py action took 0:00:02.415000


mona.py segments blocks/chunks에 있는 strings, BSTRINGs 그리고 vtable object를 확인할 수 있습니다해당 정보를 확인하려면 –t layout 옵션을 사용하면 됩니다이 명령어는 heaplayout.txt에 데이터를 쓰게 됩니다.

 

또한다음 옵션들도 사용할 수 있습니다.

  • -v: log window 데이터 쓰기
  • -fast: object 크기 제외
  • -size <sz>: <sz> 보다 작은 크기의 문자열 제외
  • -after <val>: <val>을 가리키는 문자열이나 vtable 나올 때 까지 다른건 무시현재 청크에 대한 모든 것은 출력


0:003> !py mona heap -h 5a0000 -t layout -v

Hold on...

[+] Command used:

!py mona.py heap -h 5a0000 -t layout -v

Peb : 0x7efde000, NtGlobalFlag : 0x00000070

Heaps:

------

0x005a0000 (1 segment(s) : 0x005a0000) * Default process heap  Encoding key: 0x171f4fc1

0x00170000 (2 segment(s) : 0x00170000,0x045a0000)   Encoding key: 0x21f9a301

0x00330000 (1 segment(s) : 0x00330000)   Encoding key: 0x1913b812

0x001d0000 (2 segment(s) : 0x001d0000,0x006a0000)   Encoding key: 0x547202aa

0x020c0000 (1 segment(s) : 0x020c0000)   Encoding key: 0x0896f86d

0x02c50000 (1 segment(s) : 0x02c50000)   Encoding key: 0x21f9a301

0x02b10000 (2 segment(s) : 0x02b10000,0x04450000)   Encoding key: 0x757121ce


[+] Preparing output file 'heaplayout.txt'

    - (Re)setting logfile heaplayout.txt

[+] Generating module info table, hang on...

    - Processing modules

    - Done. Let's rock 'n roll.


[+] Processing heap 0x005a0000

----- Heap 0x005a0000, Segment 0x005a0588 - 0x006a0000 (1/1) -----

Chunk 0x005a0588 (Usersize 0x24f, ChunkSize 0x250) : Fill pattern,Extra present,Busy

Chunk 0x005a07d8 (Usersize 0x18, ChunkSize 0x30) : Fill pattern,Extra present,Busy

Chunk 0x005a0808 (Usersize 0xb9e, ChunkSize 0xbb8) : Fill pattern,Extra present,Busy

  +03a3 @ 005a0bab->005a0d73 : Unicode (0x1c6/454 bytes, 0xe3/227 chars) : Path=C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86\winext\arcade;C:\Program Files (x86)\NVID...

  +00ec @ 005a0e5f->005a0eef : Unicode (0x8e/142 bytes, 0x47/71 chars) : PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 60 Stepping 3, GenuineIntel

  +0160 @ 005a104f->005a10d1 : Unicode (0x80/128 bytes, 0x40/64 chars) : PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\

  +0234 @ 005a1305->005a1387 : Unicode (0x80/128 bytes, 0x40/64 chars) : WINDBG_DIR=C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86

Chunk 0x005a13c0 (Usersize 0x135c, ChunkSize 0x1378) : Fill pattern,Extra present,Busy

  +04a7 @ 005a1867->005a1ab5 : Unicode (0x24c/588 bytes, 0x126/294 chars) : C:\Windows\System32;;C:\Windows\system32;C:\Windows\system;C:\Windows;.;C:\Program Files (x86)\Windo...

  +046c @ 005a1f21->005a20e9 : Unicode (0x1c6/454 bytes, 0xe3/227 chars) : Path=C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86\winext\arcade;C:\Program Files (x86)\NVID...

  +00ec @ 005a21d5->005a2265 : Unicode (0x8e/142 bytes, 0x47/71 chars) : PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 60 Stepping 3, GenuineIntel

  +0160 @ 005a23c5->005a2447 : Unicode (0x80/128 bytes, 0x40/64 chars) : PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\

  +0234 @ 005a267b->005a26fd : Unicode (0x80/128 bytes, 0x40/64 chars) : WINDBG_DIR=C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86

Chunk 0x005a2738 (Usersize 0x3c, ChunkSize 0x58) : Fill pattern,Extra present,Busy

Chunk 0x005a2790 (Usersize 0x30, ChunkSize 0x48) : Fill pattern,Extra present,Busy

<snip>

Chunk 0x005ec4b0 (Usersize 0x30, ChunkSize 0x48) : Fill pattern,Extra present,Busy

Chunk 0x005ec4f8 (Usersize 0x20, ChunkSize 0x38) : Fill pattern,Extra present,Busy

Chunk 0x005ec530 (Usersize 0x2c, ChunkSize 0x48) : Fill pattern,Extra present,Busy

Chunk 0x005ec578 (Usersize 0x12a68, ChunkSize 0x12a68) : Fill pattern

Chunk 0x005fefe0 (Usersize 0x1d, ChunkSize 0x20) : Busy


위 출력에서 나온 2줄은 다음과 같습니다.


Chunk 0x005a0808 (Usersize 0xb9e, ChunkSize 0xbb8) : Fill pattern,Extra present,Busy

 +03a3 @ 005a0bab->005a0d73 : Unicode (0x1c6/454 bytes, 0xe3/227 chars) : Path=C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86\winext\arcade;C:\Program Files (x86)\NVID...


두 번째 줄은 다음을 뜻합니다.

  1. 엔트리는 청크의 시작점에서 3a3 바이트에 위치해 있음
  2. 엔트리는 5a0bab 에서 5a0d73 에 있음
  3. 엔트리는 Unicode string으로 454 바이트 또는 227 문자열을 갖음
  4. 문자열은 “Path=C:\Program Files (x86)\Windows Kits\...” (생략을 갖음


댓글