What's the meaning of "Internal" in "!heap -h" output in windbg? What's the meaning of "Internal" in "!heap -h" output in windbg? windows windows

What's the meaning of "Internal" in "!heap -h" output in windbg?


TL;DR: Heap blocks marked as "internal" have a special flag in _HEAP_ENTRY.Flags

[edit] revised my previous answer with a proper answer.


Here's my guess attempt to your question.

According to the windbg help, the "!heap" command code is located in exts.dll (i.e. \winxp\exts.dll).

Put this DLL on IDA and downloaded symbols for it. There’s only one occurrence of "Internal" in the DLL, inside the DumpHeapEntry() function :

.text:0192463D                 movzx   eax, byte_1963152.text:01924644                 test    eax, eax.text:01924646                 jz      short loc_1924656.text:01924648                 push    offset aInternal ; " Internal ".text:0192464D                 call    _ExtensionApis.lpOutputRoutine ; some sort of printf routine

The output of "Internal" is therefore conditioned by the value of byte_1963152 : if byte_1963152 is not 0, then "Internal" is printed.Only once occurrence of write value with anything else than 0 happens (in ReadHeapEntry() which is called at the start of DumpHeapEntry() ):

.text:0191F025                 movzx   eax, [ebp+var_B].text:0191F029                 and     eax, 8.text:0191F02C                 jz      short loc_191F035.text:0191F02E                 mov     byte_1963152, 1

This translates to:

if((UINT)var_B & 8)    byte_1963152 = 1;

var_B is set here :

text:0191EFF7                 mov     eax, [ebp+var_18].text:0191EFFA                 mov     edx, [ebp+var_14].text:0191EFFD                 mov     cl, 10h          ; shift right by 0x10 bits.text:0191EFFF                 call    __aullshr.text:0191F004                 mov     [ebp+var_B], al

__aullshr stands for "Arithmetic Unsigned Long Long Shift Right". In the above code eax is the low 32-bit part of a 64-bit unsigned long long, while edx is the high 32-bit part.Notice that var_B is a 8-bit quantity ('al' register is used).

Hence:

// where var_14_18 is a combination (64-bit) of var_14 and var_18var_B = (char)(var_14_18 >> 0x10 );

var_14 and var_18 are set here :

.text:0191EF01                 push    0.text:0191EF03                 push    offset aAgregatecode ; "AgregateCode".text:0191EF08                 push    0.text:0191EF0A                 push    0.text:0191EF0C                 call    _GetShortField@16 ; GetShortField(x,x,x,x).text:0191EF11                 mov     [ebp+var_18], eax  ; high part.text:0191EF14                 mov     [ebp+var_14], edx  ; low part; cut.text:0191EF28                 mov     ecx, [ebp+var_18].text:0191EF2B                 and     ecx, _EncodeFlagMask ; from HEAP.EncodeFlagMask.text:0191EF31                 jz      short loc_191EF75.text:0191EF33                 mov     edx, [ebp+var_18].text:0191EF36                 xor     edx, _CrtHeapCode ; from HEAP.Encoding.Code1.text:0191EF3C                 mov     eax, [ebp+var_14].text:0191EF3F                 xor     eax, dword_1963194 ; from HEAP.Encoding.Code2.text:0191EF45                 mov     [ebp+var_18], edx.text:0191EF48                 mov     [ebp+var_14], eax    

So, windbg use the GetShortField() function on "AgregateCode" and sets both of the aforementioned variable (which is also a single unsigned long long value).Note that it also uses the HEAP.Encoding.Code1 and HEAP.Encoding.Code2 to XOR both of the value (HEAP is the the current heap from which the heap entry is a part).

"AgregateCode" is a field of both HEAP_ENTRY and HEAP_FREE_ENTRY structures (from Win 8.1 x86):

0:000> dt _heap_entry -r2ntdll!_HEAP_ENTRY   +0x000 Size             : Uint2B   +0x002 Flags            : UChar   +0x003 SmallTagIndex    : UChar   +0x000 SubSegmentCode   : Uint4B   +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   +0x004 Code234          : Uint4B   +0x000 AgregateCode     : Uint8B

