Windows Manage VMDK Mount Drive - Metasploit
This page contains detailed information about how to use the post/windows/manage/vmdk_mount metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.
Module Overview
Name: Windows Manage VMDK Mount Drive
Module: post/windows/manage/vmdk_mount
Source code: modules/post/windows/manage/vmdk_mount.rb
Disclosure date: -
Last modification time: 2021-10-29 12:45:26 +0000
Supported architecture(s): -
Supported platform(s): Windows
Target service / protocol: -
Target network port(s): -
List of CVEs: -
This module mounts a vmdk file (Virtual Machine Disk) on a drive provided by the user by taking advantage of the vstor2 device driver (VMware). First, it executes the binary vixDiskMountServer.exe to access the device and then it sends certain control code via DeviceIoControl to mount it. Use the write mode with extreme care. You should only open a disk file in writable mode if you know for sure that no snapshots or clones are linked from the file.
Module Ranking and Traits
Module Ranking:
- normal: The exploit is otherwise reliable, but depends on a specific version and can't (or doesn't) reliably autodetect. More information about ranking can be found here.
Basic Usage
There are two ways to execute this post module.
From the Meterpreter prompt
The first is by using the "run" command at the Meterpreter prompt. It allows you to run the post module against that specific session:
meterpreter > run post/windows/manage/vmdk_mount
From the msf prompt
The second is by using the "use" command at the msf prompt. You will have to figure out which session ID to set manually. To list all session IDs, you can use the "sessions" command.
msf > use post/windows/manage/vmdk_mount
msf post(vmdk_mount) > show options
... show and set options ...
msf post(vmdk_mount) > set SESSION session-id
msf post(vmdk_mount) > exploit
If you wish to run the post against all sessions from framework, here is how:
1 - Create the following resource script:
framework.sessions.each_pair do |sid, session|
run_single("use post/windows/manage/vmdk_mount")
run_single("set SESSION #{sid}")
run_single("run")
end
2 - At the msf prompt, execute the above resource script:
msf > resource path-to-resource-script
Required Options
SESSION: The session to run this module on.
VMDK_PATH: Full path to the .vmdk file
Go back to menu.
Msfconsole Usage
Here is how the windows/manage/vmdk_mount post exploitation module looks in the msfconsole:
msf6 > use post/windows/manage/vmdk_mount
msf6 post(windows/manage/vmdk_mount) > show info
Name: Windows Manage VMDK Mount Drive
Module: post/windows/manage/vmdk_mount
Platform: Windows
Arch:
Rank: Normal
Provided by:
Borja Merino <[email protected]>
Compatible session types:
Meterpreter
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
DEL_LCK false yes Delete .vmdk lock file
DRIVE Z yes Mount point (drive letter)
READ_MODE true yes Open file in read-only mode
SESSION yes The session to run this module on.
VMDK_PATH yes Full path to the .vmdk file
Description:
This module mounts a vmdk file (Virtual Machine Disk) on a drive
provided by the user by taking advantage of the vstor2 device driver
(VMware). First, it executes the binary vixDiskMountServer.exe to
access the device and then it sends certain control code via
DeviceIoControl to mount it. Use the write mode with extreme care.
You should only open a disk file in writable mode if you know for
sure that no snapshots or clones are linked from the file.
References:
http://www.shelliscoming.com/2017/05/post-exploitation-mounting-vmdk-files.html
Module Options
This is a complete list of options available in the windows/manage/vmdk_mount post exploitation module:
msf6 post(windows/manage/vmdk_mount) > show options
Module options (post/windows/manage/vmdk_mount):
Name Current Setting Required Description
---- --------------- -------- -----------
DEL_LCK false yes Delete .vmdk lock file
DRIVE Z yes Mount point (drive letter)
READ_MODE true yes Open file in read-only mode
SESSION yes The session to run this module on.
VMDK_PATH yes Full path to the .vmdk file
Advanced Options
Here is a complete list of advanced options supported by the windows/manage/vmdk_mount post exploitation module:
msf6 post(windows/manage/vmdk_mount) > show advanced
Module advanced options (post/windows/manage/vmdk_mount):
Name Current Setting Required Description
---- --------------- -------- -----------
VERBOSE false no Enable detailed status messages
WORKSPACE no Specify the workspace for this module
Post Actions
This is a list of all post exploitation actions which the windows/manage/vmdk_mount module can do:
msf6 post(windows/manage/vmdk_mount) > show actions
Post actions:
Name Description
---- -----------
Evasion Options
Here is the full list of possible evasion options supported by the windows/manage/vmdk_mount post exploitation module in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):
msf6 post(windows/manage/vmdk_mount) > show evasion
Module evasion options:
Name Current Setting Required Description
---- --------------- -------- -----------
Go back to menu.
Error Messages
This module may fail with the following error messages:
- Wrong drive letter. Choose another one
- The following mount points already exists: <DRIVES>. Choose another one
- File <VMDK> not found
- VMware installation path not found.
- The drive couldn't be mounted. Check if a .lck file is blocking the access to the vmdk file
- It was not found a lck directory
- Unable to remove file: <E.MESSAGE>
- No vstor2 key found on <REG_SERVICES>
- No image path found for the vstor2 device
- GetLastError
- Unable to open a handle to the <VSTORE> device driver. GetLastError: <GETLASTERROR>
- GetLastError
- GetlastError DeviceIoControl = <ERROR_CODE>
- The vmdk file could't be mounted
- <MOUNT_BIN> not found in "<PATH>"
- An instance of <MOUNT_BIN> is already running by another process
- The <MOUNT_BIN> instance depending on Meterpreter could not be killed
- Binary <MOUNT_BIN> could could not be spawned : <ERROR.TO_S>
Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.
Wrong drive letter. Choose another one
Here is a relevant code snippet related to the "Wrong drive letter. Choose another one" error message:
41:
42: def run
43: vol = datastore['DRIVE'][0].upcase
44: vmdk = datastore['VMDK_PATH']
45: if vol.count("EFGHIJKLMNOPQRSTUVWXYZ") == 0
46: print_error("Wrong drive letter. Choose another one")
47: return
48: end
49:
50: drives = get_drives
51: if drives.include? vol
The following mount points already exists: <DRIVES>. Choose another one
Here is a relevant code snippet related to the "The following mount points already exists: <DRIVES>. Choose another one" error message:
47: return
48: end
49:
50: drives = get_drives
51: if drives.include? vol
52: print_error("The following mount points already exists: #{drives}. Choose another one")
53: return
54: end
55:
56: # Using stat instead of file? to check if the file exists due to this https://github.com/rapid7/metasploit-framework/issues/8202
57: begin
File <VMDK> not found
Here is a relevant code snippet related to the "File <VMDK> not found" error message:
55:
56: # Using stat instead of file? to check if the file exists due to this https://github.com/rapid7/metasploit-framework/issues/8202
57: begin
58: client.fs.file.stat(vmdk)
59: rescue
60: print_error("File #{vmdk} not found")
61: return
62: end
63:
64: vmware_path = registry_getvaldata("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\vmplayer.exe", "path")
65:
VMware installation path not found.
Here is a relevant code snippet related to the "VMware installation path not found." error message:
62: end
63:
64: vmware_path = registry_getvaldata("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\vmplayer.exe", "path")
65:
66: if vmware_path.nil?
67: print_error("VMware installation path not found.")
68: return
69: end
70:
71: print_status("VMware path: \"#{vmware_path}\"")
72:
The drive couldn't be mounted. Check if a .lck file is blocking the access to the vmdk file
Here is a relevant code snippet related to the "The drive couldn't be mounted. Check if a .lck file is blocking the access to the vmdk file" error message:
86: print_good("The drive #{vol}: seems to be ready")
87: if datastore['DEL_LCK']
88: delete_lck(vmdk)
89: end
90: else
91: print_error("The drive couldn't be mounted. Check if a .lck file is blocking the access to the vmdk file")
92: # Some snapshots could give some problems when are mount in write mode
93: if !datastore['READ_MODE']
94: print_status("Try to mount the drive in read only mode")
95: end
96: end
It was not found a lck directory
Here is a relevant code snippet related to the "It was not found a lck directory" error message:
101: lck_dir = vmdk << ".lck"
102: begin
103: files = client.fs.dir.entries(lck_dir)
104: vprint_status("Directory lock: #{lck_dir}")
105: rescue Rex::Post::Meterpreter::RequestError
106: print_status("It was not found a lck directory")
107: return
108: end
109:
110: files.shift(2)
111: files.each do |f|
Unable to remove file: <E.MESSAGE>
Here is a relevant code snippet related to the "Unable to remove file: <E.MESSAGE>" error message:
118: if content.include? "vixDiskMountServer"
119: begin
120: client.fs.file.rm(f_path)
121: print_status("Lock file #{f} deleted")
122: rescue ::Exception => e
123: print_error("Unable to remove file: #{e.message}")
124: end
125: end
126: end
127: end
128:
No vstor2 key found on <REG_SERVICES>
Here is a relevant code snippet related to the "No vstor2 key found on <REG_SERVICES>" error message:
130: def find_vstor2_device
131: reg_services = "HKLM\\SYSTEM\\ControlSet001\\Services\\"
132: devices = registry_enumkeys(reg_services)
133: vstor2_key = devices.grep(/^vstor2/)
134: if !vstor2_key.any?
135: print_error("No vstor2 key found on #{reg_services}")
136: return
137: end
138:
139: device_path = registry_getvaldata(reg_services << vstor2_key[0], "ImagePath")
140:
No image path found for the vstor2 device
Here is a relevant code snippet related to the "No image path found for the vstor2 device" error message:
137: end
138:
139: device_path = registry_getvaldata(reg_services << vstor2_key[0], "ImagePath")
140:
141: if device_path.nil?
142: print_error("No image path found for the vstor2 device")
143: return
144: end
145:
146: device_name = device_path.split('\\')[-1].split('.')[0]
147: print_status("Device driver name found: \\\\.\\#{device_name}")
GetLastError
Here is a relevant code snippet related to the "GetLastError" error message:
154: i = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".index(vol)
155: drive_dword = [(0x00000001 << i)].pack('V')
156: vprint_status("DWORD value for drive #{vol}: = #{drive_dword.inspect}")
157:
158: ret = session.railgun.kernel32.CreateFileW(vstore, "GENERIC_WRITE|GENERIC_READ", "FILE_SHARE_READ|FILE_SHARE_WRITE", nil, "OPEN_EXISTING", 0, nil)
159: if ret['GetLastError'] != 0
160: print_error("Unable to open a handle to the #{vstore} device driver. GetLastError: #{ret['GetLastError']} ")
161: return false
162: end
163: # fd1, fd3 and fd5 are static values used from vixDiskMountApi.dll to build the input buffer
164: fd1 = "\x24\x01\x00\x00"
Unable to open a handle to the <VSTORE> device driver. GetLastError: <GETLASTERROR>
Here is a relevant code snippet related to the "Unable to open a handle to the <VSTORE> device driver. GetLastError: <GETLASTERROR>" error message:
155: drive_dword = [(0x00000001 << i)].pack('V')
156: vprint_status("DWORD value for drive #{vol}: = #{drive_dword.inspect}")
157:
158: ret = session.railgun.kernel32.CreateFileW(vstore, "GENERIC_WRITE|GENERIC_READ", "FILE_SHARE_READ|FILE_SHARE_WRITE", nil, "OPEN_EXISTING", 0, nil)
159: if ret['GetLastError'] != 0
160: print_error("Unable to open a handle to the #{vstore} device driver. GetLastError: #{ret['GetLastError']} ")
161: return false
162: end
163: # fd1, fd3 and fd5 are static values used from vixDiskMountApi.dll to build the input buffer
164: fd1 = "\x24\x01\x00\x00"
165: fd2 = "\x00\x00\x00\x00"
GetLastError
Here is a relevant code snippet related to the "GetLastError" error message:
179:
180: error_code = ""
181: tries = 0
182: loop do
183: ioctl = client.railgun.kernel32.DeviceIoControl(ret['return'], 0x2A002C, buffer, 292, 16348, 16348, 4, nil)
184: error_code = ioctl['GetLastError']
185: vprint_status("GetlastError DeviceIoControl = #{error_code}")
186: tries += 1
187: break if tries == 3 || (error_code != 31 && error_code != 6)
188: end
189:
GetlastError DeviceIoControl = <ERROR_CODE>
Here is a relevant code snippet related to the "GetlastError DeviceIoControl = <ERROR_CODE>" error message:
180: error_code = ""
181: tries = 0
182: loop do
183: ioctl = client.railgun.kernel32.DeviceIoControl(ret['return'], 0x2A002C, buffer, 292, 16348, 16348, 4, nil)
184: error_code = ioctl['GetLastError']
185: vprint_status("GetlastError DeviceIoControl = #{error_code}")
186: tries += 1
187: break if tries == 3 || (error_code != 31 && error_code != 6)
188: end
189:
190: if error_code == 997 || error_code == 0
The vmdk file could't be mounted
Here is a relevant code snippet related to the "The vmdk file could't be mounted" error message:
189:
190: if error_code == 997 || error_code == 0
191: client.railgun.kernel32.CloseHandle(ret['return'])
192: return true
193: else
194: print_error("The vmdk file could't be mounted")
195: return false
196: end
197: end
198:
199: # Run the hidden vixDiskMountServer process needed to interact with the driver
<MOUNT_BIN> not found in "<PATH>"
Here is a relevant code snippet related to the "<MOUNT_BIN> not found in "<PATH>"" error message:
198:
199: # Run the hidden vixDiskMountServer process needed to interact with the driver
200: def open_mountserver(path)
201: mount_bin = "vixDiskMountServer.exe"
202: if !file?(path << mount_bin)
203: print_error("#{mount_bin} not found in \"#{path}\"")
204: return false
205: end
206:
207: # If the vixDiskMountServer process is created by VMware (i.e. when the mapping utility is used) it will not be
208: # possible to mount the file. In this case killing vixDiskMountServer manually from Meterpreter and re-running
An instance of <MOUNT_BIN> is already running by another process
Here is a relevant code snippet related to the "An instance of <MOUNT_BIN> is already running by another process" error message:
213: # For this reason, to avoid this case, the process is relaunched automatically.
214: p = session.sys.process.each_process.find { |i| i["name"] == mount_bin }
215:
216: if p
217: if p["ppid"] != session.sys.process.getpid
218: print_error("An instance of #{mount_bin} is already running by another process")
219: return false
220: else
221: begin
222: print_status("Killing the #{mount_bin} instance")
223: session.sys.process.kill(p["pid"])
The <MOUNT_BIN> instance depending on Meterpreter could not be killed
Here is a relevant code snippet related to the "The <MOUNT_BIN> instance depending on Meterpreter could not be killed" error message:
221: begin
222: print_status("Killing the #{mount_bin} instance")
223: session.sys.process.kill(p["pid"])
224: sleep(1)
225: rescue ::Rex::Post::Meterpreter::RequestError => error
226: print_error("The #{mount_bin} instance depending on Meterpreter could not be killed")
227: return false
228: end
229: end
230: end
231:
Binary <MOUNT_BIN> could could not be spawned : <ERROR.TO_S>
Here is a relevant code snippet related to the "Binary <MOUNT_BIN> could could not be spawned : <ERROR.TO_S>" error message:
232: begin
233: proc = session.sys.process.execute(path, nil, { 'Hidden' => true })
234: sleep(1)
235: print_good("Process #{mount_bin} successfully spawned (Pid: #{proc.pid})")
236: rescue ::Rex::Post::Meterpreter::RequestError => error
237: print_error("Binary #{mount_bin} could could not be spawned : #{error.to_s}")
238: return false
239: end
240:
241: true
242: end
Go back to menu.
Related Pull Requests
- #8716 Merged Pull Request: Print_Status -> Print_Good (And OCD bits 'n bobs)
- #8455 Merged Pull Request: Meterpreter Post-exploitation module to mount vmdk files
References
See Also
Check also the following modules related to this module:
- post/windows/manage/add_user
- post/windows/manage/archmigrate
- post/windows/manage/change_password
- post/windows/manage/clone_proxy_settings
- post/windows/manage/delete_user
- post/windows/manage/dell_memory_protect
- post/windows/manage/download_exec
- post/windows/manage/driver_loader
- post/windows/manage/enable_rdp
- post/windows/manage/enable_support_account
- post/windows/manage/exec_powershell
- post/windows/manage/execute_dotnet_assembly
- post/windows/manage/forward_pageant
- post/windows/manage/hashcarve
- post/windows/manage/ie_proxypac
- post/windows/manage/inject_ca
- post/windows/manage/inject_host
- post/windows/manage/install_python
- post/windows/manage/install_ssh
- post/windows/manage/killav
- post/windows/manage/migrate
- post/windows/manage/mssql_local_auth_bypass
- post/windows/manage/multi_meterpreter_inject
- post/windows/manage/nbd_server
- post/windows/manage/peinjector
- post/windows/manage/persistence_exe
- post/windows/manage/portproxy
- post/windows/manage/pptp_tunnel
- post/windows/manage/priv_migrate
- post/windows/manage/pxeexploit
- post/windows/manage/reflective_dll_inject
- post/windows/manage/remove_ca
- post/windows/manage/remove_host
- post/windows/manage/rid_hijack
- post/windows/manage/rollback_defender_signatures
- post/windows/manage/rpcapd_start
- post/windows/manage/run_as
- post/windows/manage/run_as_psh
- post/windows/manage/sdel
- post/windows/manage/shellcode_inject
- post/windows/manage/sshkey_persistence
- post/windows/manage/sticky_keys
- post/windows/manage/vss
- post/windows/manage/vss_create
- post/windows/manage/vss_list
- post/windows/manage/vss_mount
- post/windows/manage/vss_set_storage
- post/windows/manage/vss_storage
- post/windows/manage/wdigest_caching
- post/windows/manage/webcam
Authors
Borja Merino <bmerinofe[at]gmail.com>
Version
This page has been produced using Metasploit Framework version 6.1.24-dev. For more modules, visit the Metasploit Module Library.
Go back to menu.