2011-01-12 18:29:56 +00:00
|
|
|
##
|
2017-07-24 06:26:21 -07:00
|
|
|
# This module requires Metasploit: https://metasploit.com/download
|
2013-10-15 13:50:46 -05:00
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2011-01-12 18:29:56 +00:00
|
|
|
##
|
2011-01-12 02:16:06 +00:00
|
|
|
|
2016-03-08 14:02:44 +01:00
|
|
|
class MetasploitModule < Msf::Post
|
2021-06-20 10:34:18 +05:30
|
|
|
include Msf::Post::Windows::Process
|
2013-09-05 13:41:25 -05:00
|
|
|
include Msf::Post::Windows::Registry
|
|
|
|
|
include Msf::Auxiliary::Report
|
2011-01-12 02:16:06 +00:00
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
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
|
2023-08-11 14:42:51 +02:00
|
|
|
module supports detection of Hyper-V, VMWare, VirtualBox, Xen, QEMU,
|
|
|
|
|
and Parallels.
|
2020-06-13 22:47:22 +00:00
|
|
|
},
|
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
|
'Author' => [
|
|
|
|
|
'Carlos Perez <carlos_perez[at]darkoperator.com>',
|
|
|
|
|
'Aaron Soto <aaron_soto[at]rapid7.com>'
|
|
|
|
|
],
|
|
|
|
|
'Platform' => [ 'win' ],
|
2022-11-29 21:28:15 +11:00
|
|
|
'SessionTypes' => %w[meterpreter powershell shell],
|
2023-07-11 21:12:50 +02:00
|
|
|
'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']
|
|
|
|
|
],
|
2022-11-29 21:28:15 +11:00
|
|
|
'Notes' => {
|
|
|
|
|
'Stability' => [CRASH_SAFE],
|
|
|
|
|
'Reliability' => [],
|
|
|
|
|
'SideEffects' => []
|
|
|
|
|
}
|
2020-06-13 22:47:22 +00:00
|
|
|
)
|
|
|
|
|
)
|
2011-01-12 02:16:06 +00:00
|
|
|
end
|
|
|
|
|
|
2023-07-22 10:48:40 -04:00
|
|
|
# enumerates through a list of VM signature processes and compares them to
|
2023-07-25 13:30:51 -04:00
|
|
|
# the processes running, returns true upon a match.
|
2023-07-23 08:53:22 -04:00
|
|
|
def processes_exist?(vm_processes)
|
2023-07-22 10:23:09 -04:00
|
|
|
vm_processes.each do |x|
|
|
|
|
|
@processes.each do |p|
|
2023-07-25 13:30:51 -04:00
|
|
|
return true if p['name'].casecmp?(x)
|
|
|
|
|
end
|
|
|
|
|
end
|
2023-07-22 11:07:30 -04:00
|
|
|
false
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-07-22 10:23:09 -04:00
|
|
|
|
2023-07-23 08:39:45 -04:00
|
|
|
# loops over a list of services that are known to be signatures of vm's and
|
2023-07-25 13:30:51 -04:00
|
|
|
# compares them to the list of running services.
|
2023-07-23 08:53:22 -04:00
|
|
|
def services_exist?(vm_services)
|
2023-07-22 10:59:30 -04:00
|
|
|
vm_services.each do |srvc|
|
|
|
|
|
return true if service_exists?(srvc)
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-07-22 11:07:30 -04:00
|
|
|
false
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-07-22 10:59:30 -04:00
|
|
|
|
2020-07-10 18:10:26 +00:00
|
|
|
def service_exists?(service)
|
2023-07-22 11:18:51 -04:00
|
|
|
@services.include?(service)
|
2020-07-10 18:10:26 +00:00
|
|
|
end
|
|
|
|
|
|
2023-07-23 09:10:51 -04:00
|
|
|
# registers relevant keys and stores them in a hash
|
|
|
|
|
def register_keys(key_list)
|
|
|
|
|
@keys = {}
|
|
|
|
|
key_list.each do |k|
|
2023-10-09 15:23:19 -04:00
|
|
|
srvals = get_srval(k)
|
2023-07-25 13:30:51 -04:00
|
|
|
srvals = [] if srvals.nil?
|
|
|
|
|
@keys.store(k, srvals)
|
|
|
|
|
end
|
2023-07-23 09:10:51 -04:00
|
|
|
@keys
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-07-23 09:10:51 -04:00
|
|
|
|
|
|
|
|
# checks the values of the keys and compares them to vm_k
|
|
|
|
|
def key_present?(vm_k)
|
|
|
|
|
@keys.each_value do |v|
|
2023-07-23 09:14:07 -04:00
|
|
|
return true if v.include?(vm_k)
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-10-09 15:24:26 -04:00
|
|
|
false
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-07-22 11:50:07 -04:00
|
|
|
|
2023-07-22 12:26:27 -04:00
|
|
|
def get_srval(key)
|
2023-07-23 09:14:07 -04:00
|
|
|
srvals = registry_enumkeys(key)
|
2023-07-22 11:50:07 -04:00
|
|
|
srvals = [] if srvals.nil?
|
|
|
|
|
srvals
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-07-22 11:50:07 -04:00
|
|
|
|
2023-07-22 12:55:03 -04:00
|
|
|
# returns true if regval matches a regex
|
2023-07-25 13:30:51 -04:00
|
|
|
def regval_match?(key, val, rgx)
|
|
|
|
|
return true if get_regval_str(key, val) =~ rgx
|
|
|
|
|
|
|
|
|
|
false
|
2023-07-22 12:26:27 -04:00
|
|
|
end
|
|
|
|
|
|
2023-07-23 08:49:54 -04:00
|
|
|
# returns true if regval is eql to a string
|
2023-07-25 13:30:51 -04:00
|
|
|
def regval_eql?(key, val, str)
|
|
|
|
|
get_regval_str(key, val) == str
|
|
|
|
|
end
|
2023-07-22 12:55:03 -04:00
|
|
|
|
2023-07-18 19:31:42 +02:00
|
|
|
def get_regval_str(key, valname)
|
|
|
|
|
ret = registry_getvaldata(key, valname)
|
2023-07-25 13:30:51 -04:00
|
|
|
if ret.is_a?(Array)
|
2023-07-18 19:31:42 +02:00
|
|
|
ret = ret.join
|
|
|
|
|
end
|
|
|
|
|
ret
|
|
|
|
|
end
|
|
|
|
|
|
2023-07-22 13:14:17 -04:00
|
|
|
def parallels?
|
2023-07-22 13:19:37 -04:00
|
|
|
@system_bios_version = get_regval_str('HKLM\\HARDWARE\\DESCRIPTION\\System', 'SystemBiosVersion')
|
2023-07-25 13:30:51 -04:00
|
|
|
|
|
|
|
|
@video_bios_version = get_regval_str('HKLM\\HARDWARE\\DESCRIPTION\\System', 'VideoBiosVersion')
|
2023-07-22 13:30:19 -04:00
|
|
|
|
2023-07-23 09:01:36 -04:00
|
|
|
if @system_bios_version =~ /parallels/i || @video_bios_version =~ /parallels/i
|
|
|
|
|
return true
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-07-23 09:10:51 -04:00
|
|
|
|
2023-07-22 13:14:17 -04:00
|
|
|
false
|
|
|
|
|
end
|
|
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
def hyperv?
|
2023-07-18 19:31:42 +02:00
|
|
|
physical_host = get_regval_str('HKLM\\SOFTWARE\\Microsoft\\Virtual Machine\\Guest\\Parameters', 'PhysicalHostNameFullyQualified')
|
2023-07-22 14:13:36 -04:00
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
if physical_host
|
2018-01-17 14:29:03 -06:00
|
|
|
report_note(
|
2020-06-13 22:47:22 +00:00
|
|
|
host: session,
|
|
|
|
|
type: 'host.physicalHost',
|
|
|
|
|
data: { physicalHost: physical_host },
|
|
|
|
|
update: :unique_data
|
|
|
|
|
)
|
2023-07-22 14:13:36 -04:00
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
print_good("This is a Hyper-V Virtual Machine running on physical host #{physical_host}")
|
|
|
|
|
return true
|
2011-01-12 02:16:06 +00:00
|
|
|
end
|
2018-01-17 14:29:03 -06:00
|
|
|
|
2023-07-11 21:10:56 +02:00
|
|
|
sfmsvals = registry_enumkeys('HKLM\\SOFTWARE\\Microsoft')
|
2020-06-13 22:47:22 +00:00
|
|
|
if sfmsvals
|
2023-07-25 13:30:51 -04:00
|
|
|
%w[Hyper-V VirtualMachine].each do |vm|
|
2023-07-22 10:23:09 -04:00
|
|
|
return true if sfmsvals.include?(vm)
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2012-12-21 22:11:57 -04:00
|
|
|
end
|
2018-01-17 14:29:03 -06:00
|
|
|
|
2023-07-23 09:01:36 -04:00
|
|
|
if @system_bios_version =~ /vrtual/i || @system_bios_version == 'Hyper-V'
|
|
|
|
|
return true
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2018-01-17 14:29:03 -06:00
|
|
|
|
2023-07-23 09:10:51 -04:00
|
|
|
keys = %w[HKLM\\HARDWARE\\ACPI\\FADT HKLM\\HARDWARE\\ACPI\\RSDT HKLM\\HARDWARE\\ACPI\\DSDT]
|
2018-01-17 14:29:03 -06:00
|
|
|
|
2023-07-23 09:10:51 -04:00
|
|
|
register_keys(keys)
|
2023-07-23 08:39:45 -04:00
|
|
|
|
2023-07-23 09:10:51 -04:00
|
|
|
return true if key_present?('VRTUAL')
|
2023-07-25 13:30:51 -04:00
|
|
|
|
2023-11-03 11:18:55 -04:00
|
|
|
hyperv_services = %w[vmicexchange]
|
2023-07-22 11:07:30 -04:00
|
|
|
|
2023-07-23 08:53:22 -04:00
|
|
|
return true if services_exist?(hyperv_services)
|
2020-06-13 22:47:22 +00:00
|
|
|
|
|
|
|
|
false
|
2011-01-12 02:16:06 +00:00
|
|
|
end
|
|
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
def vmware?
|
2023-07-25 13:30:51 -04:00
|
|
|
vmware_services = %w[
|
|
|
|
|
vmdebug vmmouse VMTools VMMEMCTL tpautoconnsvc
|
|
|
|
|
tpvcgateway vmware wmci vmx86
|
|
|
|
|
]
|
2020-06-13 22:47:22 +00:00
|
|
|
|
2023-07-23 08:53:22 -04:00
|
|
|
return true if services_exist?(vmware_services)
|
2023-07-22 12:55:03 -04:00
|
|
|
|
2023-07-25 13:30:51 -04:00
|
|
|
@system_manufacturer = get_regval_str('HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS',
|
|
|
|
|
'SystemManufacturer')
|
2023-07-22 13:22:52 -04:00
|
|
|
|
|
|
|
|
return true if @system_manufacturer =~ /vmware/i
|
|
|
|
|
|
2023-07-25 13:30:51 -04:00
|
|
|
@scsi_port_1 = get_regval_str('HKLM\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0',
|
|
|
|
|
'Identifier')
|
2023-07-22 14:13:36 -04:00
|
|
|
|
|
|
|
|
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
|
2023-07-25 13:30:51 -04:00
|
|
|
)
|
2020-06-13 22:47:22 +00:00
|
|
|
|
2023-07-22 10:48:40 -04:00
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
vmwareprocs = [
|
2023-07-11 21:02:36 +02:00
|
|
|
'vmtoolsd.exe',
|
|
|
|
|
'vmwareservice.exe',
|
|
|
|
|
'vmwaretray.exe',
|
|
|
|
|
'vmwareuser.exe'
|
2020-06-13 22:47:22 +00:00
|
|
|
]
|
2012-12-21 22:11:57 -04:00
|
|
|
|
2023-07-23 08:53:22 -04:00
|
|
|
return true if processes_exist?(vmwareprocs)
|
2023-07-25 13:30:51 -04:00
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
false
|
2011-01-12 02:16:06 +00:00
|
|
|
end
|
|
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
def virtualbox?
|
2011-01-12 02:16:06 +00:00
|
|
|
vboxprocs = [
|
2020-06-13 22:47:22 +00:00
|
|
|
'vboxservice.exe',
|
|
|
|
|
'vboxtray.exe'
|
2011-01-12 02:16:06 +00:00
|
|
|
]
|
2023-07-22 10:28:03 -04:00
|
|
|
|
2023-07-23 09:01:36 -04:00
|
|
|
vbox_srvcs = %w[VBoxMouse VBoxGuest VBoxService VBoxSF VBoxVideo]
|
|
|
|
|
|
|
|
|
|
if services_exist?(vbox_srvcs) || processes_exist?(vboxprocs)
|
|
|
|
|
return true
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2020-06-13 22:47:22 +00:00
|
|
|
|
2023-07-23 09:10:51 -04:00
|
|
|
return true if key_present?('VBOX__')
|
2020-06-13 22:47:22 +00:00
|
|
|
|
2023-07-11 21:06:14 +02:00
|
|
|
for i in 0..2 do
|
2023-07-22 12:57:54 -04:00
|
|
|
return true if regval_match?(
|
|
|
|
|
"HKLM\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port #{i}0\\Scsi Bus 0\\Target
|
|
|
|
|
Id 0\\Logical Unit Id 0",
|
2023-07-22 12:55:03 -04:00
|
|
|
'Identifier',
|
2023-07-25 13:30:51 -04:00
|
|
|
/vbox/i
|
|
|
|
|
)
|
2023-07-11 21:06:14 +02:00
|
|
|
end
|
2020-06-13 22:47:22 +00:00
|
|
|
|
2023-07-22 13:30:19 -04:00
|
|
|
return true if @system_bios_version =~ /vbox/i || @video_bios_version =~ /virtualbox/i
|
2023-07-25 13:30:51 -04:00
|
|
|
|
|
|
|
|
@system_product_name = get_regval_str('HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS', 'SystemProductName')
|
2023-07-22 13:19:37 -04:00
|
|
|
|
|
|
|
|
return true if @system_product_name =~ /virtualbox/i
|
2020-06-13 22:47:22 +00:00
|
|
|
|
|
|
|
|
false
|
2011-01-12 02:16:06 +00:00
|
|
|
end
|
|
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
def xen?
|
2011-01-12 02:16:06 +00:00
|
|
|
xenprocs = [
|
2020-06-13 22:47:22 +00:00
|
|
|
'xenservice.exe'
|
2011-01-12 02:16:06 +00:00
|
|
|
]
|
2023-07-22 10:28:03 -04:00
|
|
|
|
2023-07-23 09:01:36 -04:00
|
|
|
xen_srvcs = %w[xenevtchn xennet xennet6 xensvc xenvdb]
|
2020-06-13 22:47:22 +00:00
|
|
|
|
2023-07-23 09:01:36 -04:00
|
|
|
if processes_exist?(xenprocs) || services_exist?(xen_srvcs)
|
|
|
|
|
return true
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
2023-07-22 11:07:30 -04:00
|
|
|
|
2023-07-23 09:10:51 -04:00
|
|
|
return true if key_present?('Xen')
|
2020-06-13 22:47:22 +00:00
|
|
|
|
2023-07-22 13:19:37 -04:00
|
|
|
return true if @system_product_name =~ /xen/i
|
2023-07-11 21:07:03 +02:00
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
false
|
2011-01-12 02:16:06 +00:00
|
|
|
end
|
|
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
def qemu?
|
2023-07-23 09:01:36 -04:00
|
|
|
if @system_bios_version =~ /qemu/i || @video_bios_version =~ /qemu/i
|
2023-07-25 13:30:51 -04:00
|
|
|
return true
|
|
|
|
|
end
|
2023-07-22 14:13:36 -04:00
|
|
|
|
2023-07-23 09:01:36 -04:00
|
|
|
if @scsi_port_0 =~ /qemu|virtio/i || @system_manufacturer =~ /qemu/i
|
|
|
|
|
return true
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|
|
|
|
|
|
2023-07-22 14:13:36 -04:00
|
|
|
return true if regval_match?(
|
|
|
|
|
'HKLM\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0',
|
|
|
|
|
'ProcessorNameString',
|
2023-07-25 13:30:51 -04:00
|
|
|
/qemu/i
|
|
|
|
|
)
|
2023-07-11 21:08:19 +02:00
|
|
|
|
2023-07-23 09:10:51 -04:00
|
|
|
return true if key_present?('BOCHS_')
|
2023-07-11 20:58:22 +02:00
|
|
|
|
|
|
|
|
false
|
|
|
|
|
end
|
|
|
|
|
|
2020-06-13 22:47:22 +00:00
|
|
|
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)
|
2011-04-02 13:03:43 +00:00
|
|
|
end
|
|
|
|
|
|
2011-01-12 02:16:06 +00:00
|
|
|
def run
|
2021-04-24 18:06:37 +05:30
|
|
|
print_status('Checking if the target is a Virtual Machine ...')
|
2023-10-09 15:16:30 -04:00
|
|
|
@processes = get_processes
|
|
|
|
|
@processes = [] if @processes.nil?
|
|
|
|
|
|
|
|
|
|
@services = registry_enumkeys('HKLM\\SYSTEM\\ControlSet001\\Services')
|
|
|
|
|
@services = [] if @services.nil?
|
2020-06-13 22:47:22 +00:00
|
|
|
|
2023-07-18 19:29:02 +02:00
|
|
|
if parallels?
|
|
|
|
|
report_vm('Parallels')
|
|
|
|
|
elsif hyperv?
|
2020-06-13 22:47:22 +00:00
|
|
|
report_vm('Hyper-V')
|
|
|
|
|
elsif vmware?
|
|
|
|
|
report_vm('VMware')
|
|
|
|
|
elsif virtualbox?
|
|
|
|
|
report_vm('VirtualBox')
|
|
|
|
|
elsif xen?
|
|
|
|
|
report_vm('Xen')
|
|
|
|
|
elsif qemu?
|
2022-04-02 10:43:57 -04:00
|
|
|
report_vm('Qemu/KVM')
|
2012-01-26 13:02:39 -06:00
|
|
|
else
|
2021-04-24 18:06:37 +05:30
|
|
|
print_status('The target appears to be a Physical Machine')
|
2012-01-26 13:02:39 -06:00
|
|
|
end
|
2011-01-12 02:16:06 +00:00
|
|
|
end
|
2023-07-25 13:30:51 -04:00
|
|
|
end
|