This translated to C, gives:

          typedef struct _HEAP_ENTRY                       // 20 elements, 0x8 bytes (sizeof)           {                                                                                                 union                                        // 6 elements, 0x8 bytes (sizeof)                {                                                                                                 struct                                   // 3 elements, 0x8 bytes (sizeof)                    {                                                                           /*0x000*/             UINT16       Size;                                                      /*0x002*/             UINT8        Flags;                                                     /*0x003*/             UINT8        SmallTagIndex;                                             /*0x004*/             UINT8        _PADDING0_[0x4];                                                             };                                                                                            struct                                   // 4 elements, 0x8 bytes (sizeof)                    {                                                                           /*0x000*/             ULONG32      SubSegmentCode;                                            /*0x004*/             UINT16       PreviousSize;                                                                    union                                // 2 elements, 0x1 bytes (sizeof)                        {                                                                       /*0x006*/                 UINT8        SegmentOffset;                                         /*0x006*/                 UINT8        LFHFlags;                                                                    };                                                                      /*0x007*/             UINT8        UnusedBytes;                                                                 };                                                                                            struct                                   // 2 elements, 0x8 bytes (sizeof)                    {                                                                           /*0x000*/             UINT16       FunctionIndex;                                             /*0x002*/             UINT16       ContextValue;                                              /*0x004*/             UINT8        _PADDING1_[0x4];                                                             };                                                                                            struct                                   // 4 elements, 0x8 bytes (sizeof)                    {                                                                           /*0x000*/             ULONG32      InterceptorValue;                                          /*0x004*/             UINT16       UnusedBytesLength;                                         /*0x006*/             UINT8        EntryOffset;                                               /*0x007*/             UINT8        ExtendedBlockSignature;                                                      };                                                                                            struct                                   // 2 elements, 0x8 bytes (sizeof)                    {                                                                           /*0x000*/             ULONG32      Code1;                                                                           union                                // 2 elements, 0x4 bytes (sizeof)                        {                                                                                                 struct                           // 3 elements, 0x4 bytes (sizeof)                            {                                                                   /*0x004*/                     UINT16       Code2;                                             /*0x006*/                     UINT8        Code3;                                             /*0x007*/                     UINT8        Code4;                                                                       };                                                                  /*0x004*/                 ULONG32      Code234;                                                                     };                                                                                        };                                                                          /*0x000*/         UINT64       AgregateCode;                                                                };                                                                                        }HEAP_ENTRY, *PHEAP_ENTRY;

Thus we have the following pseudo-code (minus some other checks):

high_part, low_part = GetShortField(0,0,"AgregateCode", 0);high_part ^= HEAP.Encoding.Code1;low_part ^= HEAP.Encoding.Code2;AgregateCode = Make64BitFromTwo32Bit(high_part, low_part);    char var_B = (char)(AgregateCode >> 0x10);if(var_B & 8)    printf("Internal");

Given that "AgregateCode" is ... well, an aggregate of Code1 to Code 4 :

                  struct                                   // 2 elements, 0x8 bytes (sizeof)                    {                                                                           /*0x000*/             ULONG32      Code1;                                                                           union                                // 2 elements, 0x4 bytes (sizeof)                        {                                                                                                 struct                           // 3 elements, 0x4 bytes (sizeof)                            {                                                                   /*0x004*/                     UINT16       Code2;                                             /*0x006*/                     UINT8        Code3;                                             /*0x007*/                     UINT8        Code4;                                                                       };                                                                  /*0x004*/                 ULONG32      Code234;                                                                     };                                                                                        };                                                                          /*0x000*/         UINT64       AgregateCode; 

If you shift 0x10 and AND 8 the AgregateCode field you end up finally testing the 11th bit (start counting at 0) of Code1.

As the structure is a big union, you finally end up testing: _HEAP_ENTRY.Flags

It happens that a heap flag has already the value 8, its name is: HEAP_ENTRY_VIRTUAL_ALLOC

http://doxygen.reactos.org/da/ddb/heap_8h_source.html#l00044

https://os-design.googlecode.com/svn/trunk/ntos/inc/heap.h

It seems that this flag is used to manage big allocations, although those blocks are used internally by the system and not available directly to the end user.

