Skip to content
Branch: master
Clone or download

README.md

Paragon APFS SDK Community Edition

Paragon APFS SDK allows developers to access APFS volumes from their forensic software, applications, devices, and appliances on non-Apple platforms

Changelog

Date Event
2017 Create
June, 2019 Publication

Sources

Folder Content
linutil sources of apfsutil and UFSD interfaces implementation
ufs UFSD SDK: interfaces, headers, Paragon APFS sources, common and 3rd-party components

Key Features

  • Cross-platform implementation for Windows, Linux, macOS, RTOSes, and UEFI environments
  • Regularly updated libraries. Every build is tested for reliability, functionality, and performance before leaving the lab
  • Full read-only access on any APFS volumes:
    • Folder enumeration (both case-sensitive and case-insensitive)
    • Files reading (including cloned and compressed)
    • Get a list of file extended attributes (xattr)
    • Accessing all APFS sub-volumes
    • Reading encrypted volumes (if OpenSSL is present and detected by CMake)

Limitations

  • Read-only access to APFS volumes. A read-write version of Paragon APFS SDK will be available soon on site: https://www.paragon-software.com/
  • Only first sub-volume can be accessed on 32-bit platforms
  • Stable work with 16TB+ volumes is not guaranteed
  • No support for hardware-encrypted APFS volumes
  • No support for Big Endian platforms (MIPS, PowerPC)

apfsutil

The utility to test and show the UFSD SDK capabilities. Usage:

$ apfsutil <test_name> [options] /dev/xxx/path/to/file/or/folder

where:
    test_name      name of the test to run (see 'User scenarios' section)

options:
   --passN=password  use password for the volume N (for encrypted volumes). APFS volumes are listed from N=1 to 100
   --trace           turn on UFSD trace
   --subvolumes      mount all sub-volumes (All sub-volumes from the container will be "mounted" in the 'Ufsd_Volumes' folder in the root)

For example:

$ sudo apfsutil readfile /dev/sdb1/test_folder/newfile.txt
$ sudo apfsutil enumfolder --subvolumes --pass1=qwerty --pass2=qwerty2 /dev/sdb1/Ufsd_Volumes/Untitled/test_folder

or Windows

$ apfsutil enumfolder f:\test_folder

Build prerequisites

  • C++ compiler
  • CMake
  • (Optional) OpenSSL library

How to build

Linux/Mac OS

$ mkdir .build
$ cd .build
$ cmake ..
$ cmake --build .

Windows

There are two ways for building apfsutil under Windows:

  1. Compile with MSVC from VS2015 or later.
  2. Download and install MinGW, add MinGW "bin" directory to the PATH system environment variable and run cmake with "MinGW Makefiles" generator.
$ mkdir .build
$ cd .build
$ cmake -G "MinGW Makefiles" ..
$ cmake --build .

If you have both MinGW "bin" and MSYS "bin" directories in PATH, use "MSYS Makefiles" generator instead.

Warning: option --trace is available only in the debug mode. To build:

$ cmake -DCMAKE_BUILD_TYPE=Debug ..

User scenarios

apfsutil already contains some simple user scenarios, such as

test name test description
enumroot root folder enumeration
enumfolder sub-directory enumeration
readfile file reading
listea list and show all file extended attributes
listsubvolumes show all sub-volumes from the container

Sub-volumes

apfsutil can work with all sub-volumes in an APFS container. To mount all ones, add option --subvolumes to the apfsutil arguments. Without this option, only the main (1st) volume will be mounted. Paragon APFS SDK puts sub-volumes in the "/Ufsd_Volumes" folder. To read or enumerate files and folders on a sub-volume, its full path should be specified. For example, first of all, get a list of sub-volumes. Note, for this user scenario the --subvolume is optional. If a required sub-volume name is known, this step can be skipped.

$ apfsutil listsubvolumes /dev/xxx
Volumes:
Untitled Volume2 MyEncryptedVolume
APFS: listsubvolumes returns 0. finished in 4 ms

