{"id":9637,"date":"2013-01-18T17:00:00","date_gmt":"2013-01-18T16:00:00","guid":{"rendered":"https:\/\/www.corelan.be\/?p=9637"},"modified":"2026-03-22T10:04:25","modified_gmt":"2026-03-22T09:04:25","slug":"heap-layout-visualization-with-mona-py-and-windbg","status":"publish","type":"post","link":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/","title":{"rendered":"Heap Layout Visualization with mona.py and WinDBG"},"content":{"rendered":"<h3>Introduction<\/h3>\n<p>Time flies. Almost 3 weeks have passed since we announced the ability to run mona.py under WinDBG.&#160; A lot of work has been done on mona.py in the meantime.&#160; We improved stability and performance, updated to pykd.pyd 0.2.0.14 and ported a few additional immlib methods to windbglib.<\/p>\n<p>I figured this would be a good time to look at 2 &quot;new&quot; features in mona.py:<\/p>\n<ul>\n<li>heap <\/li>\n<li>kb (knowledgebase)<\/li>\n<\/ul>\n<h3>Heap<\/h3>\n<p>Some of you may feel cold shivers running down your spine when you hear the word &quot;Heap&quot;.&#160; 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.<\/p>\n<p>That's why I decided to work on improving the &quot;heap&quot; function in mona.py.&#160; Note that I will be using WinDBG in this post because &quot;heap&quot; takes advantage of WinDBG symbols.&#160; The function will work on Immunity Debugger as well, but its abilities and output will be limited.<\/p>\n<p>Before looking at the various mona commands, let's agree on a couple definitions. The word &quot;chunk&quot; will be used to refer to a region of memory.&#160; The word &quot;block&quot; is used to reference 8 bytes of memory.&#160; &quot;Blocks&quot; are typically used as the unit for certain size fields in heap chunk headers.<\/p>\n<p>Without further ado, let's look at what &quot;heap&quot; can do.&#160; For the sake of this exercise, I have attached WinDBG to calc.exe on XP SP3.&#160; Of course, everything will work on Windows 7 as well (32bit or 32bit in WOW64).<\/p>\n<p>If you want to follow along, please update mona.py first :<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:014&gt; <strong><font color=\"#ffff00\">.load pykd.pyd\n<\/font><\/strong>0:014&gt; <strong><font color=\"#ffff00\">!py mona update<\/font><\/strong>\nHold on...\n[+] Version compare :\n    Current Version : '2.0', Current Revision : 322\n    Latest Version : '2.0', Latest Revision : 322\n[+] You are running the latest version\n[+] Locating windbglib path\n[+] Checking if C:\\Program Files\\Debugging Tools for Windows (x86)\\windbglib.py needs an update...\n[+] Version compare :\n    Current Version : '1.0', Current Revision : 108\n    Latest Version : '1.0', Latest Revision : 108\n[+] You are running the latest version\n\n[+] This mona.py action took 0:00:07.579000<\/pre>\n<p>If you don't have mona &amp; windbglib yet, look here :<\/p>\n<ul>\n<li>windbglib : <a title=\"http:\/\/github.com\/corelan\/windbglib\" href=\"https:\/\/github.com\/corelan\/windbglib\">https:\/\/github.com\/corelan\/windbglib<\/a> (has an installer script for both windbglib and mona)<\/li>\n<li>mona : <a title=\"http:\/\/github.com\/corelan\/mona\" href=\"https:\/\/github.com\/corelan\/mona\">https:\/\/github.com\/corelan\/mona<\/a><\/li>\n<\/ul>\n<p>First, run !py mona help heap to see all available options:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">Usage of command 'heap' :\n--------------------------\nShow information about various heap chunk lists\nMandatory arguments :\n    -h &lt;address&gt; : base address of the heap to query\n    -t &lt;type&gt; : where type is 'lal' (lookasidelist), 'freelist', 'segments', 'chunks', 'layout' or 'all'\n    'lal' and 'freelist' only work on XP\/2003\n    'layout' will show all heap chunks and their vtables &amp; strings. Use on WinDBG <span style=\"color: #0000ff\">for<\/span> maximum results.\nOptional arguments :\n    -stat : show statistics (also works in combination with -h heap, -t segments or -t chunks\n    -size &lt;nr&gt; : only show strings of at least the specified size. Works in combination with 'layout'\n    -after &lt;data&gt; : only show current &amp; next chunk layout entries when an entry contains this data\n                    (Only works in combination with 'layout')\n    -v : show data \/ <span style=\"color: #0000ff\">write<\/span> verbose info to the Log window<\/pre>\n<p>The -t lal, -t freelist and -t all options are outdated and need work.&#160; The options that we are interested in right now are &quot;segments&quot;, &quot;chunks&quot; and &quot;layout&quot;.<\/p>\n<p>To get a list with all process heaps, run:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:001&gt; <strong><font color=\"#ffff00\">!py mona heap<\/font><\/strong>\nHold on...\nHeaps:\n------\n0x000a0000 (1 segment(s) : 0x000a0640) * Default process heap\n0x001a0000 (1 segment(s) : 0x001a0640) \n0x001b0000 (1 segment(s) : 0x001b0640) \n0x003c0000 (1 segment(s) : 0x003c0640) \n0x003d0000 (1 segment(s) : 0x003d0640) \n0x003f0000 (1 segment(s) : 0x003f0640) \n0x00370000 (1 segment(s) : 0x00370640) \n\nPlease specify a valid searchtype -t\nValid values are :\n   lal\n   freelist\n   all\n   segments\n   chunks\n   layout\n\n[+] This mona.py action took 0:00:00.190000<\/pre>\n<p>The output should match with WinDBG's !heap command, but mona will immediately show information about the segments as well.<\/p>\n<p>To see the segments for a specific heap, run:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:001&gt; <strong><font color=\"#ffff00\">!py mona heap -h 000a0000 -t segments<\/font><\/strong>\nHold on...\nHeaps:\n------\n0x000a0000 (1 segment(s) : 0x000a0640) * Default process heap\n0x001a0000 (1 segment(s) : 0x001a0640) \n0x001b0000 (1 segment(s) : 0x001b0640) \n0x003c0000 (1 segment(s) : 0x003c0640) \n0x003d0000 (1 segment(s) : 0x003d0640) \n0x003f0000 (1 segment(s) : 0x003f0640) \n0x00370000 (1 segment(s) : 0x00370640) \n\n[+] Processing heap 0x000a0000\nSegment List <span style=\"color: #0000ff\">for<\/span> heap 0x655360:\n---------------------------------\nHeap : 0x000a0000 : Segment 0x000a0640 - 0x001a0000 (FirstEntry: 0x000a0680 - LastValidEntry: 0x001a0000)\n\n[+] This mona.py action took 0:00:00.327000<\/pre>\n<p>(note: if you omit the -h &lt;heapbase&gt; parameter, mona.py will show all segments for all heaps)<\/p>\n<p>If you're lazy, you can also use the word &quot;default&quot; as argument to -h, to indicate that you want information for the default process heap.<\/p>\n<p>To see all chunks in the segments for a heap, run:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:001&gt; <strong><font color=\"#ffff00\">!py mona heap -h 000a0000 -t chunks<\/font><\/strong>\nHold on...\nHeaps:\n------\n0x000a0000 (1 segment(s) : 0x000a0640) * Default process heap\n0x001a0000 (1 segment(s) : 0x001a0640) \n0x001b0000 (1 segment(s) : 0x001b0640) \n0x003c0000 (1 segment(s) : 0x003c0640) \n0x003d0000 (1 segment(s) : 0x003d0640) \n0x003f0000 (1 segment(s) : 0x003f0640) \n0x00370000 (1 segment(s) : 0x00370640) \n\n[+] Preparing output file 'heapchunks.txt'\n    - (Re)setting logfile heapchunks.txt\n[+] Generating module info table, hang on...\n    - Processing modules\n    - Done. Let's rock 'n roll.\n[+] Processing heap 0x000a0000\nSegment List <span style=\"color: #0000ff\">for<\/span> heap 0x655360:\n---------------------------------\nHeap : 0x000a0000 : Segment 0x000a0640 - 0x001a0000 (FirstEntry: 0x000a0680 - LastValidEntry: 0x001a0000)\n    Nr of chunks : 584 \n    _HEAP_ENTRY  psize   size  unused  UserPtr   UserSize\n       000a0680  00008  01808   00008  000a0688  00001800 (6144) (Busy)\n       000a1e88  00301  00210   00008  000a1e90  00000208 (520) (Busy)\n       000a2098  00042  00228   0000e  000a20a0  0000021a (538) (Busy)\n       000a22c0  00045  00030   0000e  000a22c8  00000022 (34) (Busy)\n&lt;...&gt; \n       000b4110  00025  00040   00008  000b4118  00000038 (56) (Busy)\n       000b4150  00008  00128   00008  000b4158  00000120 (288) (Busy)\n       000b4278  00025  03d88   00008  000b4280  00003d80 (15744) (Last)\n       0x000b8000 - 0x001a0000 (end of segment) : uncommitted\n\n[+] This mona.py action took 0:00:03.027000<\/pre>\n<p>The output of this command is also written into heapchunks.txt.<\/p>\n<p>Again, you can show all chunks for all segments in all heaps by omitting the -h &lt;heapbase&gt; parameter.<\/p>\n<p>Of course, the output should be exactly the same as the chunk-related part in the output of the&#160; !heap -h &lt;heapbase&gt; 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.<\/p>\n<p>To see some statistics about the chunks and their sizes, you can use the -stat parameter in combination with -t chunks:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:001&gt; !py mona heap -h 000a0000 -t chunks -stat\nHold on...\nHeaps:\n------\n0x000a0000 (1 segment(s) : 0x000a0640) * Default process heap\n0x001a0000 (1 segment(s) : 0x001a0640) \n0x001b0000 (1 segment(s) : 0x001b0640) \n0x003c0000 (1 segment(s) : 0x003c0640) \n0x003d0000 (1 segment(s) : 0x003d0640) \n0x003f0000 (1 segment(s) : 0x003f0640) \n0x00370000 (1 segment(s) : 0x00370640) \n\n[+] Preparing output file 'heapchunks.txt'\n    - (Re)setting logfile heapchunks.txt\n[+] Generating module info table, hang on...\n    - Processing modules\n    - Done. Let's rock 'n roll.\n[+] Processing heap 0x000a0000\nSegment List <span style=\"color: #0000ff\">for<\/span> heap 0x655360:\n---------------------------------\nHeap : 0x000a0000 : Segment 0x000a0640 - 0x001a0000 (FirstEntry: 0x000a0680 - LastValidEntry: 0x001a0000)\n    Nr of chunks : 584 \n    _HEAP_ENTRY  psize   size  unused  UserPtr   UserSize\n    Segment Statistics:\n    Size : 0x3d80 (15744) : 1 chunks (0.17 %)\n    Size : 0x1800 (6144) : 1 chunks (0.17 %)\n    Size : 0x1258 (4696) : 1 chunks (0.17 %)\n    Size : 0x928 (2344) : 2 chunks (0.34 %)\n    Size : 0x888 (2184) : 1 chunks (0.17 %)\n    Size : 0x7ac (1964) : 1 chunks (0.17 %)\n    Size : 0x586 (1414) : 1 chunks (0.17 %)\n    Size : 0x4e4 (1252) : 1 chunks (0.17 %)\n    Size : 0x4b0 (1200) : 1 chunks (0.17 %)\n    Size : 0x494 (1172) : 1 chunks (0.17 %)\n    Size : 0x480 (1152) : 1 chunks (0.17 %)\n    Size : 0x400 (1024) : 1 chunks (0.17 %)\n    Size : 0x314 (788) : 2 chunks (0.34 %)\n    Size : 0x30e (782) : 1 chunks (0.17 %)\n    Size : 0x308 (776) : 1 chunks (0.17 %)\n    Size : 0x2fa (762) : 1 chunks (0.17 %)\n    Size : 0x2f8 (760) : 1 chunks (0.17 %)\n    \n    &lt; . . . &gt;\n\n    Total chunks : 584\n\n\nGlobal statistics\n  Size : 0x3d80 (15744) : 1 chunks (0.17 %)\n  Size : 0x1800 (6144) : 1 chunks (0.17 %)\n  Size : 0x1258 (4696) : 1 chunks (0.17 %)\n  Size : 0x928 (2344) : 2 chunks (0.34 %)\n  Size : 0x888 (2184) : 1 chunks (0.17 %)\n  Size : 0x7ac (1964) : 1 chunks (0.17 %)\n  Size : 0x586 (1414) : 1 chunks (0.17 %)\n  Size : 0x4e4 (1252) : 1 chunks (0.17 %)\n  Size : 0x4b0 (1200) : 1 chunks (0.17 %)\n  Size : 0x494 (1172) : 1 chunks (0.17 %)\n  Size : 0x480 (1152) : 1 chunks (0.17 %)\n  Size : 0x400 (1024) : 1 chunks (0.17 %)\n  Size : 0x314 (788) : 2 chunks (0.34 %)\n  Size : 0x30e (782) : 1 chunks (0.17 %)\n  Size : 0x308 (776) : 1 chunks (0.17 %)\n  Size : 0x2fa (762) : 1 chunks (0.17 %)\n  \n  &lt; . . . &gt;\n\n  Total chunks : 584\n\n[+] This mona.py action took 0:00:01.562000<\/pre>\n<p>So far so good, let's move on.<\/p>\n<p>&#160;<\/p>\n<h3>Heap layout<\/h3>\n<p>The &quot;layout&quot; 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.&#160; Currently, mona.py is able to discover strings (ascii or unicode), BSTR objects, and objects that have a vtable.&#160; When running the layout feature under Immunity Debugger, you won't see any objects that have a vtable.&#160; Not much I can do about it. <\/p>\n<p>The output of the &quot;layout&quot; function will be written into the &quot;heaplayout.txt&quot; file.&#160; We'll take a look at some examples in a few moments.<\/p>\n<p>There are a couple of parameters that will influence the output or behaviour of the &quot;layout&quot; command, allowing you to fine-tune the amount of information, as well as the type of information you want to see:<\/p>\n<ul>\n<li>-v : this will cause all information to be written into the Log window as well.<\/li>\n<li>-fast : this will skip the discovery of object sizes<\/li>\n<li>-size &lt;nr&gt; : this will cause mona.py to skip string related entries that are smaller than the provided size<\/li>\n<li>-after &lt;value&gt; : this will cause mona.py to ignore entries inside a chunk until either a string or vtable reference is found that contains this &lt;value&gt;.&#160; It will then output everything for the current chunk.&#160;&#160; <\/li>\n<\/ul>\n<p>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.<\/p>\n<h4>Overall Layout<\/h4>\n<p>To get the maximum amount of information, simply run<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\"><font color=\"#ffff00\">!py mona heap -t layout -v<\/font><\/pre>\n<p>The output is grouped per heap, per segment, per chunk.&#160; Let's look a random location in the output :<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">----- Heap 0x003d0000, Segment 0x003d0640 - 0x003e0000 (1\/1) -----\nchunk 0x003d0680 (Usersize 0x1800, chunksize 0x1808) : Busy\nchunk 0x003d1e88 (Usersize 0x88, chunksize 0x90) : Busy\nchunk 0x003d1f18 (Usersize 0x88, chunksize 0x90) : Busy\nchunk 0x003d1fa8 (Usersize 0x3df, chunksize 0x448) : Free\n  +003f @ 003d1fe7-&gt;003d200b : String (Data : 0x23\/35 bytes, 0x23\/35 chars) : ComSpec=C:\\WINDOWS\\<span style=\"color: #0000ff\">system<\/span>32\\cmd.exe\n  +0021 @ 003d202c-&gt;003d2053 : String (Data : 0x26\/38 bytes, 0x26\/38 chars) : HOMEPATH=\\Documents and Settings\\peter\n  +003c @ 003d208f-&gt;003d21bd : String (Data : 0x12d\/301 bytes, 0x12d\/301 chars) : Path=C:\\Perl\\site\\bin;C:\\Perl\\bin;C:\\WINDOWS\\<span style=\"color: #0000ff\">system<\/span>32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;c:\\python2...\n        @ 003d2168           : Object : 74726f54 MSCTF!CLBarItemSinkProxy::`vftable'+0x8 \n  +0055 @ 003d21bd-&gt;003d21f6 : String (Data : 0x38\/56 bytes, 0x38\/56 chars) : PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH\n  +001b @ 003d2211-&gt;003d2256 : String (Data : 0x44\/68 bytes, 0x44\/68 chars) : PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 11, GenuineIntel\n  +0081 @ 003d22d7-&gt;003d22fc : String (Data : 0x24\/36 bytes, 0x24\/36 chars) : TEMP=C:\\DOCUME~1\\peter\\LOCALS~1\\Temp\n  +0000 @ 003d22fc-&gt;003d2320 : String (Data : 0x23\/35 bytes, 0x23\/35 chars) : TMP=C:\\DOCUME~1\\peter\\LOCALS~1\\Temp\n  +0023 @ 003d2343-&gt;003d236f : String (Data : 0x2b\/43 bytes, 0x2b\/43 chars) : USERPROFILE=C:\\Documents and Settings\\peter\n  +0000 @ 003d236f-&gt;003d23bb : String (Data : 0x4b\/75 bytes, 0x4b\/75 chars) : VS100COMNTOOLS=C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\\Tools\\<\/pre>\n<p>In this excerpt, we see that<\/p>\n<ul>\n<li>The first 3 chunks of segment 0x003d0640 in heap 0x003d0000 do not seem to contain strings or vtable references<\/li>\n<li>The fourth chunk contains strings and an object.<\/li>\n<\/ul>\n<p>Let's focus on the first String in the 4th chunk for a moment.&#160; The line contains the following values:<\/p>\n<ul>\n<li>+003F : this indicates the distance from the end of the previous entry (or the start of the heap chunk in case of the first entry) to the start of the current entry (which is a string in this case)<\/li>\n<li>@ 003d1fe7-&gt;003d200b : this is the memory range consumed by the current entry.&#160; In case of a string (ascii or unicode), the first pointer will point to the start of the string.&#160; In case of a BSTR, the first pointer will point to the start of the BSTR header.&#160; In case of an &quot;object&quot;, the pointer contains the address of the vtable reference.<\/li>\n<li>&quot;String&quot; : this field indicates the type of entry, and is followed by the size of the data in&#160; bytes and chars. Bytes indicate the number of bytes consumed by this entry, including header and terminator bytes.&#160; In case of unicode, the bytes will be twice the amount of chars.&#160; <\/li>\n<li>Data : if the entry is a string, you'll see up to the first 100 chars.&#160; If the entry is an object, you will get the vtable reference.<\/li>\n<\/ul>\n<p>Whenever a vtable reference is found, mona.py will attempt to find the size of the object it belongs to.&#160; If it was not able to do that, you will only see the start address of the object, but no end address.&#160;&#160;&#160; The offset placed at the start of on the line right after the object might indicate how big the object is.&#160; You will usually need to subtract 0x8 or 0xc bytes from that value to get the actual object size.<\/p>\n<p>On top of that, it's very common that a vftable contains multiple function pointers.&#160; Mona.py will group all function pointers within a distance of 0xc bytes together and only show one entry about it in the log.&#160; Not perfect, but avoids a good amount of noise.<\/p>\n<p>Let's look at 2 more examples to demonstrate additional features.<\/p>\n<h4>Heap Spray<\/h4>\n<p>Imagine you want to see if a heap spray was successful, find where it is and how big the chunks are.&#160; Let's try the following basic heapspray script on IE8, XP SP3:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">&lt;html&gt;&lt;head&gt;\n&lt;script&gt;\n\n<span style=\"color: #0000ff\">var<\/span> largechunk = &quot;<span style=\"color: #8b0000\">AAAA<\/span>&quot;;\n<span style=\"color: #0000ff\">var<\/span> spray = <span style=\"color: #0000ff\">new<\/span> <span style=\"color: #0000ff\">Array<\/span>();\n\n<span style=\"color: #0000ff\">function<\/span> dospray()\n{\n\t<span style=\"color: #0000ff\">while<\/span> (largechunk.<span style=\"color: #0000ff\">length<\/span> &lt; 0x10000) largechunk += largechunk;\n\t\n\t<span style=\"color: #0000ff\">for<\/span> (<span style=\"color: #0000ff\">var<\/span> i = 0; i &lt; 0x200; i++)\n\t{\n\t\tspray[i] = largechunk.substring(0,(0x800-6)\/2);\n\t}\n\t<span style=\"color: #0000ff\">alert<\/span>(&quot;<span style=\"color: #8b0000\">Spray done ?<\/span>&quot;);\n}\n\n&lt;\/script&gt;\n&lt;\/head&gt;\n&lt;body onload=&quot;<span style=\"color: #8b0000\">dospray();<\/span>&quot; \/&gt;\n&lt;\/html&gt;<\/pre>\n<p>Attach WinDBG to the iexplore.exe tab that contains the heap spray routine.&#160; I decided to use A's in the heapspray and I know every BSTR should be about 0x800 bytes.&#160; To make sure mona.py will find my strings, I'll tell it to look for strings of 0x300 bytes and larger.&#160; That should be enough to ignore the noise and still allow enough room for mistakes.<\/p>\n<p>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.&#160; The -size parameter will look for the number of ascii bytes.&#160; In case of a BSTR, it will only count half of the bytes.&#160;&#160; Of course, you don't have to use the -size parameter.&#160; 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.<\/p>\n<p>Let's ask mona to find our heapspray:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">!py mona heap -t layout -size 0x300<\/pre>\n<p>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.&#160;&#160; In my (slow) VM, the command took about 4 minutes to complete.&#160; While this sounds bad, you will notice however that any subsequent runs will go faster.&#160; 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.&#160; I'll get back to this later.<\/p>\n<p>We have told mona to only give us strings that are at least 0x500 bytes.&#160; In addition to finding those strings, mona.py will still show you all vtable references.&#160; 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:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">chunk 0x02dc9840 (Usersize 0x1ff8, chunksize 0x2000) : Busy\n  +01f8 @ 02dc9a38           : Object : 774ec300 ole32!CComApartment::`vftable' \n  +01d8 @ 02dc9c10-&gt;02dc9c38 : Object (0x28 bytes): 3cf70002 mshtml!CMetaElement::`vftable'+0x16a <\/pre>\n<p>Anyways, when the search has completed, open the heaplayout.txt file and search for &quot;AAAAAAAAAAAAAAAAAAAAA&quot;:<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image2.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; margin: 7px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb2.png\" width=\"730\" height=\"201\" \/><\/a><\/p>\n<p>Perfect, there is our spray !&#160; Let's look at one of the lines :<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">+2040 @ 02da2080-&gt;02da2880 : BSTR 0x800\/2048 bytes (Data : 0x7fa\/2042 bytes, 0x3fd\/1021 chars)<\/pre>\n<p>The BSTR object is, as expected, exactly 0x800 bytes, including 4 byte header and 2 byte terminator.&#160; That means that 0x800 - 6 bytes ( = 0x7fa bytes) are used for data.&#160; Inside the data, we find a string of 0x7fa \/ 2 ( = 0x3fd) non-null byte characters.<\/p>\n<p>The offset between each line in the screenshot above is 0x8 bytes.&#160; This indicates the spray chunks are adjacent.&#160; The output also indicates that the BSTR objects are placed inside bigger heap chunks.&#160; That also explains why you are not seeing a lot of chunks of 0x800 in the output of WinDBG !heap -stat -h 00150000:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:016&gt; !heap -stat -h 00150000\n heap @ 00150000\ngroup-by: TOTSIZE max-display: 20\n    size     #chunks     total     ( %) (percent of total busy bytes)\n    fff8 18 - 17ff40  (41.05)\n    3fff8 3 - bffe8  (20.53)\n    3ff8 11 - 43f78  (7.27)\n    1ff8 1e - 3bf10  (6.41)\n    20fc1 1 - 20fc1  (3.53)\n    1fff8 1 - 1fff8  (3.42)\n    7ff8 3 - 17fe8  (2.57)\n    13fc1 1 - 13fc1  (2.14)\n    8fc1 2 - 11f82  (1.92)\n    b2e0 1 - b2e0  (1.20)\n    ff8 b - afa8  (1.17)\n    7f8 15 - a758  (1.12)\n    57f0 1 - 57f0  (0.59)\n    4ffc 1 - 4ffc  (0.53)\n    4fc1 1 - 4fc1  (0.53)\n    5e4 b - 40cc  (0.43)\n    3980 1 - 3980  (0.38)\n    20 1c7 - 38e0  (0.38)\n    3f8 a - 27b0  (0.27)\n    1e04 1 - 1e04  (0.20)<\/pre>\n<p>&#160;<\/p>\n<h4>Precise Heap Layout<\/h4>\n<p>Let's take things one step further.&#160; Imagine you want to set up a specific heap layout in IE9 on Windows 7.&#160; The heap layout needs to contain repeating sequences of a button object (CButtonLayout) and a string.&#160;&#160;&#160; 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).<\/p>\n<p>The command to run is:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">!py mona heap -t layout -after CButtonLayout<\/pre>\n<p>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.&#160;&#160; This value matching process is case sensitive.<\/p>\n<p>Open the log file (heaplayout.txt) and search for the string.&#160; This time, the amount of detail in the log file is limited to chunks that contain a CButtonLayout vftable.<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image3.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; margin: 7px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb3.png\" width=\"752\" height=\"393\" \/><\/a><\/p>\n<p>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.&#160; After spending a few moments of reverse engineering, you will discover that the size of a CButtonLayout object is 0x100 bytes.&#160;&#160; We can now tell mona.py to remember this value by adding it to the knowledge base:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">!py mona kb -set -id vtableCache -value MSHTML!CButtonLayout,0x100\n!py mona kb -set -id vtableCache -value mshtml!CButtonLayout,0x100<\/pre>\n<p>Run the mona heap -t layout -after CButtonLayout command again. The output now looks like this:<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image4.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; margin: 7px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb4.png\" width=\"752\" height=\"268\" \/><\/a><\/p>\n<p>Much better, and the great thing is that mona will remember this value as long as it's part of the knowledgebase.&#160; Since the knowledgebase doesn't get cleared when you close Windbg, this means forever.&#160; Just remember that OS updates might change object sizes, so you may have to remove the knowledgebase file from time to time &amp; let mona generate it again.<\/p>\n<p>&#160;<\/p>\n<h3>Knowledgebase<\/h3>\n<p>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.<\/p>\n<p>When mona heap -t layout runs, it will attempt to find object sizes and saves them into a vtableCache dictionary.&#160; This dictionary is then saved into the knowledgebase, which is basically a file (windbglib.db) that contains serialized python objects (pickle).&#160; Whenever mona heap -t layout is used, mona will read this knowledgebase and populates the internal vtableCache with values from the database.&#160; That explains why results were produced much faster after the first run.<\/p>\n<p>The mona.py &quot;kb&quot; command allows you to manipulate this knowledgebase using the list, set or del function.<\/p>\n<p>To list all knowledgebase IDs in the file, run<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:015&gt; <strong><font color=\"#ffff00\">!py mona kb -list<\/font><\/strong>\nHold on...\n\n<span style=\"color: #0000ff\">Number<\/span> of IDs <span style=\"color: #0000ff\">in<\/span> Knowledgebase : 1\nIDs :\n-----\nvtableCache\n\n[+] This mona.py action took 0:00:00<\/pre>\n<p>To get all data inside the python object associated with a given knowledgebase ID, simply add the -id parameter:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\"><p>0:015&gt; <strong><font color=\"#ffff00\">!py mona kb -list -id vtableCache<\/font><\/strong>\nHold on...\n\n<span style=\"color: #0000ff\">Number<\/span> of IDs <span style=\"color: #0000ff\">in<\/span> Knowledgebase : 1\nEntries <span style=\"color: #0000ff\">for<\/span> ID vtableCache (type dict) :\n------------------------------------------\n  IEFRAME!CFrameLayer : 0 (0x0)\n  DWrite!pz::Rule::GenericExpression&lt;pz::Expression&lt;pz::BinaryOperation&lt;pz::Expression&lt;pz::BinaryOperation&lt;pz::Expression&lt;pz::BinaryOperation&lt;pz::Expression&lt;pz::Reference,pz::IsAlwaysTrue,pz::NoAction&gt;,pz::Expression&lt;pz::UnaryOperation&lt;pz::Expression&lt;pz::BinaryOperation&lt;pz::Expression&lt;pz::Reference,pz::IsAlwaysTrue,pz::NoAction&gt;,pz::Expression&lt;pz::UnaryOperation&lt;pz::Expression&lt;pz::DynamicKind&lt;<span style=\"color: #0000ff\">enum<\/span> : 0 (0x0)\n  MSHTML!QuirkTokenizer : 0 (0x0)\n  MSHTML!ATL::CComObject&lt;CHTMLEditorProxy&gt; : 0 (0x0)\n  windowscodecs!CDemandBitmapCache&lt;IWICBitmapSource&gt; : 0 (0x0)\n  d3d10!D3D10Statechunk::TShaderInput&lt;ID3D10Buffer,&amp;ID3D10Device::`vcall'{192}',&amp;ID3D10Device::`vcall'{64}'&gt; : 0 (0x0)\n  IEFRAME!CMenuBandMetrics : 0 (0x0)\n  IEFRAME!CIEFrameAuto::COmHistory : 0 (0x0)\n  DWrite!ClientAlpcConnection : 0 (0x0)\n  MSHTML!CCurrentStyle : 0 (0x0)\n  msimtf!CClassFactory : 0 (0x0)\n  MSHTML!CInsertParagraphCommand : 0 (0x0)\n  MSHTML!CDoc : 0 (0x0)\n  MSHTML!CProgSink : 0 (0x0)\n  MSHTML!CIE50PasteModeCommand : 0 (0x0)\n  propsys!CGlobalMappingData : 0 (0x0)\n  ieapfltr!GenericDeletableCollection&lt;FormDetails&gt; : 0 (0x0)\n  MSHTML!CForeColorCommand : 0 (0x0)\n  MSHTML!CBaseROStmOnBuffer : 0 (0x0)\n  MSHTML!CBaseXSLTFilter : 0 (0x0)\n  d2d1!CHwRadialGradientBrush : 0 (0x0)\n  MSHTML!CDataCache&lt;CBoxShadow&gt; : 0 (0x0)<\/p><p>\n  &lt;...&gt;<\/p><p>\n  MSCTF!CEditRecord : 0 (0x0)\n  DWrite!InnerComObject&lt;DWriteFactory,DWriteGdiInterop&gt; : 0 (0x0)\n\n<span style=\"color: #0000ff\">Number<\/span> of entries <span style=\"color: #0000ff\">for<\/span> ID vtableCache : 605\n\n[+] This mona.py action took 0:00:00.219000<\/p><\/pre>\n<p>You can also filter using the -value argument:<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:015&gt; <strong><font color=\"#ffff00\">!py mona kb -list -id vtableCache -value CButton<\/font><\/strong>\nHold on...\n\n<span style=\"color: #0000ff\">Number<\/span> of IDs <span style=\"color: #0000ff\">in<\/span> Knowledgebase : 1\nEntries <span style=\"color: #0000ff\">for<\/span> ID vtableCache (type dict) :\n------------------------------------------\n  (Filter : CButton)\n  MSHTML!CButton : 0 (0x0)\n  MSHTML!CButtonLayout : 256 (0x100)\n  mshtml!CButtonLayout : 256 (0x100)\n\n<span style=\"color: #0000ff\">Number<\/span> of filtered entries <span style=\"color: #0000ff\">for<\/span> ID vtableCache : 3\n\n[+] This mona.py action took 0:00:00.016000<\/pre>\n<p>To remove an entry from the list, use the &quot;del&quot; function :<\/p>\n<pre style=\"border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #252525; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px\">0:015&gt; <strong><font color=\"#ffff00\">!py mona kb -del -id vtableCache -value mshtml!CButtonLayout<\/font><\/strong>\nHold on...\n\n*** Object mshtml!CButtonLayout <span style=\"color: #0000ff\">in<\/span> ID vtableCache removed from Knowledgebase\n\n[+] This mona.py action took 0:00:00.032000\n\n0:015&gt; <strong><font color=\"#ffff00\">!py mona kb -list -id vtableCache -value CButton<\/font><\/strong>\nHold on...\n\n<span style=\"color: #0000ff\">Number<\/span> of IDs <span style=\"color: #0000ff\">in<\/span> Knowledgebase : 1\nEntries <span style=\"color: #0000ff\">for<\/span> ID vtableCache (type dict) :\n------------------------------------------\n  (Filter : CButton)\n  MSHTML!CButton : 0 (0x0)\n  MSHTML!CButtonLayout : 256 (0x100)\n\n<span style=\"color: #0000ff\">Number<\/span> of filtered entries <span style=\"color: #0000ff\">for<\/span> ID vtableCache : 2\n\n[+] This mona.py action took 0:00:00<\/pre>\n<p>Note : if you omit the -value parameter, the entire ID object will be removed.&#160; No big deal, because mona.py will recreate the ID automatically, any manual changes to the list will be lost.&#160; In any case, don't edit the windbglib.db file&#160; yourself.&#160; If it gets corrupted, remove it &amp; let mona.py create a new one.<\/p>\n<p>&#160;<\/p>\n<p>If you have further questions about mona : <a title=\"https:\/\/www.corelan.be\/index.php\/forum\/mona\/\" href=\"https:\/\/www.corelan.be\/index.php\/forum\/mona\/\">https:\/\/www.corelan.be\/index.php\/forum\/mona\/<\/a><\/p>\n<p>Have a great week-end !<\/p>\n<p>-peter<\/p>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Time flies. Almost 3 weeks have passed since we announced the ability to run mona.py under WinDBG.&#160; A lot of work has been done on mona.py in the meantime.&#160; 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 &hellip; <a href=\"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> \"Heap Layout Visualization with mona.py and WinDBG\"<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[3708,244,245,3180,127,3187],"tags":[3732,2802,2576,2171,2124,1478,285,261],"class_list":["post-9637","post","type-post","status-publish","format-standard","hentry","category-debugging","category-exploit-writing-tutorials","category-exploits","category-mona","category-security","category-tools-security","tag-heap-exploitation","tag-mona-py","tag-debugging","tag-corelanc0d3r","tag-debugger","tag-plugin","tag-windbg","tag-corelan"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Heap Layout Visualization with mona.py and WinDBG - Corelan | Exploit Development &amp; Vulnerability Research<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Heap Layout Visualization with mona.py and WinDBG - Corelan | Exploit Development &amp; Vulnerability Research\" \/>\n<meta property=\"og:description\" content=\"Introduction Time flies. Almost 3 weeks have passed since we announced the ability to run mona.py under WinDBG.&#160; A lot of work has been done on mona.py in the meantime.&#160; 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 &hellip; Continue reading &quot;Heap Layout Visualization with mona.py and WinDBG&quot;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/\" \/>\n<meta property=\"og:site_name\" content=\"Corelan | Exploit Development &amp; Vulnerability Research\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/corelanconsulting\" \/>\n<meta property=\"article:published_time\" content=\"2013-01-18T16:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-22T09:04:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb2.png\" \/>\n<meta name=\"author\" content=\"corelanc0d3r\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@corelanc0d3r\" \/>\n<meta name=\"twitter:site\" content=\"@corelanc0d3r\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/\"},\"author\":{\"name\":\"corelanc0d3r\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#\\\/schema\\\/person\\\/3be5542b9b0a0787893db83a5ad68e8f\"},\"headline\":\"Heap Layout Visualization with mona.py and WinDBG\",\"datePublished\":\"2013-01-18T16:00:00+00:00\",\"dateModified\":\"2026-03-22T09:04:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/\"},\"wordCount\":2300,\"publisher\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2013\\\/01\\\/image_thumb2.png\",\"keywords\":[\"heap exploitation\",\"mona.py\",\"debugging\",\"corelanc0d3r\",\"debugger\",\"plugin\",\"windbg\",\"corelan\"],\"articleSection\":[\"Debugging\",\"Exploit Writing Tutorials\",\"Exploits\",\"mona\",\"Security\",\"Tools\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/\",\"name\":\"Heap Layout Visualization with mona.py and WinDBG - Corelan | Exploit Development &amp; Vulnerability Research\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2013\\\/01\\\/image_thumb2.png\",\"datePublished\":\"2013-01-18T16:00:00+00:00\",\"dateModified\":\"2026-03-22T09:04:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2013\\\/01\\\/image_thumb2.png\",\"contentUrl\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2013\\\/01\\\/image_thumb2.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2013\\\/01\\\/18\\\/heap-layout-visualization-with-mona-py-and-windbg\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.corelan.be\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Heap Layout Visualization with mona.py and WinDBG\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#website\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/\",\"name\":\"Corelan CyberSecurity Research\",\"description\":\"Corelan publishes in-depth tutorials on exploit development, Windows exploitation, vulnerability research, heap internals, reverse engineering and security tooling used by professionals worldwide.\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.corelan.be\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#organization\",\"name\":\"Corelan CyberSecurity Research\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/corelanlogo2_small-20.png\",\"contentUrl\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/corelanlogo2_small-20.png\",\"width\":200,\"height\":200,\"caption\":\"Corelan CyberSecurity Research\"},\"image\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/corelanconsulting\",\"https:\\\/\\\/x.com\\\/corelanc0d3r\",\"https:\\\/\\\/x.com\\\/corelanconsulting\",\"https:\\\/\\\/instagram.com\\\/corelanconsult\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#\\\/schema\\\/person\\\/3be5542b9b0a0787893db83a5ad68e8f\",\"name\":\"corelanc0d3r\",\"pronouns\":\"he\\\/him\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x\",\"caption\":\"corelanc0d3r\"},\"description\":\"Peter Van Eeckhoutte is the founder of Corelan and a globally recognized expert in exploit development and vulnerability research. With over two decades in IT security, he built Corelan into a respected platform for deep technical research, hands-on training, and knowledge sharing. Known for his influential exploit development tutorials, tools, and real-world training, Peter combines a strong research mindset with a passion for education\u2014helping security professionals understand not just how exploits work, but why.\",\"sameAs\":[\"https:\\\/\\\/www.corelan-training.com\",\"https:\\\/\\\/instagram.com\\\/corelanc0d3r\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/petervaneeckhoutte\\\/\",\"https:\\\/\\\/x.com\\\/corelanc0d3r\"],\"url\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/author\\\/admin0\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Heap Layout Visualization with mona.py and WinDBG - Corelan | Exploit Development &amp; Vulnerability Research","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/","og_locale":"en_US","og_type":"article","og_title":"Heap Layout Visualization with mona.py and WinDBG - Corelan | Exploit Development &amp; Vulnerability Research","og_description":"Introduction Time flies. Almost 3 weeks have passed since we announced the ability to run mona.py under WinDBG.&#160; A lot of work has been done on mona.py in the meantime.&#160; 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 &hellip; Continue reading \"Heap Layout Visualization with mona.py and WinDBG\"","og_url":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/","og_site_name":"Corelan | Exploit Development &amp; Vulnerability Research","article_publisher":"https:\/\/www.facebook.com\/corelanconsulting","article_published_time":"2013-01-18T16:00:00+00:00","article_modified_time":"2026-03-22T09:04:25+00:00","og_image":[{"url":"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb2.png","type":"","width":"","height":""}],"author":"corelanc0d3r","twitter_card":"summary_large_image","twitter_creator":"@corelanc0d3r","twitter_site":"@corelanc0d3r","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/#article","isPartOf":{"@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/"},"author":{"name":"corelanc0d3r","@id":"https:\/\/www.corelan.be\/#\/schema\/person\/3be5542b9b0a0787893db83a5ad68e8f"},"headline":"Heap Layout Visualization with mona.py and WinDBG","datePublished":"2013-01-18T16:00:00+00:00","dateModified":"2026-03-22T09:04:25+00:00","mainEntityOfPage":{"@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/"},"wordCount":2300,"publisher":{"@id":"https:\/\/www.corelan.be\/#organization"},"image":{"@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/#primaryimage"},"thumbnailUrl":"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb2.png","keywords":["heap exploitation","mona.py","debugging","corelanc0d3r","debugger","plugin","windbg","corelan"],"articleSection":["Debugging","Exploit Writing Tutorials","Exploits","mona","Security","Tools"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/","url":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/","name":"Heap Layout Visualization with mona.py and WinDBG - Corelan | Exploit Development &amp; Vulnerability Research","isPartOf":{"@id":"https:\/\/www.corelan.be\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/#primaryimage"},"image":{"@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/#primaryimage"},"thumbnailUrl":"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb2.png","datePublished":"2013-01-18T16:00:00+00:00","dateModified":"2026-03-22T09:04:25+00:00","breadcrumb":{"@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/#primaryimage","url":"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb2.png","contentUrl":"https:\/\/www.corelan.be\/wp-content\/uploads\/2013\/01\/image_thumb2.png"},{"@type":"BreadcrumbList","@id":"https:\/\/www.corelan.be\/index.php\/2013\/01\/18\/heap-layout-visualization-with-mona-py-and-windbg\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.corelan.be\/"},{"@type":"ListItem","position":2,"name":"Heap Layout Visualization with mona.py and WinDBG"}]},{"@type":"WebSite","@id":"https:\/\/www.corelan.be\/#website","url":"https:\/\/www.corelan.be\/","name":"Corelan CyberSecurity Research","description":"Corelan publishes in-depth tutorials on exploit development, Windows exploitation, vulnerability research, heap internals, reverse engineering and security tooling used by professionals worldwide.","publisher":{"@id":"https:\/\/www.corelan.be\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.corelan.be\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.corelan.be\/#organization","name":"Corelan CyberSecurity Research","url":"https:\/\/www.corelan.be\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.corelan.be\/#\/schema\/logo\/image\/","url":"https:\/\/www.corelan.be\/wp-content\/uploads\/2026\/03\/corelanlogo2_small-20.png","contentUrl":"https:\/\/www.corelan.be\/wp-content\/uploads\/2026\/03\/corelanlogo2_small-20.png","width":200,"height":200,"caption":"Corelan CyberSecurity Research"},"image":{"@id":"https:\/\/www.corelan.be\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/corelanconsulting","https:\/\/x.com\/corelanc0d3r","https:\/\/x.com\/corelanconsulting","https:\/\/instagram.com\/corelanconsult"]},{"@type":"Person","@id":"https:\/\/www.corelan.be\/#\/schema\/person\/3be5542b9b0a0787893db83a5ad68e8f","name":"corelanc0d3r","pronouns":"he\/him","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x","url":"https:\/\/secure.gravatar.com\/avatar\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x","caption":"corelanc0d3r"},"description":"Peter Van Eeckhoutte is the founder of Corelan and a globally recognized expert in exploit development and vulnerability research. With over two decades in IT security, he built Corelan into a respected platform for deep technical research, hands-on training, and knowledge sharing. Known for his influential exploit development tutorials, tools, and real-world training, Peter combines a strong research mindset with a passion for education\u2014helping security professionals understand not just how exploits work, but why.","sameAs":["https:\/\/www.corelan-training.com","https:\/\/instagram.com\/corelanc0d3r","https:\/\/www.linkedin.com\/in\/petervaneeckhoutte\/","https:\/\/x.com\/corelanc0d3r"],"url":"https:\/\/www.corelan.be\/index.php\/author\/admin0\/"}]}},"views":25903,"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/posts\/9637","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/comments?post=9637"}],"version-history":[{"count":1,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/posts\/9637\/revisions"}],"predecessor-version":[{"id":14047,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/posts\/9637\/revisions\/14047"}],"wp:attachment":[{"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/media?parent=9637"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/categories?post=9637"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/tags?post=9637"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}