imagemounter
imagemounter copied to clipboard
Add APFS support using apfs-fuse
This adds support for APFS using a trivial wrapper around apfs-fuse, in line with vmfs-fuse usage.
Closes #30
Looks great! Do you have any test cases you may be able to add?
Hmm, I tested this on an image obtained from a live system, but am not immediately able to get it to work on a test image created using mkapfs. To be continued!
EDIT: The manual approach seems to work:
# truncate -s 200MiB test.apfs
# losetup -f
/dev/loop27
# losetup /dev/loop27 test.apfs
# mkdir /tmp/mac
# apfs-fuse /dev/loop27 /tmp/mac
# tree /tmp/mac
/tmp/mac
├── private-dir
└── root
However, following the commands that imount produces, apfs-fuse runs into an error..
imagemounter version 3.1.0
[+] Mounting image test.apfs using auto...
$ affuse -o allow_other test.apfs /tmp/image_mounter_yamjqa8u
Can't open image file: Invalid argument
[-] Could not mount test.apfs, trying other method
Traceback (most recent call last):
File "/home/user/repos/imagemounter/imagemounter/disk.py", line 209, in mount
_util.check_call_(cmd, stdout=subprocess.PIPE)
File "/home/user/repos/imagemounter/imagemounter/_util.py", line 122, in check_call_
return subprocess.check_call(cmd, *args, **kwargs)
File "/usr/lib/python3.10/subprocess.py", line 369, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['affuse', '-o', 'allow_other', 'test.apfs', '/tmp/image_mounter_yamjqa8u']' returned non-zero exit status 1.
$ affuse test.apfs /tmp/image_mounter_yamjqa8u
Can't open image file: Invalid argument
[-] Could not mount test.apfs, trying other method
Traceback (most recent call last):
File "/home/user/repos/imagemounter/imagemounter/disk.py", line 209, in mount
_util.check_call_(cmd, stdout=subprocess.PIPE)
File "/home/user/repos/imagemounter/imagemounter/_util.py", line 122, in check_call_
return subprocess.check_call(cmd, *args, **kwargs)
File "/usr/lib/python3.10/subprocess.py", line 369, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['affuse', 'test.apfs', '/tmp/image_mounter_yamjqa8u']' returned non-zero exit status 1.
$ xmount --in dd test.apfs /tmp/image_mounter_yamjqa8u
Raw path to disk is /tmp/image_mounter_yamjqa8u/test.dd
$ disktype /tmp/image_mounter_yamjqa8u/test.dd
<
< --- /tmp/image_mounter_yamjqa8u/test.dd
< Regular file, size 200 MiB (209715200 bytes)
<
[+] Mounted raw image [1/1]
[+] Mounting volumes in test.apfs
$ mmls /tmp/image_mounter_yamjqa8u/test.dd
< return code 1
[-] Failed executing mmls command
Traceback (most recent call last):
File "/home/user/repos/imagemounter/imagemounter/volume_system.py", line 413, in detect
output = _util.check_output_(cmd, stderr=subprocess.STDOUT)
File "/home/user/repos/imagemounter/imagemounter/_util.py", line 133, in check_output_
result = subprocess.check_output(cmd, *args, **kwargs)
File "/usr/lib/python3.10/subprocess.py", line 420, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "/usr/lib/python3.10/subprocess.py", line 524, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['mmls', '/tmp/image_mounter_yamjqa8u/test.dd']' returned non-zero exit status 1.
[+] Detecting as single volume instead
$ file -sL /tmp/image_mounter_yamjqa8u/test.dd
< /tmp/image_mounter_yamjqa8u/test.dd: Apple File System (APFS), blocksize 4096
Initializing volume 0:Apple File System (APFS)
[+] Mounting volume 0:Apple File System (APFS)
Trying to determine fs type from fsdescription 'Apple File System (APFS)'
Current certainty levels: Counter({<class 'imagemounter.filesystems.ApfsFileSystem'>: 80})
$ fsstat /tmp/image_mounter_yamjqa8u/test.dd -o 0
$ losetup -f
< /dev/loop29
$ losetup -r -o 0 --sizelimit 4096 /dev/loop29 /tmp/image_mounter_yamjqa8u/test.dd
$ apfs-fuse /dev/loop29 /tmp/im_0_v4f42_6u_
Unable to load container.
$ losetup -d /dev/loop29
[-] Execution failed due to <class 'subprocess.CalledProcessError'> Command '['apfs-fuse', '/dev/loop29', '/tmp/im_0_v4f42_6u_']' returned non-zero exit status 22.