Important: this operation is only available on the unlocked (unmounted) APFS Container!

Then enumerate the root sub-volume folder, or read any file

$ apfsutil enumfolder /dev/xxx/Ufsd_Volumes/Untitled
$ apfsutil readfile /dev/xxx/Ufsd_Volumes/Untitled/testfile.txt

How to add your case

To create your own custom case, put its name (any, but not previously defined) in the list named s_Cmd (in the linutil/apfsutil.cpp) and create a command handler (function) there.

static const t_CmdHandler s_Cmd[] = {
  { "enumroot"        , OnEnumRoot         },   // readdir example
  { "enumfolder"      , OnEnumFolder       },   // enumerate folder
  { "readfile"        , OnReadFile         },   // file reading
  { "listea"          , OnListEa           },   // list all extended attributes
  { "listsubvolumes"  , OnEnumSubvolumes   },   // sub-volumes enumeration
  // handlers for RW version
  { "createfile"      , OnCreateFile       },   // create file
  { "createfolder"    , OnCreateFolder     },   // create folder
  { "queryalloc"      , OnQueryAlloc       },   // list file extents (allocations)
  { "fsinfo"          , OnFsInfo           },   // get file system information
  //
  // TODO: add your handlers here
  // ...
  { NULL      , NULL },
};

Test handler should be of type

typedef int (*HandlerFunc)(CFileSystem*, const char*);

Inside your specified handler all public functions from base UFSD classes CFileSystem, CFile, CDir are available (for more details see ufs\ufsd\include\ufsd\u_fsbase.h).

After rebuilding the utility selected test case will be available to start

$ sudo apfsutil my_new_case /dev/xxx/path/to/file/or/folder

Read-Write access

Some operations require the full Read-Write sources (The version will be available soon on site: https://www.paragon-software.com/). In the Community Edition these cases will return a "not implemented" error.

test name test description
createfile file creation
createfolder folder creation
queryalloc list file extents
fsinfo information about the file system (all sub-volumes, even encrypted)

fsinfo example

$ sudo apfsutil fsinfo /dev/sdb1
APFS Volume [0] 0F7AFC7E-BDF6-4546-8494-2A0C449E8D1F
  Name               : volume1 (Case-insensitive)
  Creator            : newfs_apfs (945.200.129)
  Used Clusters      : 1187894
  Reserved Clusters  : 0
  Files              : 63478
  Directories        : 1630
  Symlinks           : 5
  Special files      : 0
  Snapshots          : 0
  Encrypted          : Yes

APFS Volume [1] D45089E3-D391-4246-9490-B4EAC8D4E395
  Name               : volume2 (Case-insensitive)
  Creator            : diskmanagementd (945.200.129)
  Used Clusters      : 270
  Reserved Clusters  : 0
  Files              : 71
  Directories        : 19
  Symlinks           : 1
  Special files      : 0
  Snapshots          : 0
  Encrypted          : No

APFS Volume [2] 9D8EBA18-B110-4FCB-86FC-3E18B304628E
  Name               : volume3 (Case-insensitive)
  Creator            : diskmanagementd (945.200.129)
  Used Clusters      : 265
  Reserved Clusters  : 0
  Files              : 64
  Directories        : 18
  Symlinks           : 0
  Special files      : 0
  Snapshots          : 0
  Encrypted          : No

apfsutil error codes

The utility can return following exit codes:

code description
0 all is OK, no error
-1 invalid command line parameters
-2 invalid or empty device name
-3 the device is mounted (linux only)
-4 no handler specified for the selected test_name
-5 misuse of the --pass option
0xA0001001 Errors from the Paragon APFS SDK
...
0xA0001026 (console output will contain an error message)

Licensing

The license for this project is defined in a separate document "LICENSE.txt" Paragon APFS SDK also contains the following code:

You can’t perform that action at this time.