Typically such internal blocks have Flags member set to 9: HEAP_ENTRY_VIRTUAL_ALLOC | HEAP_ENTRY_BUSY

[edit] Example :

Say I have a heap at 0x005b0000 :

0:004> !heap -hIndex   Address  Name      Debugging options enabled  1:   005b0000 

This heap (_HEAP) has a HEAP_ENTRY marked as "Internal" at 0x005b8d00:

0:004> !heap -h 005b0000Index   Address  Name      Debugging options enabled  1:   005b0000     Segment at 005b0000 to 006b0000 (0009d000 bytes committed)    Flags:                00000002    ForceFlags:           00000000    Granularity:          8 bytes    Segment Reserve:      00100000    Segment Commit:       00002000    DeCommit Block Thres: 00000800    DeCommit Total Thres: 00002000    Total Free Size:      00001ae8    Max. Allocation Size: 7ffdefff    Lock Variable at:     005b0138    Next TagIndex:        0000    Maximum TagIndex:     0000    Tag Entries:          00000000    PsuedoTag Entries:    00000000    Virtual Alloc List:   005b00a0    Uncommitted ranges:   005b0090    FreeList[ 00 ] at 005b00c4: 0063fbc0 . 00633060   (7 blocks)    Heap entries for Segment00 in Heap 005b0000        005b0000: 00000 . 00588 [101] - busy (587)        //[cut]        005b8d00: 03d20 . 378b0 [101] - busy (378a8) Internal   

A detailed view of the HEAP structure (notice the "Encoding" structure (_HEAP_ENTRY) at offset 0x50 which helps to decode the encoded heap entry with an XOR):

