Lucene search
K

Windows Gather Virtual Environment Detection

🗓️ 17 Sep 2023 22:05:47Reported by Carlos Perez <[email protected]>, Aaron Soto <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 242 Views

This module detects virtual environments on Windows systems and supports detection of Hyper-V, VMWare, VirtualBox, Xen, QEMU, and Parallels

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Post
  include Msf::Post::Windows::Process
  include Msf::Post::Windows::Registry
  include Msf::Auxiliary::Report

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Windows Gather Virtual Environment Detection',
        'Description' => %q{
          This module attempts to determine whether the system is running
          inside of a virtual environment and if so, which one. This
          module supports detection of Hyper-V, VMWare, VirtualBox, Xen, QEMU,
          and Parallels.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'Carlos Perez <carlos_perez[at]darkoperator.com>',
          'Aaron Soto <aaron_soto[at]rapid7.com>'
        ],
        'Platform' => [ 'win' ],
        'SessionTypes' => %w[meterpreter powershell shell],
        'References' => [
          ['URL', 'https://handlers.sans.org/tliston/ThwartingVMDetection_Liston_Skoudis.pdf'],
          ['URL', 'https://www.heise.de/security/downloads/07/1/1/8/3/5/5/9/vmde.pdf'],
          ['URL', 'https://evasions.checkpoint.com/techniques/registry.html']
        ],
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [],
          'SideEffects' => []
        }
      )
    )
  end

  # enumerates through a list of VM signature processes and compares them to
  # the processes running, returns true upon a match.
  def processes_exist?(vm_processes)
    vm_processes.each do |x|
      @processes.each do |p|
        return true if p['name'].casecmp?(x)
      end
    end
    false
  end

  # loops over a list of services that are known to be signatures of vm's and
  # compares them to the list of running services.
  def services_exist?(vm_services)
    vm_services.each do |srvc|
      return true if service_exists?(srvc)
    end
    false
  end

  def service_exists?(service)
    @services.include?(service)
  end

  # registers relevant keys and stores them in a hash
  def register_keys(key_list)
    @keys = {}
    key_list.each do |k|
      srvals = get_srval(k)
      srvals = [] if srvals.nil?
      @keys.store(k, srvals)
    end
    @keys
  end

  # checks the values of the keys and compares them to vm_k
  def key_present?(vm_k)
    @keys.each_value do |v|
      return true if v.include?(vm_k)
    end
    false
  end

  def get_srval(key)
    srvals = registry_enumkeys(key)
    srvals = [] if srvals.nil?
    srvals
  end

  # returns true if regval matches a regex
  def regval_match?(key, val, rgx)
    return true if get_regval_str(key, val) =~ rgx

    false
  end

  # returns true if regval is eql to a string
  def regval_eql?(key, val, str)
    get_regval_str(key, val) == str
  end

  def get_regval_str(key, valname)
    ret = registry_getvaldata(key, valname)
    if ret.is_a?(Array)
      ret = ret.join
    end
    ret
  end

  def parallels?
    @system_bios_version = get_regval_str('HKLM\\HARDWARE\\DESCRIPTION\\System', 'SystemBiosVersion')

    @video_bios_version = get_regval_str('HKLM\\HARDWARE\\DESCRIPTION\\System', 'VideoBiosVersion')

    if @system_bios_version =~ /parallels/i || @video_bios_version =~ /parallels/i
      return true
    end

    false
  end

  def hyperv?
    physical_host = get_regval_str('HKLM\\SOFTWARE\\Microsoft\\Virtual Machine\\Guest\\Parameters', 'PhysicalHostNameFullyQualified')

    if physical_host
      report_note(
        host: session,
        type: 'host.physicalHost',
        data: { physicalHost: physical_host },
        update: :unique_data
      )

      print_good("This is a Hyper-V Virtual Machine running on physical host #{physical_host}")
      return true
    end

    sfmsvals = registry_enumkeys('HKLM\\SOFTWARE\\Microsoft')
    if sfmsvals
      %w[Hyper-V VirtualMachine].each do |vm|
        return true if sfmsvals.include?(vm)
      end
    end

    if @system_bios_version =~ /vrtual/i || @system_bios_version == 'Hyper-V'
      return true
    end

    keys = %w[HKLM\\HARDWARE\\ACPI\\FADT HKLM\\HARDWARE\\ACPI\\RSDT HKLM\\HARDWARE\\ACPI\\DSDT]

    register_keys(keys)

    return true if key_present?('VRTUAL')

    hyperv_services = %w[vmicexchange]

    return true if services_exist?(hyperv_services)

    false
  end

  def vmware?
    vmware_services = %w[
      vmdebug vmmouse VMTools VMMEMCTL tpautoconnsvc
      tpvcgateway vmware wmci vmx86
    ]

    return true if services_exist?(vmware_services)

    @system_manufacturer = get_regval_str('HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS',
                                          'SystemManufacturer')

    return true if @system_manufacturer =~ /vmware/i

    @scsi_port_1 = get_regval_str('HKLM\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0',
                                  'Identifier')

    return true if @scsi_port_1 =~ /vmware/i

    return true if regval_match?(
      'HKLM\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000',
      'DriverDesc',
      /cl_vmx_svga|VMWare/i
    )


    vmwareprocs = [
      'vmtoolsd.exe',
      'vmwareservice.exe',
      'vmwaretray.exe',
      'vmwareuser.exe'
    ]

    return true if processes_exist?(vmwareprocs)

    false
  end

  def virtualbox?
    vboxprocs = [
      'vboxservice.exe',
      'vboxtray.exe'
    ]

    vbox_srvcs = %w[VBoxMouse VBoxGuest VBoxService VBoxSF VBoxVideo]

    if services_exist?(vbox_srvcs) || processes_exist?(vboxprocs)
      return true
    end

    return true if key_present?('VBOX__')

    for i in 0..2 do
      return true if regval_match?(
        "HKLM\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port #{i}0\\Scsi Bus 0\\Target
         Id 0\\Logical Unit Id 0",
        'Identifier',
        /vbox/i
      )
    end

    return true if @system_bios_version =~ /vbox/i || @video_bios_version =~ /virtualbox/i

    @system_product_name = get_regval_str('HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS', 'SystemProductName')

    return true if @system_product_name =~ /virtualbox/i

    false
  end

  def xen?
    xenprocs = [
      'xenservice.exe'
    ]

    xen_srvcs = %w[xenevtchn xennet xennet6 xensvc xenvdb]

    if processes_exist?(xenprocs) || services_exist?(xen_srvcs)
      return true
    end

    return true if key_present?('Xen')

    return true if @system_product_name =~ /xen/i

    false
  end

  def qemu?
    if @system_bios_version =~ /qemu/i || @video_bios_version =~ /qemu/i
      return true
    end

    if @scsi_port_0 =~ /qemu|virtio/i || @system_manufacturer =~ /qemu/i
      return true
    end

    return true if regval_match?(
      'HKLM\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0',
      'ProcessorNameString',
      /qemu/i
    )

    return true if key_present?('BOCHS_')

    false
  end

  def report_vm(hypervisor)
    print_good("This is a #{hypervisor} Virtual Machine")
    report_note(
      host: session,
      type: 'host.hypervisor',
      data: { hypervisor: hypervisor },
      update: :unique_data
    )
    report_virtualization(hypervisor)
  end

  def run
    print_status('Checking if the target is a Virtual Machine ...')
    @processes = get_processes
    @processes = [] if @processes.nil?

    @services = registry_enumkeys('HKLM\\SYSTEM\\ControlSet001\\Services')
    @services = [] if @services.nil?

    if parallels?
      report_vm('Parallels')
    elsif hyperv?
      report_vm('Hyper-V')
    elsif vmware?
      report_vm('VMware')
    elsif virtualbox?
      report_vm('VirtualBox')
    elsif xen?
      report_vm('Xen')
    elsif qemu?
      report_vm('Qemu/KVM')
    else
      print_status('The target appears to be a Physical Machine')
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation