ArsenalRecon / Arsenal-Image-Mounter

Arsenal Image Mounter mounts the contents of disk images as complete disks in Microsoft Windows.
https://ArsenalRecon.com/weapons/image-mounter
Other
531 stars 89 forks source link

aim_ll support for volume mount points seems broken #20

Closed benrg closed 10 months ago

benrg commented 3 years ago

To reproduce: aim_ll -a -f diskimage -m d:\mountpoint

Expected result: the volume (sole partition in the image) is mounted at the mountpoint.

Actual result:

Creating device...
Created device ###### -> diskimage
Attached disk volume \\?\Volume{...}
  Mounted at F:\
Created new volume mount point at d:\mountpoint\

Disk Manager then shows the volume as mounted at both the mount point and the drive letter (which seems to be the alphabetically first available letter excluding A: and B:).

Also, aim_ll -d -m d:\mountpoint, while it does remove the disk, doesn't delete the reparse point at d:\mountpoint. This problem persists even if I delete the spurious drive letter in Disk Manager so that the volume is mounted only at d:\mountpoint when I try to remove it.

LTRData commented 3 years ago

Windows automatically assigns drive letters to drives as they appear in the system so if you specify a directory mount point with AIM you will get both that mount point and the drive letter that Windows assigned automatically. If you do not want that to happen and instead only use the mount points that AIM assigns and that you could control through aim_ll command line, you can turn automatic drive letter assignment off in Windows: mountvol /n

This has other side effects though, it means that you will not automatically get a drive letter assigned for a new hard drive that you attach in the system but you can assign one manually using mountvol at command line, or the assign command in diskpart tool, or using Disk Management GUI.

benrg commented 3 years ago

The reason I reported this as a bug is that -m with a drive letter behaves as I expect: -m q: mounts the volume only on q:, not both q: and d:, even if automounting is enabled and d: is available, and -m r: mounts it only on r:, not both r: and q:, even if the volume manager remembers that it was previously mounted on q:.

mountvol /n doesn't really address this problem, both because it has global effect as you said, and because it doesn't change the behavior when the volume was attached previously at a different location, and the cache hasn't been cleared with mountvol /r.

This is an issue for me because if the volume is mounted on any drive letter, even if I never refer to it, Windows seems to view it as the canonical mount point for the purpose of GetFinalPathNameByHandle. I'm trying to mount a volume at a certain location (drive letter or NTFS folder) and have the canonical path of the files on the volume reliably be that location. It's not clear how to accomplish that with aim_ll as it stands, when the location is an NTFS folder. I could parse the textual output of aim_ll to find the volume GUID and call the volume management functions myself, but that's fairly painful, and feels unreliable, since I don't know how the output might change in future versions.

LTRData commented 3 years ago

The difference when using for example -m q: is that mount manager in Windows only allows one drive letter per volume but many directory mount points, which implies that setting a new drive letter removes the existing drive letter, while setting a new directory mount point does not remove any other existing mount points. (There is a brief time between when Windows assigns a drive letter and aim_ll changes it, so there could sometimes be format request dialogs showing up with the auto-assigned drive letter instead which is bad, but at least it does not happen very often.)

In your particular case I would recommend a more programmatic solution where you have more control over what happens. PowerShell script to the API would be one way for example:

Add-Type -Path .\Arsenal.ImageMounter.dll

$aim = [Arsenal.ImageMounter.ScsiAdapter]::new()

$devnr = [Arsenal.ImageMounter.ScsiAdapter]::AutoDeviceNumber
$aim.CreateDevice(0, 0, 0, [System.IO.FileAccess]::ReadWrite, 'C:\testimage.dd', $false, [ref] $devnr)

$disk = $aim.OpenDevice($devnr)

$volname = $disk.EnumerateDiskVolumes()[0]
'Volume: ' + $volname

$mountpoint = [Arsenal.ImageMounter.IO.NativeFileIO]::EnumerateVolumeMountPoints($volname)[0]
'Mount point: ' + $mountpoint

[Arsenal.ImageMounter.IO.NativeFileIO]::DeleteVolumeMountPoint($mountpoint)

[Arsenal.ImageMounter.IO.NativeFileIO]::SetVolumeMountPoint('C:\your_preferred_mount_dir', $volname)

$disk.Dispose()

$aim.Dispose()

This mounts an image file, finds the drive letter that Windows has automatically assigned and removes it and then sets another mount point.

LTRData commented 3 years ago

You will need Arsenal.ImageMounter.dll for this, it is available in this repository in the Arsenal.ImageMounter.7z archive file in the API directory.