0:004> dt _heap 005b0000 -r1ntdll!_HEAP   +0x000 Entry            : _HEAP_ENTRY      +0x000 Size             : 0xbe38      +0x002 Flags            : 0xf5 ''      +0x003 SmallTagIndex    : 0xff ''      +0x000 SubSegmentCode   : 0xfff5be38       +0x004 PreviousSize     : 0xcf53      +0x006 SegmentOffset    : 0 ''      +0x006 LFHFlags         : 0 ''      +0x007 UnusedBytes      : 0x1 ''      +0x000 FunctionIndex    : 0xbe38      +0x002 ContextValue     : 0xfff5      +0x000 InterceptorValue : 0xfff5be38      +0x004 UnusedBytesLength : 0xcf53      +0x006 EntryOffset      : 0 ''      +0x007 ExtendedBlockSignature : 0x1 ''      +0x000 Code1            : 0xfff5be38      +0x004 Code2            : 0xcf53      +0x006 Code3            : 0 ''      +0x007 Code4            : 0x1 ''      +0x000 AgregateCode     : 0x100cf53`fff5be38   +0x008 SegmentSignature : 0xffeeffee   +0x00c SegmentFlags     : 0   +0x010 SegmentListEntry : _LIST_ENTRY [ 0x5b00a8 - 0x5b00a8 ]      +0x000 Flink            : 0x005b00a8 _LIST_ENTRY [ 0x5b0010 - 0x5b0010 ]      +0x004 Blink            : 0x005b00a8 _LIST_ENTRY [ 0x5b0010 - 0x5b0010 ]   +0x018 Heap             : 0x005b0000 _HEAP      +0x000 Entry            : _HEAP_ENTRY      +0x008 SegmentSignature : 0xffeeffee      +0x00c SegmentFlags     : 0      +0x010 SegmentListEntry : _LIST_ENTRY [ 0x5b00a8 - 0x5b00a8 ]      +0x018 Heap             : 0x005b0000 _HEAP      +0x01c BaseAddress      : 0x005b0000       +0x020 NumberOfPages    : 0x100      +0x024 FirstEntry       : 0x005b0588 _HEAP_ENTRY      +0x028 LastValidEntry   : 0x006b0000 _HEAP_ENTRY      +0x02c NumberOfUnCommittedPages : 0x63      +0x030 NumberOfUnCommittedRanges : 1      +0x034 SegmentAllocatorBackTraceIndex : 0      +0x036 Reserved         : 0      +0x038 UCRSegmentList   : _LIST_ENTRY [ 0x64cff0 - 0x64cff0 ]      +0x040 Flags            : 2      +0x044 ForceFlags       : 0      +0x048 CompatibilityFlags : 0      +0x04c EncodeFlagMask   : 0x100000      +0x050 Encoding         : _HEAP_ENTRY      +0x058 PointerKey       : 0x75c3a7b      +0x05c Interceptor      : 0      +0x060 VirtualMemoryThreshold : 0xfe00      +0x064 Signature        : 0xeeffeeff      +0x068 SegmentReserve   : 0x100000      +0x06c SegmentCommit    : 0x2000      +0x070 DeCommitFreeBlockThreshold : 0x800      +0x074 DeCommitTotalFreeThreshold : 0x2000      +0x078 TotalFreeSize    : 0x1ae8      +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 [ 0x64cfe8 - 0x64cfe8 ]      +0x098 AlignRound       : 0xf      +0x09c AlignMask        : 0xfffffff8      +0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0x5b00a0 - 0x5b00a0 ]      +0x0a8 SegmentList      : _LIST_ENTRY [ 0x5b0010 - 0x5b0010 ]      +0x0b0 AllocatorBackTraceIndex : 0      +0x0b4 NonDedicatedListLength : 0      +0x0b8 BlocksIndex      : 0x005b0150       +0x0bc UCRIndex         : 0x005b0590       +0x0c0 PseudoTagEntries : (null)       +0x0c4 FreeLists        : _LIST_ENTRY [ 0x633060 - 0x63fbc0 ]      +0x0cc LockVariable     : 0x005b0138 _HEAP_LOCK      +0x0d0 CommitRoutine    : 0x075c3a7b        long  +75c3a7b      +0x0d4 FrontEndHeap     : 0x005b8d08       +0x0d8 FrontHeapLockCount : 0      +0x0da FrontEndHeapType : 0x2 ''      +0x0dc Counters         : _HEAP_COUNTERS      +0x130 TuningParameters : _HEAP_TUNING_PARAMETERS   +0x01c BaseAddress      : 0x005b0000    +0x020 NumberOfPages    : 0x100   +0x024 FirstEntry       : 0x005b0588 _HEAP_ENTRY      +0x000 Size             : 0xbec1      +0x002 Flags            : 0xf5 ''      +0x003 SmallTagIndex    : 0x6 ''      +0x000 SubSegmentCode   : 0x06f5bec1       +0x004 PreviousSize     : 0xcfe2      +0x006 SegmentOffset    : 0 ''      +0x006 LFHFlags         : 0 ''      +0x007 UnusedBytes      : 0x1 ''      +0x000 FunctionIndex    : 0xbec1      +0x002 ContextValue     : 0x6f5      +0x000 InterceptorValue : 0x6f5bec1      +0x004 UnusedBytesLength : 0xcfe2      +0x006 EntryOffset      : 0 ''      +0x007 ExtendedBlockSignature : 0x1 ''      +0x000 Code1            : 0x6f5bec1      +0x004 Code2            : 0xcfe2      +0x006 Code3            : 0 ''      +0x007 Code4            : 0x1 ''      +0x000 AgregateCode     : 0x100cfe2`06f5bec1   +0x028 LastValidEntry   : 0x006b0000 _HEAP_ENTRY      +0x000 Size             : 0xeff8      +0x002 Flags            : 0xe7 ''      +0x003 SmallTagIndex    : 0xff ''      +0x000 SubSegmentCode   : 0xffe7eff8       +0x004 PreviousSize     : 0xd3df      +0x006 SegmentOffset    : 0xc7 ''      +0x006 LFHFlags         : 0xc7 ''      +0x007 UnusedBytes      : 0xff ''      +0x000 FunctionIndex    : 0xeff8      +0x002 ContextValue     : 0xffe7      +0x000 InterceptorValue : 0xffe7eff8      +0x004 UnusedBytesLength : 0xd3df      +0x006 EntryOffset      : 0xc7 ''      +0x007 ExtendedBlockSignature : 0xff ''      +0x000 Code1            : 0xffe7eff8      +0x004 Code2            : 0xd3df      +0x006 Code3            : 0xc7 ''      +0x007 Code4            : 0xff ''      +0x000 AgregateCode     : 0xffc7d3df`ffe7eff8   +0x02c NumberOfUnCommittedPages : 0x63   +0x030 NumberOfUnCommittedRanges : 1   +0x034 SegmentAllocatorBackTraceIndex : 0   +0x036 Reserved         : 0   +0x038 UCRSegmentList   : _LIST_ENTRY [ 0x64cff0 - 0x64cff0 ]      +0x000 Flink            : 0x0064cff0 _LIST_ENTRY [ 0x5b0038 - 0x5b0038 ]      +0x004 Blink            : 0x0064cff0 _LIST_ENTRY [ 0x5b0038 - 0x5b0038 ]   +0x040 Flags            : 2   +0x044 ForceFlags       : 0   +0x048 CompatibilityFlags : 0   +0x04c EncodeFlagMask   : 0x100000   +0x050 Encoding         : _HEAP_ENTRY      +0x000 Size             : 0xbe89      +0x002 Flags            : 0xf4 ''      +0x003 SmallTagIndex    : 0x4f 'O'      +0x000 SubSegmentCode   : 0x4ff4be89       +0x004 PreviousSize     : 0xcf53      +0x006 SegmentOffset    : 0 ''      +0x006 LFHFlags         : 0 ''      +0x007 UnusedBytes      : 0 ''      +0x000 FunctionIndex    : 0xbe89      +0x002 ContextValue     : 0x4ff4      +0x000 InterceptorValue : 0x4ff4be89      +0x004 UnusedBytesLength : 0xcf53      +0x006 EntryOffset      : 0 ''      +0x007 ExtendedBlockSignature : 0 ''      +0x000 Code1            : 0x4ff4be89      +0x004 Code2            : 0xcf53      +0x006 Code3            : 0 ''      +0x007 Code4            : 0 ''      +0x000 AgregateCode     : 0xcf53`4ff4be89   +0x058 PointerKey       : 0x75c3a7b   +0x05c Interceptor      : 0   +0x060 VirtualMemoryThreshold : 0xfe00   +0x064 Signature        : 0xeeffeeff   +0x068 SegmentReserve   : 0x100000   +0x06c SegmentCommit    : 0x2000   +0x070 DeCommitFreeBlockThreshold : 0x800   +0x074 DeCommitTotalFreeThreshold : 0x2000   +0x078 TotalFreeSize    : 0x1ae8   +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 [ 0x64cfe8 - 0x64cfe8 ]      +0x000 Flink            : 0x0064cfe8 _LIST_ENTRY [ 0x5b0090 - 0x5b0090 ]      +0x004 Blink            : 0x0064cfe8 _LIST_ENTRY [ 0x5b0090 - 0x5b0090 ]   +0x098 AlignRound       : 0xf   +0x09c AlignMask        : 0xfffffff8   +0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0x5b00a0 - 0x5b00a0 ]      +0x000 Flink            : 0x005b00a0 _LIST_ENTRY [ 0x5b00a0 - 0x5b00a0 ]      +0x004 Blink            : 0x005b00a0 _LIST_ENTRY [ 0x5b00a0 - 0x5b00a0 ]   +0x0a8 SegmentList      : _LIST_ENTRY [ 0x5b0010 - 0x5b0010 ]      +0x000 Flink            : 0x005b0010 _LIST_ENTRY [ 0x5b00a8 - 0x5b00a8 ]      +0x004 Blink            : 0x005b0010 _LIST_ENTRY [ 0x5b00a8 - 0x5b00a8 ]   +0x0b0 AllocatorBackTraceIndex : 0   +0x0b4 NonDedicatedListLength : 0   +0x0b8 BlocksIndex      : 0x005b0150    +0x0bc UCRIndex         : 0x005b0590    +0x0c0 PseudoTagEntries : (null)    +0x0c4 FreeLists        : _LIST_ENTRY [ 0x633060 - 0x63fbc0 ]      +0x000 Flink            : 0x00633060 _LIST_ENTRY [ 0x632fc8 - 0x5b00c4 ]      +0x004 Blink            : 0x0063fbc0 _LIST_ENTRY [ 0x5b00c4 - 0x633390 ]   +0x0cc LockVariable     : 0x005b0138 _HEAP_LOCK      +0x000 Lock             : <unnamed-tag>   +0x0d0 CommitRoutine    : 0x075c3a7b     long  +75c3a7b   +0x0d4 FrontEndHeap     : 0x005b8d08    +0x0d8 FrontHeapLockCount : 0   +0x0da FrontEndHeapType : 0x2 ''   +0x0dc Counters         : _HEAP_COUNTERS      +0x000 TotalMemoryReserved : 0x100000      +0x004 TotalMemoryCommitted : 0x9d000      +0x008 TotalMemoryLargeUCR : 0      +0x00c TotalSizeInVirtualBlocks : 0      +0x010 TotalSegments    : 1      +0x014 TotalUCRs        : 1      +0x018 CommittOps       : 0x19      +0x01c DeCommitOps      : 0      +0x020 LockAcquires     : 0xd37      +0x024 LockCollisions   : 0      +0x028 CommitRate       : 0x24      +0x02c DecommittRate    : 0xb      +0x030 CommitFailures   : 0      +0x034 InBlockCommitFailures : 0      +0x038 CompactHeapCalls : 0      +0x03c CompactedUCRs    : 0      +0x040 AllocAndFreeOps  : 0      +0x044 InBlockDeccommits : 0      +0x048 InBlockDeccomitSize : 0      +0x04c HighWatermarkSize : 0x9cde0      +0x050 LastPolledSize   : 0x8f9c8   +0x130 TuningParameters : _HEAP_TUNING_PARAMETERS      +0x000 CommittThresholdShift : 4      +0x004 MaxPreCommittThreshold : 0xfe000

