Work-around for page heap "reallocate in place" false positive.

TL;DR: verifier.dll has a bug where it falsely reports heap corruption. I've found a work-around.

While testing a new fuzzer in Chrome, verifier.dll started reporting heap corruption when a memory chunk was being freed. The report stated that a DWORD at 14 bytes before the start of the chunk was corrupted. When running with page heap enabled, each heap chunk gets a header that contains some information about the chunk. Whenever a heap function is called, the code in verifier.dll does a sanity check on this is information to see if it has been corrupted. This chunk was failing that check.

My repro could reliably trigger this issue and the chunk in which the corruption happened was always the same. I therefore assumed this was an out-of-bounds write in Chrome caused by a negative offset, so I tried to determine where in the Chrome code the instruction that corrupted this memory was. To that effect, I set a memory write breakpoint immediately after the chunk was allocated and output the value that was stored there. But when I ran Chrome the breakpoint did not trigger and the value was not changed even though verifier.dll was still reporting corruption when the chunk was freed.

So, I Googled the error code verifier.dll gave me and found that someone had reported a bug in verifier.dll two years ago that looked like it might be what was going on here: the value stored at the "corrupted" location contains the size of the memory allocation, which consists of whole pages (0x1000 bytes in my case). Stored immediately before this location is the size in bytes of the memory chunk. Verifier.dll checks that rounding the size in bytes value up to whole pages is the same as the size in pages value. So, if you allocate 0x5050 bytes, these two values would be 0x5050 and 0x6000, which would pass this test. However, if you reallocate this chunk in place to a smaller size (say 0x4000), page heap does not shrink the memory allocation and only updates the size in bytes. The values will now be 0x4000 and 0x6000, which will fail this test and Verifier.dll incorrectly reports that the header has been corrupted.

To work around this issue, simply updating the size of the memory allocation in pages after a reallocation seems to work. To do so, I created a WinDBG command that sets a breakpoint on the reallocation handling code in verifier.dll. When the breakpoint is hit, it checks if the reallocation will shrink the chunk. If it will, it continues the reallocation function until it returns. The function will return the address of the reallocated memory chunk in @eax. If this address is the same as the one passed in the arguments, the reallocation was in place. In this case, the heap allocation size in the header is updated to prevent triggering this bug. This means that this value is no longer correct in that the actual allocation is larger, but AFAIK this does not cause any problems.

It would more sense to fix this with a shim, but I haven't the time to develop one myself. But please do let me know if you create one!

Here is the WinDBG work around:

bp verifier!AVrfDebugPageHeapReAllocate "r $t0=poi(@esp+0xC);.if (dwo(@$t0-18) > dwo(@esp+10)) {.printf \"Reallocate shrink %X -> %X @ %X\\r\\n\",dwo(@$t0-18),dwo(@esp+10),@$t0;~.gu;.if(@$t0==@eax) {r @$t1=(dwo(@$t0-18)+0xfff)&0xFFFFF000;.printf \"Update page heap data %X->%X\\r\\n\",dwo(@$t0-14),@$t1;ed @$t0-14 @$t1};g}.else{g}"
Update:The original work-around used "gu", which might cause issues in multi-threaded processes. Replacing this with "~.gu" appears to fix the issue, as this prevents other threads from running, and thus interfering with the execution.

If you have a minute to spare, please up-vote this bug to put some pressure on Microsoft to fix it.


1502F - MSIE8-11 VBScript CSubMacthes::get_Item out-of-bounds read

TL;DR: Details on CVE-2015-1684: an arbitrary read vulnerability in VBScript regular expressions that affected all version of MSIE, which was fixed by Microsoft in MS15-043 one month ago.


When a VBScript RegExp object is created with an expression that contains a sub match "(...)" inside a look-ahead "(?=...)", and the Execute method is then used to successfully match against a string, the resulting Matches collection will contain Match objects that (under the hood) only store the matched string and do not store the matched look-ahead. However, the SubMatches property can be used to try to read data from within the look-ahead. This results in a controlable out-of-bounds read relative to the addresss of the matched string data. Since the size of the matched string is attacker controlled, as is the time of allocation, heap feng-shui techniques may be used to put it in a useful position relative to memory that contains sensitive information the attacker wants to read. Also, if the matched string is empty a NULL ptr is used as the base, resulting in an absolute read.


<script language="VBScript">
  Dim oRegExp
  Set oRegExp = New RegExp
  oRegExp.Pattern = "A+(?=0B+([^.]+)*)"
  ' Allocate 0x10 bytes, then read 0x4 bytes at offset 0x12.


1501H - MSIE 8 - F12 Developer Tools tooltips use-after-free

TL;DR: Full disclosure of low risk 0-day in MSIE 8 after 60-day deadline passed without a fix.


Open a new tab, and then open the Developer Tools by pressing F12, or selecting it from the "Tools" menu. Then select the "Scripts" tab in the Developer Tools window. Next hover the mouse over one of the buttons with the text "Start Debugging", "Run Script" and "Multi Line Mode"/"Single Line Mode". When a tooltip is shown, click the button.At this point, memory that was freed is accessed. When running MSIE with page heap enabled, you will see an access violation exception.


