MAPI and User Mode Stack Tracing

James wrote up a good article on analyzing a MAPI memory leak using user mode stack tracing. I wanted to highlight some points he made. Let’s look at some !heap output from one of my recent cases (using only public symbols here):

 0:000> !heap -p -a 03fbec28    
    address 03fbec28 found in
    _HEAP @ 3f90000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        03fbec20 0021 0000  [07]   03fbec28    000f0 - (busy)
          ? EMSMDB32!MSProviderInit+1d27a
        Trace: 1922
        7c8531e4 ntdll!RtlAllocateHeapSlowly+0x00000041
        7c83d97a ntdll!RtlAllocateHeap+0x00000e9f
        35b732f4 EMSMDB32!MSProviderInit+0x0000186a

The line starting with the ? is the output of dps (Display Words and Symbols) against the start of the allocation. Basically, it’s saying “suppose this was a pointer – what does it point to?”. The reason it does this is in case this allocation happens to be an object. Objects are usually laid out in memory with pointers to the object’s virtual tables (vtable) at the beginning. Even without symbols, we can see that this in this case, it *could* be an object. Let’s take a closer look:

 0:000> dps 03fbec28 l3
03fbec28  35b8ed04 EMSMDB32!MSProviderInit+0x1d27a

03fbec2c  35b728b8 EMSMDB32!MSProviderInit+0xe2e

03fbec30  00000001

0:000> dps 35b8ed04 l3

35b8ed04  35b90861 EMSMDB32!MSProviderInit+0x1edd7

35b8ed08  e958026a

35b8ed0c  ffff4140

0:000> dps 35b728b8 l3

35b728b8  35b90839 EMSMDB32!MSProviderInit+0x1edaf

35b728bc  35b7d7eb EMSMDB32!MSProviderInit+0xbd61

35b728c0  35b7d91f EMSMDB32!MSProviderInit+0xbe95

First, we run dps against the allocation, and see two possible vtables. If they are indeed vtables, dps against what they point to should also be code within emsmdb32. And we see that it is – the first points to a vtable with a single function, and the second points to a vtable with several functions. We can carry this further by unassembling the possible functions (such as 35b90861 or 35b90839) to see that the output does resemble a function header. Assuming we’re debugging our own process, we can look further down the stack from the !heap command and see that this memory was allocated in response to an OpenEntry call for a message, and conclude this is a message object.

Next time: we’ll take a look at flags and recognizing MAPI properties in memory.