Now a detailed view of the _HEAP_ENTRY (marked as internal). This is an encoded structure, which can be decoded by XORing it with _HEAP.Encoding member:

0:004> dt _heap_entry 005b8d00ntdll!_HEAP_ENTRY   +0x000 Size             : 0xd19f   +0x002 Flags            : 0xfd ''   +0x003 SmallTagIndex    : 0x3f '?'   +0x000 SubSegmentCode   : 0x3ffdd19f    +0x004 PreviousSize     : 0xc8f7   +0x006 SegmentOffset    : 0 ''   +0x006 LFHFlags         : 0 ''   +0x007 UnusedBytes      : 0x8 ''   +0x000 FunctionIndex    : 0xd19f   +0x002 ContextValue     : 0x3ffd   +0x000 InterceptorValue : 0x3ffdd19f   +0x004 UnusedBytesLength : 0xc8f7   +0x006 EntryOffset      : 0 ''   +0x007 ExtendedBlockSignature : 0x8 ''   +0x000 Code1            : 0x3ffdd19f   +0x004 Code2            : 0xc8f7   +0x006 Code3            : 0 ''   +0x007 Code4            : 0x8 ''   +0x000 AgregateCode     : 0x800c8f7`3ffdd19f          

Now the commented code :

1) Fetch Aggregate form HEAP_ENTRY
2) Decode (XOR) HEAP_ENTRY with HEAP.Encoding member
3) Shift result to get _HEAP_ENTRY.Flags
4) AND result with HEAP_ENTRY_VIRTUAL_ALLOC (8) to see if it's an internal block

CPU DisasmAddress     Command                                  Comments730AEF01    PUSH 0                                   ; /Arg4 = 0730AEF03    PUSH ??_C@_0N@BCMFEPJJ@AgregateCode?$AA@ ; |Arg3 = ASCII "AgregateCode"730AEF08    PUSH 0                                   ; |Arg2 = 0730AEF0A    PUSH 0                                   ; |Arg1 = 0730AEF0C    CALL GetShortField                       ; \exts.GetShortField730AEF11    MOV DWORD PTR SS:[LOCAL.6],EAX           ; low part = 0x3FFDD19F (_HEAP_ENTRY.Code1)730AEF14    MOV DWORD PTR SS:[LOCAL.5],EDX           ; high part = 0x0800C8F7730AEF17    MOV EDX,DWORD PTR SS:[LOCAL.6]730AEF1A    MOV DWORD PTR DS:[730F3158],EDX730AEF20    MOV EAX,DWORD PTR SS:[LOCAL.5]730AEF23    MOV DWORD PTR DS:[730F315C],EAX730AEF28    MOV ECX,DWORD PTR SS:[LOCAL.6]           ; 0x3FFDD19F730AEF2B    AND ECX,DWORD PTR DS:[EncodeFlagMask]    ; ecx = 0x3FFDD19F ^ 0x00100000 = 0x00100000730AEF31    JE SHORT 730AEF75730AEF33    MOV EDX,DWORD PTR SS:[LOCAL.6]           ; edx = 0x3FFDD19F730AEF36    XOR EDX,DWORD PTR DS:[CrtHeapCode]       ; edx = 0x3FFDD19F ^ 0x4FF4BE89 = 0x70096F16730AEF3C    MOV EAX,DWORD PTR SS:[LOCAL.5]           ; eax = 0x0800C8F7730AEF3F    XOR EAX,DWORD PTR DS:[730F3194]          ; eax = 0x0800C8F7 ^ 0xCF53 = 0x080007A4730AEF45    MOV DWORD PTR SS:[LOCAL.6],EDX           ; edx = 0x70096F16730AEF48    MOV DWORD PTR SS:[LOCAL.5],EAX           ; eax = 0x080007A4;[...]    730AEFEE    MOVZX EAX,WORD PTR SS:[LOCAL.6]730AEFF2    MOV DWORD PTR DS:[CrtHeapEntry],EAX      ; entry = 0x6f16730AEFF7    MOV EAX,DWORD PTR SS:[LOCAL.6]           ; low part = 0x70096F16730AEFFA    MOV EDX,DWORD PTR SS:[LOCAL.5]           ; high part = 0x080007A4730AEFFD    MOV CL,10730AEFFF    CALL _aullshr730AF004    MOV BYTE PTR SS:[LOCAL.3+1],AL           ; 0x00000800:07A47009 -> al = 9730AF007    MOVZX ECX,BYTE PTR SS:[LOCAL.3+1]730AF00B    AND ECX,FFFFFFE6730AF00E    OR ECX,DWORD PTR DS:[730F3148]730AF014    MOV DWORD PTR DS:[730F3148],ECX730AF01A    MOV EDX,DWORD PTR DS:[730F3148]730AF020    AND EDX,00000001730AF023    JE SHORT 730AF035730AF025    MOVZX EAX,BYTE PTR SS:[LOCAL.3+1]        ; eax = 9 730AF029    AND EAX,00000008                         ; 9 & 8 = 1730AF02C    JE SHORT 730AF035730AF02E    MOV BYTE PTR DS:[730F3152],1             ; set "Internal" flag

Hope it helps!


At least sometimes Internal means that the memory block corresponds to LFH heap entry.I have a windbg dump that reported lots of internal entries with !heap -h. However after applying !heap -hl windbg shows more detailed information like

        ...        0000000026ae0c70: 40000 . 40000 [101] - busy (3fff0) Internal         LFH data region at 0000000026ae0c80 (subsegment 00000000269c09c0):            0000000026ae0ca0: 00910 - busy (908)            0000000026ae15b0: 00910 - busy (908)            0000000026ae1ec0: 00910 - busy (908)            0000000026ae27d0: 00910 - busy (908)            0000000026ae30e0: 00910 - busy (908)            0000000026ae39f0: 00910 - busy (908)            0000000026ae4300: 00910 - busy (908)            0000000026ae4c10: 00910 - busy (908)            0000000026ae5520: 00910 - busy (908)            0000000026ae5e30: 00910 - busy (908)            ...skipped            0000000026b1df60: 00910 - busy (908)            0000000026b1e870: 00910 - busy (908)            0000000026b1f180: 00910 - busy (908)            0000000026b1fa90: 00910 - busy (908)        0000000026b20c70: 40000 . 10000 [101] - busy (fff0) Internal         LFH data region at 0000000026b20c80 (subsegment 00000000269c09f0):            0000000026b20ca0: 00020 - busy (18)            0000000026b20cc0: 00020 - busy (10)            0000000026b20ce0: 00020 - busy (18)        ....