Time flies. Almost 3 weeks have passed since we announced the ability to run mona.py under WinDBG. A lot of work has been done on mona.py in the meantime. We improved stability and performance, updated to pykd.pyd 0.2.0.14 and ported a few additional immlib methods to windbglib.
I figured this would be a good time to look at 2 "new" features in mona.py:
Some of you may feel cold shivers running down your spine when you hear the word "Heap". Perhaps you feel comfortable about your ability to explore what is stored on the thread stack, but when it comes down to heap, you’re pretty much blind or ignorant.
That’s why I decided to work on improving the "heap" function in mona.py. Note that I will be using WinDBG in this post because "heap" takes advantage of WinDBG symbols. The function will work on Immunity Debugger as well, but its abilities and output will be limited.
Before looking at the various mona commands, let’s agree on a couple definitions. The word "chunk" will be used to refer to a region of memory. The word "block" is used to reference 8 bytes of memory. "Blocks" are typically used as the unit for certain size fields in heap chunk headers.
Without further ado, let’s look at what "heap" can do. For the sake of this exercise, I have attached WinDBG to calc.exe on XP SP3. Of course, everything will work on Windows 7 as well (32bit or 32bit in WOW64).
If you want to follow along, please update mona.py first :
0:014> .load pykd.pyd 0:014> !py mona update Hold on... [+] Version compare : Current Version : '2.0', Current Revision : 322 Latest Version : '2.0', Latest Revision : 322 [+] You are running the latest version [+] Locating windbglib path [+] Checking if C:\Program Files\Debugging Tools for Windows (x86)\windbglib.py needs an update... [+] Version compare : Current Version : '1.0', Current Revision : 108 Latest Version : '1.0', Latest Revision : 108 [+] You are running the latest version [+] This mona.py action took 0:00:07.579000
If you don’t have mona & windbglib yet, look here :
First, run !py mona help heap to see all available options:
Usage of command 'heap' : -------------------------- Show information about various heap chunk lists Mandatory arguments : -h <address> : base address of the heap to query -t <type> : where type is 'lal' (lookasidelist), 'freelist', 'segments', 'chunks', 'layout' or 'all' 'lal' and 'freelist' only work on XP/2003 'layout' will show all heap chunks and their vtables & strings. Use on WinDBG for maximum results. Optional arguments : -stat : show statistics (also works in combination with -h heap, -t segments or -t chunks -size <nr> : only show strings of at least the specified size. Works in combination with 'layout' -after <data> : only show current & next chunk layout entries when an entry contains this data (Only works in combination with 'layout') -v : show data / write verbose info to the Log window
The -t lal, -t freelist and -t all options are outdated and need work. The options that we are interested in right now are "segments", "chunks" and "layout".
To get a list with all process heaps, run:
0:001> !py mona heap Hold on... Heaps: ------ 0x000a0000 (1 segment(s) : 0x000a0640) * Default process heap 0x001a0000 (1 segment(s) : 0x001a0640) 0x001b0000 (1 segment(s) : 0x001b0640) 0x003c0000 (1 segment(s) : 0x003c0640) 0x003d0000 (1 segment(s) : 0x003d0640) 0x003f0000 (1 segment(s) : 0x003f0640) 0x00370000 (1 segment(s) : 0x00370640) Please specify a valid searchtype -t Valid values are : lal freelist all segments chunks layout [+] This mona.py action took 0:00:00.190000
The output should match with WinDBG’s !heap command, but mona will immediately show information about the segments as well.
To see the segments for a specific heap, run:
0:001> !py mona heap -h 000a0000 -t segments Hold on... Heaps: ------ 0x000a0000 (1 segment(s) : 0x000a0640) * Default process heap 0x001a0000 (1 segment(s) : 0x001a0640) 0x001b0000 (1 segment(s) : 0x001b0640) 0x003c0000 (1 segment(s) : 0x003c0640) 0x003d0000 (1 segment(s) : 0x003d0640) 0x003f0000 (1 segment(s) : 0x003f0640) 0x00370000 (1 segment(s) : 0x00370640) [+] Processing heap 0x000a0000 Segment List for heap 0x655360: --------------------------------- Heap : 0x000a0000 : Segment 0x000a0640 - 0x001a0000 (FirstEntry: 0x000a0680 - LastValidEntry: 0x001a0000) [+] This mona.py action took 0:00:00.327000
(note: if you omit the -h <heapbase> parameter, mona.py will show all segments for all heaps)
If you’re lazy, you can also use the word "default" as argument to -h, to indicate that you want information for the default process heap.
To see all chunks in the segments for a heap, run:
0:001> !py mona heap -h 000a0000 -t chunks Hold on... Heaps: ------ 0x000a0000 (1 segment(s) : 0x000a0640) * Default process heap 0x001a0000 (1 segment(s) : 0x001a0640) 0x001b0000 (1 segment(s) : 0x001b0640) 0x003c0000 (1 segment(s) : 0x003c0640) 0x003d0000 (1 segment(s) : 0x003d0640) 0x003f0000 (1 segment(s) : 0x003f0640) 0x00370000 (1 segment(s) : 0x00370640) [+] 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 0x000a0000 Segment List for heap 0x655360: --------------------------------- Heap : 0x000a0000 : Segment 0x000a0640 - 0x001a0000 (FirstEntry: 0x000a0680 - LastValidEntry: 0x001a0000) Nr of chunks : 584 _HEAP_ENTRY psize size unused UserPtr UserSize 000a0680 00008 01808 00008 000a0688 00001800 (6144) (Busy) 000a1e88 00301 00210 00008 000a1e90 00000208 (520) (Busy) 000a2098 00042 00228 0000e 000a20a0 0000021a (538) (Busy) 000a22c0 00045 00030 0000e 000a22c8 00000022 (34) (Busy) <...> 000b4110 00025 00040 00008 000b4118 00000038 (56) (Busy) 000b4150 00008 00128 00008 000b4158 00000120 (288) (Busy) 000b4278 00025 03d88 00008 000b4280 00003d80 (15744) (Last) 0x000b8000 - 0x001a0000 (end of segment) : uncommitted [+] This mona.py action took 0:00:03.027000
The output of this command is also written into heapchunks.txt.
Again, you can show all chunks for all segments in all heaps by omitting the -h <heapbase> parameter.
Of course, the output should be exactly the same as the chunk-related part in the output of the !heap -h <heapbase> command in WinDBG, but mona will show a little bit more information about each chunk, making it easier to find the information you need right away.
To see some statistics about the chunks and their sizes, you can use the -stat parameter in combination with -t chunks:
0:001> !py mona heap -h 000a0000 -t chunks -stat Hold on... Heaps: ------ 0x000a0000 (1 segment(s) : 0x000a0640) * Default process heap 0x001a0000 (1 segment(s) : 0x001a0640) 0x001b0000 (1 segment(s) : 0x001b0640) 0x003c0000 (1 segment(s) : 0x003c0640) 0x003d0000 (1 segment(s) : 0x003d0640) 0x003f0000 (1 segment(s) : 0x003f0640) 0x00370000 (1 segment(s) : 0x00370640) [+] 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 0x000a0000 Segment List for heap 0x655360: --------------------------------- Heap : 0x000a0000 : Segment 0x000a0640 - 0x001a0000 (FirstEntry: 0x000a0680 - LastValidEntry: 0x001a0000) Nr of chunks : 584 _HEAP_ENTRY psize size unused UserPtr UserSize Segment Statistics: Size : 0x3d80 (15744) : 1 chunks (0.17 %) Size : 0x1800 (6144) : 1 chunks (0.17 %) Size : 0x1258 (4696) : 1 chunks (0.17 %) Size : 0x928 (2344) : 2 chunks (0.34 %) Size : 0x888 (2184) : 1 chunks (0.17 %) Size : 0x7ac (1964) : 1 chunks (0.17 %) Size : 0x586 (1414) : 1 chunks (0.17 %) Size : 0x4e4 (1252) : 1 chunks (0.17 %) Size : 0x4b0 (1200) : 1 chunks (0.17 %) Size : 0x494 (1172) : 1 chunks (0.17 %) Size : 0x480 (1152) : 1 chunks (0.17 %) Size : 0x400 (1024) : 1 chunks (0.17 %) Size : 0x314 (788) : 2 chunks (0.34 %) Size : 0x30e (782) : 1 chunks (0.17 %) Size : 0x308 (776) : 1 chunks (0.17 %) Size : 0x2fa (762) : 1 chunks (0.17 %) Size : 0x2f8 (760) : 1 chunks (0.17 %) < . . . > Total chunks : 584 Global statistics Size : 0x3d80 (15744) : 1 chunks (0.17 %) Size : 0x1800 (6144) : 1 chunks (0.17 %) Size : 0x1258 (4696) : 1 chunks (0.17 %) Size : 0x928 (2344) : 2 chunks (0.34 %) Size : 0x888 (2184) : 1 chunks (0.17 %) Size : 0x7ac (1964) : 1 chunks (0.17 %) Size : 0x586 (1414) : 1 chunks (0.17 %) Size : 0x4e4 (1252) : 1 chunks (0.17 %) Size : 0x4b0 (1200) : 1 chunks (0.17 %) Size : 0x494 (1172) : 1 chunks (0.17 %) Size : 0x480 (1152) : 1 chunks (0.17 %) Size : 0x400 (1024) : 1 chunks (0.17 %) Size : 0x314 (788) : 2 chunks (0.34 %) Size : 0x30e (782) : 1 chunks (0.17 %) Size : 0x308 (776) : 1 chunks (0.17 %) Size : 0x2fa (762) : 1 chunks (0.17 %) < . . . > Total chunks : 584 [+] This mona.py action took 0:00:01.562000
So far so good, let’s move on.
The "layout" routine take things one step further. It will get all process heaps (or just a selected heap), query all segments associated with a heap, get all chunks inside a segment, and attempt to discover what type of data is stored in that chunk. Currently, mona.py is able to discover strings (ascii or unicode), BSTR objects, and objects that have a vtable. When running the layout feature under Immunity Debugger, you won’t see any objects that have a vtable. Not much I can do about it.
The output of the "layout" function will be written into the "heaplayout.txt" file. We’ll take a look at some examples in a few moments.
There are a couple of parameters that will influence the output or behaviour of the "layout" command, allowing you to fine-tune the amount of information, as well as the type of information you want to see:
We’ll use 3 examples to demonstrate how mona.py can help you to see what is stored in the heap, and where certain data is placed in relation to other data on the stack.
To get the maximum amount of information, simply run
!py mona heap -t layout -v
The output is grouped per heap, per segment, per chunk. Let’s look a random location in the output :
----- Heap 0x003d0000, Segment 0x003d0640 - 0x003e0000 (1/1) ----- chunk 0x003d0680 (Usersize 0x1800, chunksize 0x1808) : Busy chunk 0x003d1e88 (Usersize 0x88, chunksize 0x90) : Busy chunk 0x003d1f18 (Usersize 0x88, chunksize 0x90) : Busy chunk 0x003d1fa8 (Usersize 0x3df, chunksize 0x448) : Free +003f @ 003d1fe7->003d200b : String (Data : 0x23/35 bytes, 0x23/35 chars) : ComSpec=C:\WINDOWS\system32\cmd.exe +0021 @ 003d202c->003d2053 : String (Data : 0x26/38 bytes, 0x26/38 chars) : HOMEPATH=\Documents and Settings\peter +003c @ 003d208f->003d21bd : String (Data : 0x12d/301 bytes, 0x12d/301 chars) : Path=C:\Perl\site\bin;C:\Perl\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;c:\python2... @ 003d2168 : Object : 74726f54 MSCTF!CLBarItemSinkProxy::`vftable'+0x8 +0055 @ 003d21bd->003d21f6 : String (Data : 0x38/56 bytes, 0x38/56 chars) : PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH +001b @ 003d2211->003d2256 : String (Data : 0x44/68 bytes, 0x44/68 chars) : PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 11, GenuineIntel +0081 @ 003d22d7->003d22fc : String (Data : 0x24/36 bytes, 0x24/36 chars) : TEMP=C:\DOCUME~1\peter\LOCALS~1\Temp +0000 @ 003d22fc->003d2320 : String (Data : 0x23/35 bytes, 0x23/35 chars) : TMP=C:\DOCUME~1\peter\LOCALS~1\Temp +0023 @ 003d2343->003d236f : String (Data : 0x2b/43 bytes, 0x2b/43 chars) : USERPROFILE=C:\Documents and Settings\peter +0000 @ 003d236f->003d23bb : String (Data : 0x4b/75 bytes, 0x4b/75 chars) : VS100COMNTOOLS=C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools\
In this excerpt, we see that
Let’s focus on the first String in the 4th chunk for a moment. The line contains the following values:
Whenever a vtable reference is found, mona.py will attempt to find the size of the object it belongs to. If it was not able to do that, you will only see the start address of the object, but no end address. The offset placed at the start of on the line right after the object might indicate how big the object is. You will usually need to subtract 0x8 or 0xc bytes from that value to get the actual object size.
On top of that, it’s very common that a vftable contains multiple function pointers. Mona.py will group all function pointers within a distance of 0xc bytes together and only show one entry about it in the log. Not perfect, but avoids a good amount of noise.
Let’s look at 2 more examples to demonstrate additional features.
Imagine you want to see if a heap spray was successful, find where it is and how big the chunks are. Let’s try the following basic heapspray script on IE8, XP SP3:
<html><head> <script> var largechunk = "AAAA"; var spray = new Array(); function dospray() { while (largechunk.length < 0x10000) largechunk += largechunk; for (var i = 0; i < 0x200; i++) { spray[i] = largechunk.substring(0,(0x800-6)/2); } alert("Spray done ?"); } </script> </head> <body onload="dospray();" /> </html>
Attach WinDBG to the iexplore.exe tab that contains the heap spray routine. I decided to use A’s in the heapspray and I know every BSTR should be about 0x800 bytes. To make sure mona.py will find my strings, I’ll tell it to look for strings of 0x300 bytes and larger. That should be enough to ignore the noise and still allow enough room for mistakes.
Keep in mind that I did not use the unescape function, and I am trying to allocate chunks of exactly 0x800 bytes, which means the actual string length will be less. The -size parameter will look for the number of ascii bytes. In case of a BSTR, it will only count half of the bytes. Of course, you don’t have to use the -size parameter. In any case, I expect to find a bunch of BSTR objects, most likely in the default process heap, but let’s pretend (or cofirm) I am clueless.
Let’s ask mona to find our heapspray:
!py mona heap -t layout -size 0x300
The fact that the execution of the command takes a lot longer to finish than what was the case with calc.exe is because we didn’t limit the search to a specific heap, our process has more heaps than calc.exe, and the total number of segments and chunks is larger as well. In my (slow) VM, the command took about 4 minutes to complete. While this sounds bad, you will notice however that any subsequent runs will go faster. In fact, a second run only took 20 to 30 seconds to complete. Even after closing WinDBG and opening a new session, it will be faster. I’ll get back to this later.
We have told mona to only give us strings that are at least 0x500 bytes. In addition to finding those strings, mona.py will still show you all vtable references. This time, mona.py was able to find the size of some of the objects, which means the output will contain more information for those objects:
chunk 0x02dc9840 (Usersize 0x1ff8, chunksize 0x2000) : Busy +01f8 @ 02dc9a38 : Object : 774ec300 ole32!CComApartment::`vftable' +01d8 @ 02dc9c10->02dc9c38 : Object (0x28 bytes): 3cf70002 mshtml!CMetaElement::`vftable'+0x16a
Anyways, when the search has completed, open the heaplayout.txt file and search for "AAAAAAAAAAAAAAAAAAAAA":
Perfect, there is our spray ! Let’s look at one of the lines :
+2040 @ 02da2080->02da2880 : BSTR 0x800/2048 bytes (Data : 0x7fa/2042 bytes, 0x3fd/1021 chars)
The BSTR object is, as expected, exactly 0x800 bytes, including 4 byte header and 2 byte terminator. That means that 0x800 – 6 bytes ( = 0x7fa bytes) are used for data. Inside the data, we find a string of 0x7fa / 2 ( = 0x3fd) non-null byte characters.
The offset between each line in the screenshot above is 0x8 bytes. This indicates the spray chunks are adjacent. The output also indicates that the BSTR objects are placed inside bigger heap chunks. That also explains why you are not seeing a lot of chunks of 0x800 in the output of WinDBG !heap -stat -h 00150000:
0:016> !heap -stat -h 00150000 heap @ 00150000 group-by: TOTSIZE max-display: 20 size #chunks total ( %) (percent of total busy bytes) fff8 18 - 17ff40 (41.05) 3fff8 3 - bffe8 (20.53) 3ff8 11 - 43f78 (7.27) 1ff8 1e - 3bf10 (6.41) 20fc1 1 - 20fc1 (3.53) 1fff8 1 - 1fff8 (3.42) 7ff8 3 - 17fe8 (2.57) 13fc1 1 - 13fc1 (2.14) 8fc1 2 - 11f82 (1.92) b2e0 1 - b2e0 (1.20) ff8 b - afa8 (1.17) 7f8 15 - a758 (1.12) 57f0 1 - 57f0 (0.59) 4ffc 1 - 4ffc (0.53) 4fc1 1 - 4fc1 (0.53) 5e4 b - 40cc (0.43) 3980 1 - 3980 (0.38) 20 1c7 - 38e0 (0.38) 3f8 a - 27b0 (0.27) 1e04 1 - 1e04 (0.20)
Let’s take things one step further. Imagine you want to set up a specific heap layout in IE9 on Windows 7. The heap layout needs to contain repeating sequences of a button object (CButtonLayout) and a string. This time, we are going to limit the output of mona to showing the heap chunks that contain a CButtonLayout vtable (and anything placed after that vtable inside that chunk).
The command to run is:
!py mona heap -t layout -after CButtonLayout
As soon as mona.py finds a string or vtable that contains the value provided in the -after parameter, it will display all information for that current chunk after that position in the chunk. This value matching process is case sensitive.
Open the log file (heaplayout.txt) and search for the string. This time, the amount of detail in the log file is limited to chunks that contain a CButtonLayout vftable.
As you can see, mona.py was not able to determine the exact size of the CButtonLayout object, because it was not able to find a CreateElement construction routine in mshtml.dll. After spending a few moments of reverse engineering, you will discover that the size of a CButtonLayout object is 0x100 bytes. We can now tell mona.py to remember this value by adding it to the knowledge base:
!py mona kb -set -id vtableCache -value MSHTML!CButtonLayout,0x100 !py mona kb -set -id vtableCache -value mshtml!CButtonLayout,0x100
Run the mona heap -t layout -after CButtonLayout command again. The output now looks like this:
Much better, and the great thing is that mona will remember this value as long as it’s part of the knowledgebase. Since the knowledgebase doesn’t get cleared when you close Windbg, this means forever. Just remember that OS updates might change object sizes, so you may have to remove the knowledgebase file from time to time & let mona generate it again.
As mentioned earlier, one of the things you may have noticed is that the first run of mona heap -t layout took a few minutes to complete, and all subsequent runs appeared to be a lot faster, even after closing WinDBG and opening it again.
When mona heap -t layout runs, it will attempt to find object sizes and saves them into a vtableCache dictionary. This dictionary is then saved into the knowledgebase, which is basically a file (windbglib.db) that contains serialized python objects (pickle). Whenever mona heap -t layout is used, mona will read this knowledgebase and populates the internal vtableCache with values from the database. That explains why results were produced much faster after the first run.
The mona.py "kb" command allows you to manipulate this knowledgebase using the list, set or del function.
To list all knowledgebase IDs in the file, run
0:015> !py mona kb -list Hold on... Number of IDs in Knowledgebase : 1 IDs : ----- vtableCache [+] This mona.py action took 0:00:00
To get all data inside the python object associated with a given knowledgebase ID, simply add the -id parameter:
0:015> !py mona kb -list -id vtableCache Hold on... Number of IDs in Knowledgebase : 1 Entries for ID vtableCache (type dict) : ------------------------------------------ IEFRAME!CFrameLayer : 0 (0x0) DWrite!pz::Rule::GenericExpression<pz::Expression<pz::BinaryOperation<pz::Expression<pz::BinaryOperation<pz::Expression<pz::BinaryOperation<pz::Expression<pz::Reference,pz::IsAlwaysTrue,pz::NoAction>,pz::Expression<pz::UnaryOperation<pz::Expression<pz::BinaryOperation<pz::Expression<pz::Reference,pz::IsAlwaysTrue,pz::NoAction>,pz::Expression<pz::UnaryOperation<pz::Expression<pz::DynamicKind<enum : 0 (0x0) MSHTML!QuirkTokenizer : 0 (0x0) MSHTML!ATL::CComObject<CHTMLEditorProxy> : 0 (0x0) windowscodecs!CDemandBitmapCache<IWICBitmapSource> : 0 (0x0) d3d10!D3D10Statechunk::TShaderInput<ID3D10Buffer,&ID3D10Device::`vcall'{192}',&ID3D10Device::`vcall'{64}'> : 0 (0x0) IEFRAME!CMenuBandMetrics : 0 (0x0) IEFRAME!CIEFrameAuto::COmHistory : 0 (0x0) DWrite!ClientAlpcConnection : 0 (0x0) MSHTML!CCurrentStyle : 0 (0x0) msimtf!CClassFactory : 0 (0x0) MSHTML!CInsertParagraphCommand : 0 (0x0) MSHTML!CDoc : 0 (0x0) MSHTML!CProgSink : 0 (0x0) MSHTML!CIE50PasteModeCommand : 0 (0x0) propsys!CGlobalMappingData : 0 (0x0) ieapfltr!GenericDeletableCollection<FormDetails> : 0 (0x0) MSHTML!CForeColorCommand : 0 (0x0) MSHTML!CBaseROStmOnBuffer : 0 (0x0) MSHTML!CBaseXSLTFilter : 0 (0x0) d2d1!CHwRadialGradientBrush : 0 (0x0) MSHTML!CDataCache<CBoxShadow> : 0 (0x0) <...> MSCTF!CEditRecord : 0 (0x0) DWrite!InnerComObject<DWriteFactory,DWriteGdiInterop> : 0 (0x0) Number of entries for ID vtableCache : 605 [+] This mona.py action took 0:00:00.219000
0:015> !py mona kb -list -id vtableCache Hold on... Number of IDs in Knowledgebase : 1 Entries for ID vtableCache (type dict) : ------------------------------------------ IEFRAME!CFrameLayer : 0 (0x0) DWrite!pz::Rule::GenericExpression<pz::Expression<pz::BinaryOperation<pz::Expression<pz::BinaryOperation<pz::Expression<pz::BinaryOperation<pz::Expression<pz::Reference,pz::IsAlwaysTrue,pz::NoAction>,pz::Expression<pz::UnaryOperation<pz::Expression<pz::BinaryOperation<pz::Expression<pz::Reference,pz::IsAlwaysTrue,pz::NoAction>,pz::Expression<pz::UnaryOperation<pz::Expression<pz::DynamicKind<enum : 0 (0x0) MSHTML!QuirkTokenizer : 0 (0x0) MSHTML!ATL::CComObject<CHTMLEditorProxy> : 0 (0x0) windowscodecs!CDemandBitmapCache<IWICBitmapSource> : 0 (0x0) d3d10!D3D10Statechunk::TShaderInput<ID3D10Buffer,&ID3D10Device::`vcall'{192}',&ID3D10Device::`vcall'{64}'> : 0 (0x0) IEFRAME!CMenuBandMetrics : 0 (0x0) IEFRAME!CIEFrameAuto::COmHistory : 0 (0x0) DWrite!ClientAlpcConnection : 0 (0x0) MSHTML!CCurrentStyle : 0 (0x0) msimtf!CClassFactory : 0 (0x0) MSHTML!CInsertParagraphCommand : 0 (0x0) MSHTML!CDoc : 0 (0x0) MSHTML!CProgSink : 0 (0x0) MSHTML!CIE50PasteModeCommand : 0 (0x0) propsys!CGlobalMappingData : 0 (0x0) ieapfltr!GenericDeletableCollection<FormDetails> : 0 (0x0) MSHTML!CForeColorCommand : 0 (0x0) MSHTML!CBaseROStmOnBuffer : 0 (0x0) MSHTML!CBaseXSLTFilter : 0 (0x0) d2d1!CHwRadialGradientBrush : 0 (0x0) MSHTML!CDataCache<CBoxShadow> : 0 (0x0)
<...>
MSCTF!CEditRecord : 0 (0x0) DWrite!InnerComObject<DWriteFactory,DWriteGdiInterop> : 0 (0x0) Number of entries for ID vtableCache : 605 [+] This mona.py action took 0:00:00.219000
You can also filter using the -value argument:
0:015> !py mona kb -list -id vtableCache -value CButton Hold on... Number of IDs in Knowledgebase : 1 Entries for ID vtableCache (type dict) : ------------------------------------------ (Filter : CButton) MSHTML!CButton : 0 (0x0) MSHTML!CButtonLayout : 256 (0x100) mshtml!CButtonLayout : 256 (0x100) Number of filtered entries for ID vtableCache : 3 [+] This mona.py action took 0:00:00.016000
To remove an entry from the list, use the "del" function :
0:015> !py mona kb -del -id vtableCache -value mshtml!CButtonLayout Hold on... *** Object mshtml!CButtonLayout in ID vtableCache removed from Knowledgebase [+] This mona.py action took 0:00:00.032000 0:015> !py mona kb -list -id vtableCache -value CButton Hold on... Number of IDs in Knowledgebase : 1 Entries for ID vtableCache (type dict) : ------------------------------------------ (Filter : CButton) MSHTML!CButton : 0 (0x0) MSHTML!CButtonLayout : 256 (0x100) Number of filtered entries for ID vtableCache : 2 [+] This mona.py action took 0:00:00
Note : if you omit the -value parameter, the entire ID object will be removed. No big deal, because mona.py will recreate the ID automatically, any manual changes to the list will be lost. In any case, don’t edit the windbglib.db file yourself. If it gets corrupted, remove it & let mona.py create a new one.
If you have further questions about mona : https://www.corelan.be/index.php/forum/mona/
Have a great week-end !
-peter
Tags:
© Corelan Consulting BV. All rights reserved. The contents of this page may not be reproduced, redistributed, or republished, in whole or in part, for commercial or non-commercial purposes without prior written permission. See the Terms of Use and Privacy Policy for details.