parent
eec70706d0
commit
7a71d22625
|
@ -97,6 +97,26 @@ class RemoteEsxDriver < VmDriver
|
|||
def delete_all_snapshots
|
||||
remote_system_command("vim-cmd vmsvc/snapshot.removeall #{@vmid}")
|
||||
end
|
||||
|
||||
def run_command(command)
|
||||
raise "Not Implemented"
|
||||
end
|
||||
|
||||
def copy_from_guest(from, to)
|
||||
if @os == "linux"
|
||||
scp_from(from, to)
|
||||
else
|
||||
raise "Unimplemented"
|
||||
end
|
||||
end
|
||||
|
||||
def copy_to_guest(from, to)
|
||||
if @os == "linux"
|
||||
scp_to(from, to)
|
||||
else
|
||||
raise "Unimplemented"
|
||||
end
|
||||
end
|
||||
|
||||
def check_file_exists(file)
|
||||
raise "Not Implemented"
|
||||
|
@ -106,137 +126,16 @@ class RemoteEsxDriver < VmDriver
|
|||
raise "Not Implemented"
|
||||
end
|
||||
|
||||
def run_command(command, timeout=60)
|
||||
|
||||
setup_session
|
||||
#puts "Using session #{@session}"
|
||||
|
||||
# TODO: pass the timeout down
|
||||
|
||||
if @session
|
||||
if @session.type == "shell"
|
||||
#puts "Running command via shell: #{command}"
|
||||
@session.shell_command_token(command, timeout)
|
||||
elsif @session.type == "meterpreter"
|
||||
#puts "Running command via meterpreter: #{command}"
|
||||
@session.shell_command(command)
|
||||
end
|
||||
else
|
||||
raise "No session"
|
||||
end
|
||||
end
|
||||
|
||||
def copy_to_guest(local,remote)
|
||||
setup_session
|
||||
if @session.type == "meterpreter"
|
||||
@session.run_cmd("upload #{local} #{remote}")
|
||||
else
|
||||
@driver.copy_to(local,remote)
|
||||
end
|
||||
end
|
||||
|
||||
def copy_from_guest(local, remote)
|
||||
setup_session
|
||||
if @session.type == "meterpreter"
|
||||
@session.run_cmd("download #{local} #{remote}")
|
||||
else
|
||||
@driver.copy_from(local,remote)
|
||||
end
|
||||
end
|
||||
|
||||
def cleanup
|
||||
|
||||
end
|
||||
|
||||
def running?
|
||||
power_status_string = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.getstate #{@vmid}\"`
|
||||
return true if power_status_string =~ /Powered on/
|
||||
#power_status_string = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.getstate #{@vmid}\"`
|
||||
#return true if power_status_string =~ /Powered on/
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_framework
|
||||
return if @framework
|
||||
@framework = Msf::Simple::Framework.create
|
||||
end
|
||||
|
||||
# perform the setup only once
|
||||
def setup_session
|
||||
return if @session
|
||||
|
||||
# require the framework (assumes this sits in lib/lab/modifiers)
|
||||
require 'msf/base'
|
||||
|
||||
create_framework # TODO - this should use a single framework for all hosts, not one-per-host
|
||||
|
||||
@session = nil
|
||||
@session_input = Rex::Ui::Text::Input::Buffer.new
|
||||
@session_output = Rex::Ui::Text::Output::Buffer.new
|
||||
|
||||
if @os == "windows"
|
||||
exploit_name = 'windows/smb/psexec'
|
||||
|
||||
# TODO - check for x86, choose the appropriate payload
|
||||
|
||||
payload_name = 'windows/meterpreter/bind_tcp'
|
||||
options = {
|
||||
"RHOST" => @hostname,
|
||||
"SMBUser" => @vm_user,
|
||||
"SMBPass" => @vm_pass}
|
||||
|
||||
#puts "DEBUG: using options #{options}"
|
||||
|
||||
# Initialize the exploit instance
|
||||
exploit = @framework.exploits.create(exploit_name)
|
||||
|
||||
begin
|
||||
# Fire it off.
|
||||
@session = exploit.exploit_simple(
|
||||
'Payload' => payload_name,
|
||||
'Options' => options,
|
||||
'LocalInput' => @session_input,
|
||||
'LocalOutput' => @session_output)
|
||||
@session.load_stdapi
|
||||
|
||||
#puts "DEBUG: Generated session: #{@session}"
|
||||
|
||||
rescue Exception => e
|
||||
#puts "DEBUG: Unable to exploit"
|
||||
#puts e.to_s
|
||||
end
|
||||
else
|
||||
module_name = 'scanner/ssh/ssh_login'
|
||||
|
||||
# TODO - check for x86, choose the appropriate payload
|
||||
|
||||
payload_name = 'linux/x86/shell_bind_tcp'
|
||||
options = { "RHOSTS" => @hostname,
|
||||
"USERNAME" => @vm_user,
|
||||
"PASSWORD" => @vm_pass,
|
||||
"BLANK_PASSWORDS" => false,
|
||||
"USER_AS_PASS" => false,
|
||||
"VERBOSE" => false}
|
||||
|
||||
# Initialize the module instance
|
||||
aux = @framework.auxiliary.create(module_name)
|
||||
|
||||
#puts "DEBUG: created module: #{aux}"
|
||||
|
||||
begin
|
||||
# Fire it off.
|
||||
aux.run_simple(
|
||||
'Payload' => payload_name,
|
||||
'Options' => options,
|
||||
'LocalInput' => @session_input,
|
||||
'LocalOutput' => @session_output)
|
||||
|
||||
@session = @framework.sessions.first.last
|
||||
rescue Exception => e
|
||||
#puts "DEBUG: Unable to exploit"
|
||||
#puts e.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_snapshots
|
||||
# Command take the format:
|
||||
# vmware-vim-cmd vmsvc/snapshot.revert [vmid: int] [snapshotlevel: int] [snapshotindex: int]
|
||||
|
@ -248,7 +147,7 @@ private
|
|||
# ...
|
||||
snapshots = []
|
||||
|
||||
# Use these to keep track of the parsing...
|
||||
# Use these to keep track of the parsing...
|
||||
current_tree = -1
|
||||
current_num = 0
|
||||
count = 0
|
||||
|
|
|
@ -86,11 +86,11 @@ class VmDriver
|
|||
def run_command(command)
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
|
||||
def copy_from_guest(from, to)
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
|
||||
def copy_to_guest(from, to)
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
@ -117,6 +117,7 @@ private
|
|||
#::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
|
||||
# scp.upload!(from,to)
|
||||
#end
|
||||
|
||||
system_command("scp #{local} #{@vm_user}@#{@hostname}:#{remote}")
|
||||
end
|
||||
|
||||
|
@ -126,13 +127,17 @@ private
|
|||
#::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
|
||||
# scp.download!(from,to)
|
||||
#end
|
||||
|
||||
system_command("scp #{@vm_user}@#{@hostname}:#{remote} #{local}")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def ssh_exec(command)
|
||||
|
||||
::Net::SSH.start(@hostname, @vm_user, :password => @vm_pass) do |ssh|
|
||||
result = ssh.exec!(command)
|
||||
end
|
||||
|
||||
`scp #{@vm_user}@#{@hostname} from to`
|
||||
end
|
||||
|
||||
|
@ -143,6 +148,7 @@ private
|
|||
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string
|
||||
raise "WARNING! Invalid character in: #{string}"
|
||||
end
|
||||
|
||||
string
|
||||
end
|
||||
|
||||
|
@ -153,17 +159,18 @@ private
|
|||
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/.match string
|
||||
raise "WARNING! Invalid character in: #{string}"
|
||||
end
|
||||
|
||||
string
|
||||
end
|
||||
|
||||
|
||||
# The only reason we don't filter here is because we need
|
||||
# the ability to still run clean (controlled entirely by us)
|
||||
# command lines.
|
||||
def system_command(command)
|
||||
`#{command}`
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
def remote_system_command(command)
|
||||
system_command("ssh #{@user}@#{@host} \"#{command}\"")
|
||||
end
|
||||
|
|
|
@ -1,73 +1,26 @@
|
|||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# This allows us to override the default way of running commands
|
||||
# Currently useful for the remote esx driver
|
||||
# Currently useful for the esx controller
|
||||
|
||||
module Lab
|
||||
module Modifier
|
||||
module Meterpreter
|
||||
|
||||
|
||||
attr_accessor :framework
|
||||
attr_accessor :session
|
||||
attr_accessor :session_input
|
||||
attr_accessor :session_output
|
||||
|
||||
def meterpreter_run_command(command, timeout=60)
|
||||
|
||||
setup_session
|
||||
puts "Using session #{@session}"
|
||||
|
||||
# TODO: pass the timeout down
|
||||
|
||||
if @session
|
||||
if @session.type == "shell"
|
||||
puts "Running command via shell: #{command}"
|
||||
@session.shell_command_token(command, timeout)
|
||||
elsif @session.type == "meterpreter"
|
||||
puts "Running command via meterpreter: #{command}"
|
||||
@session.shell_command(command) #, timeout)
|
||||
end
|
||||
else
|
||||
raise "No session"
|
||||
end
|
||||
end
|
||||
|
||||
def meterpreter_copy_to_guest(local,remote)
|
||||
puts "DEBUG: Meterpreter"
|
||||
setup_session
|
||||
if @session.type == "meterpreter"
|
||||
@session.run_cmd("upload #{local} #{remote}")
|
||||
else
|
||||
@driver.copy_to(local,remote)
|
||||
end
|
||||
end
|
||||
|
||||
def meterpreter_copy_from_guest(local, remote)
|
||||
puts "DEBUG: Meterpreter"
|
||||
setup_session
|
||||
if @session.type == "meterpreter"
|
||||
@session.run_cmd("download #{local} #{remote}")
|
||||
else
|
||||
@driver.copy_from(local,remote)
|
||||
end
|
||||
end
|
||||
|
||||
# This isn't part of the normal API, but too good to pass up.
|
||||
def meterpreter_run_script(script, options)
|
||||
if @session.type == "meterpreter"
|
||||
@session.execute_script(script, options)
|
||||
else
|
||||
raise "Unsupported on #{@session.type}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_framework
|
||||
return if @framework
|
||||
@framework = Msf::Simple::Framework.create
|
||||
@framework = Msf::Simple::Framework.create
|
||||
end
|
||||
|
||||
|
||||
# perform the setup only once
|
||||
def setup_session
|
||||
return if @session
|
||||
|
@ -75,11 +28,12 @@ private
|
|||
# require the framework (assumes this sits in lib/lab/modifiers)
|
||||
require 'msf/base'
|
||||
|
||||
create_framework # TODO - this should use a single framework for all hosts, not one-per-host
|
||||
create_framework ## TODO - this should use a single framework
|
||||
## for all hosts, not one-per-host
|
||||
|
||||
@session = nil
|
||||
@session_input = Rex::Ui::Text::Input::Buffer.new
|
||||
@session_output = Rex::Ui::Text::Output::Buffer.new
|
||||
@session = nil
|
||||
@session_input = Rex::Ui::Text::Input::Buffer.new
|
||||
@session_output = Rex::Ui::Text::Output::Buffer.new
|
||||
|
||||
if @os == "windows"
|
||||
exploit_name = 'windows/smb/psexec'
|
||||
|
@ -87,12 +41,11 @@ private
|
|||
# TODO - check for x86, choose the appropriate payload
|
||||
|
||||
payload_name = 'windows/meterpreter/bind_tcp'
|
||||
options = {
|
||||
"RHOST" => @hostname,
|
||||
"SMBUser" => @vm_user,
|
||||
"SMBPass" => @vm_pass}
|
||||
options = { "RHOST" => @hostname,
|
||||
"SMBUser" => @vm_user,
|
||||
"SMBPass" => @vm_pass}
|
||||
|
||||
puts "DEBUG: using options #{options}"
|
||||
puts "DEBUG: using options #{options}"
|
||||
|
||||
# Initialize the exploit instance
|
||||
exploit = @framework.exploits.create(exploit_name)
|
||||
|
@ -126,7 +79,7 @@ private
|
|||
"USER_AS_PASS" => false,
|
||||
"VERBOSE" => false}
|
||||
|
||||
puts "DEBUG: using options #{options}"
|
||||
puts "DEBUG: using options #{options}"
|
||||
|
||||
# Initialize the module instance
|
||||
aux = @framework.auxiliary.create(module_name)
|
||||
|
@ -148,7 +101,64 @@ private
|
|||
puts e.to_s
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
def run_command(command, timeout=60)
|
||||
|
||||
setup_session
|
||||
puts "Using session #{@session}"
|
||||
|
||||
# TODO: pass the timeout down
|
||||
|
||||
if @session
|
||||
if @session.type == "shell"
|
||||
puts "Running command via shell: #{command}"
|
||||
@session.shell_command_token(command, timeout)
|
||||
elsif @session.type == "meterpreter"
|
||||
puts "Running command via meterpreter: #{command}"
|
||||
@session.shell_command(command) #, timeout)
|
||||
end
|
||||
else
|
||||
raise "No session"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# This isn't part of the normal API, but too good to pass up.
|
||||
def run_script(script, options)
|
||||
if @session.type == "meterpreter"
|
||||
@session.execute_script(script, options)
|
||||
else
|
||||
raise "Unsupported on #{@session.type}"
|
||||
end
|
||||
end
|
||||
|
||||
# For meterpreter API compatibility
|
||||
#def execute_file(script,options)
|
||||
# run_script(script,options)
|
||||
#end
|
||||
|
||||
def copy_to_guest(local,remote)
|
||||
setup_session
|
||||
if @session.type == "meterpreter"
|
||||
@session.run_cmd("upload #{local} #{remote}")
|
||||
else
|
||||
@driver.copy_to(local,remote)
|
||||
end
|
||||
end
|
||||
|
||||
def copy_from_guest(local, remote)
|
||||
setup_session
|
||||
if @session.type == "meterpreter"
|
||||
@session.run_cmd("download #{local} #{remote}")
|
||||
else
|
||||
@driver.copy_from(local,remote)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -103,15 +103,12 @@ class Vm
|
|||
# modifiers are properly used with the correct VM image.
|
||||
@modifiers = config['modifiers']
|
||||
|
||||
if @modifiers
|
||||
@modifiers.each do |modifier|
|
||||
begin
|
||||
self.class.send(:include, eval("Lab::Modifier::#{modifier}"))
|
||||
rescue Exception => e
|
||||
#puts "WARNING: Unable to load: #{modifier}"
|
||||
#puts "Exception: #{e}"
|
||||
end
|
||||
end
|
||||
if @modifiers
|
||||
begin
|
||||
@modifiers.each { |modifier| self.class.send(:include, eval("Lab::Modifier::#{modifier}"))}
|
||||
rescue Exception => e
|
||||
# modifier likely didn't exist
|
||||
end
|
||||
end
|
||||
|
||||
# Consume all tags
|
||||
|
@ -209,9 +206,11 @@ class Vm
|
|||
end
|
||||
|
||||
def to_yaml
|
||||
|
||||
# TODO - push this down to the drivers.
|
||||
|
||||
# Standard configuration options
|
||||
out = " - vmid: #{@vmid}\n"
|
||||
out = " hostname: #{@hostname}\n"
|
||||
out += " driver: #{@driver_type}\n"
|
||||
out += " location: #{@location}\n"
|
||||
out += " type: #{@type}\n"
|
||||
|
|
|
@ -158,12 +158,12 @@ module Controllers
|
|||
case driver_type.intern
|
||||
when :workstation
|
||||
vm_list = ::Lab::Controllers::WorkstationController::running_list
|
||||
|
||||
|
||||
vm_list.each do |item|
|
||||
|
||||
|
||||
## Name the VM
|
||||
index = @vms.count + 1
|
||||
|
||||
|
||||
## Add it to the vm list
|
||||
@vms << Vm.new( { 'vmid' => "vm_#{index}",
|
||||
'driver' => driver_type,
|
||||
|
@ -171,6 +171,8 @@ module Controllers
|
|||
'user' => user,
|
||||
'host' => host } )
|
||||
end
|
||||
|
||||
|
||||
when :virtualbox
|
||||
vm_list = ::Lab::Controllers::VirtualBoxController::running_list
|
||||
vm_list.each do |item|
|
||||
|
@ -187,10 +189,10 @@ module Controllers
|
|||
vm_list = ::Lab::Controllers::RemoteWorkstationController::running_list(user, host)
|
||||
|
||||
vm_list.each do |item|
|
||||
|
||||
|
||||
## Name the VM
|
||||
index = @vms.count + 1
|
||||
|
||||
|
||||
## Add it to the vm list
|
||||
@vms << Vm.new( { 'vmid' => "vm_#{index}",
|
||||
'driver' => driver_type,
|
||||
|
@ -200,6 +202,7 @@ module Controllers
|
|||
end
|
||||
when :remote_esx
|
||||
vm_list = ::Lab::Controllers::RemoteEsxController::running_list(user,host)
|
||||
|
||||
vm_list.each do |item|
|
||||
@vms << Vm.new( { 'vmid' => "#{item[:id]}",
|
||||
'name' => "#{item[:name]}",
|
||||
|
@ -207,11 +210,12 @@ module Controllers
|
|||
'user' => user,
|
||||
'host' => host } )
|
||||
end
|
||||
|
||||
else
|
||||
raise TypeError, "Unsupported VM Type"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def build_from_config(driver_type=nil, user=nil, host=nil, clear=false)
|
||||
if clear
|
||||
|
@ -230,17 +234,18 @@ module Controllers
|
|||
'user' => user,
|
||||
'host' => host } )
|
||||
end
|
||||
|
||||
else
|
||||
raise TypeError, "Unsupported VM Type"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def running?(vmid)
|
||||
if includes_vmid?(vmid)
|
||||
return self.find_by_hostname(vmid).running?
|
||||
end
|
||||
return false
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -384,6 +384,8 @@ class Plugin::Lab < Msf::Plugin
|
|||
local_path = args[args.count-2]
|
||||
vm_path = args[args.count-1]
|
||||
|
||||
print_line "Copying from #{local_path} to #{vm_path} on #{args[0]}"
|
||||
|
||||
if args[0] == "all"
|
||||
@controller.each do |vm|
|
||||
if vm.running?
|
||||
|
@ -393,7 +395,7 @@ class Plugin::Lab < Msf::Plugin
|
|||
end
|
||||
else
|
||||
args[0..-2].each do |vmid_arg|
|
||||
next unless @controller.includes_hostname? vmid_arg
|
||||
next unless @controller.includes_vmid? vmid_arg
|
||||
if @controller[vmid_arg].running?
|
||||
print_line "Copying from #{local_path} to #{vm_path} on #{vmid_arg}"
|
||||
@controller[vmid_arg].copy_to_guest(local_path, vm_path)
|
||||
|
|
Loading…
Reference in New Issue