Because the attacker vector appears highly unlikely to represent a risk to any user, I did not bother to do an in-depth investigation. However, the use-after- free occurs in the same process in which the web-page is rendered. This suggests that there may be a way for the web-page to reallocate the freed memory before its reuse and potentially exploit this issue. However, it appears that the free and re-use occur in a very short time span, which would make that rather hard if not impossible.


I allow vendors 60 days to fix an issue, unless they can provide an adequate reason for extending this deadline. Failure to meet a deadline without an adequate explanation will normally result in public disclosure of information regarding the vulnerability to the general public.


  • 23 January 2015: vulnerability discovered and reported to MSRC by email.
  • 23 January 2015: email from MSRC acknowledges receipt of report.
  • 25 March 2015: email to MSRC to notify them that deadline has been exceeded.
  • 25 March 2015: Full disclosure of vulnerability details.


Heap feng shui

I finally got around to play with Alexander Sotirov's new heap tricks for attacking browsers. In short: Alexander has reversed the way heap gets allocated and freed in IE and written some tools in JavaScript that allow you to control heap allocations. Where normal heap spraying is quick and dirty and gets the job done often enough, this gives you the control to make an exploit truely reliable. It does take a very deep understanding of the internals of process heaps and how vulnerabilities are actually exploited to understand how it works, which is good because script kiddies suck.


Exterminate - Mandelbrot Fractal Zoom Music Video

Five animated zooms into the Mandelbrot set, morphed into one another and synchronized to music. By slowly increasing the number of iterations as we zoom in, we can see the fractal grow. You can watch it on YouTube. Technical details are max. iterations: 6000, max. zoom: 6.2e+14, total rendered frames: 2310 (at 320x240), time to design and create the complete animation: ~50 hrs., rendering time: ~2hrs, rendering software: Ultra Fractal 4.03, video software: VisualDub 1.6.17, music: Snap! - Exterminate, full AVI size: 57.4Mb.


Ascii Art Mandelbrot Fractal Zoom

As part of my DHTML++ demo, I wrote an ASCII Art Mandebrot Fractal zoomer. Unfortunately, the current version is waaaay to slow to calculate the frames in real-time. Apparently they did not optimize JavaScript in Internet Explorer for rendering fractals in real time. I am working on a much smarter algorithm, which only calculates the fractal once. I intend to use variable accuracy. This means I can get more detail around the area I zoom in to, so I do not need to recalculate the fractal for every frame. However, this is a bit more complex than it sounds, so don't hold your breath. In the mean time, here's an example of what it will look like.


VBScript Functions for JavaScript

If you're used to languages like JavaScript, C and Java, then VBScript can be a pain to code. But VBScript does offer a number of useful features that JavaScript does not, such as MsgBox, InputBox and String. To make these easily available in JavaScript, I have created a script that creates an object that works as a wrapper for these functions in JavaScript. The object has a method for each VBScript function, which can be used to call these functions. This allows you to use them from JavaScript as if they were a normal part of JavaScript.

To use the script, download it from http://skypher.com/SkyLined/download/vbs.js/vbs.js, put it on your server and add this tag to you HTML file:
<SCRIPT src="vbs.js" type="text/javascript" language="JavaScript"></SCRIPT>

Any script that runs after this script will have access to an object called "vbs", which has a number of properties and methods that can be used to access VBScript features.

Properties: (See MsgBox function documentation at MSDN)
vbOKOnly, vbOKCancel, vbAbortRetryIgnore, vbYesNoCancel, vbYesNo, vbRetryCancel, vbCritical, vbQuestion, vbExclamation, vbInformation, vbDefaultButton1, vbDefaultButton2, vbDefaultButton3, vbDefaultButton4, vbApplicationModal, vbSystemModal

Methods: (see VBScript functions reference at MSDN)
Abs, Array, Asc, Atn, CBool, CByte, CCur, CDate, CDbl, Chr, CInt, CLng, Cos, CreateObject, CSng, CStr, Date, DateAdd, DateDiff, DatePart, DateSerial, DateValue, Day, Escape, Eval, Exp, Filter, Fix, FormatCurrency, FormatDatTime, FormatNumber, FormatPercent, GetLocale, GetObject, GetRef, Hex, Hour, InputBox, InStr, InStrRev, Int, IsArray, IsDate, IsEmpty, IsNull, IsNumeric, IsObject, Join, LBound, LCase, Left, Len, LoadPicture, Log, LTrim, Mid, Minute, Month, MonthName, MsgBox, Now, Oct, Replace, RGB, Right, Rnd, Round, RTrim, ScriptEngine, ScriptEngineBuildVersion, ScriptEngineMajorVersion, ScriptEngineMinorVersion, Second, SetLocale, Sgn, Sin, Space, Split, Sqr, StrComp, String, StrReverse, Tan, Time, Timer, TimeSerial, TimeValue, Trim, TypeName, UBound, UCase, Unescape, VarType, Weekday, WeekDayName, Year

vbs.MsgBox("Hello, world!", vbs.vbOKOnly | vbs.vbInformation, "JavaScript");

JavaScript Shell v4.2beta

Topic moved to http://skypher.com.