Skip to main content

TFFS Filesystem Mounter

Project Description

This project contains code to parse and mount (read only) the TFFS filesystem found in certain Automotive systems. Earlier we created a similar tool: qnxmount for other filesystems found in Automotive applications running the QNX OS.

Most of the initial research and reverse engineering of TFFS was done by the Digital Analysis Division of the National Forensic Service (NFS) of the Republic of Korea. This research is documented in their paper published at DFRWS 2023 and their code can be found here.

The information in the paper was augmented with some additional reverse engineering efforts of our own based on executable files found in Automotive systems. All of this filesystem structure information combined was put in the parser.ksy file, which is written in the declarative binary structure language: kaitai, enabling the automatic generation of parser code. The filesystem can then be mounted using FUSE with some python glue code between the FUSE python bindings and the generated parser.

This project is only tested on Linux machines.

Getting started

tffsmount needs Python 3.9.2 or later and FUSE. The fusepy bindings load libfuse 2; libfuse 3 alone is not enough:

sudo apt install libfuse2t64   # libfuse2 on releases before Ubuntu 24.04

libfuse 2 also needs a fusermount on your PATH. The fuse3 package provides one; older releases ship it in the fuse package.

Install tffsmount from PyPI in a virtual environment:

python3 -m venv venv
source ./venv/bin/activate
pip install tffsmount

To install from source instead, run pip install . in a clone of this repository.

Usage

~ tffsmount -h
usage: tffsmount [-h] [-o OFFSET] [-k KEYS] image mount_point

positional arguments:
  image                Path to image containing tffs file system
  mount_point          Path to mount point

options:
  -h, --help           show this help message and exit
  -o, --offset OFFSET  Offset of tffs partition in image
  -k, --keys KEYS      Path to a JSON file holding one object that maps each
                       fscrypt key descriptor (8 bytes) to its master key (up
                       to 64 bytes), both as hex strings, e.g.
                       {"a1b2c3d4e5f60708": "00112233..."}.

The offset can be given in decimal, octal, binary or hexadecimal and does not need to be page-aligned. For example, to mount a tffs filesystem at offset 0x1000 in an image:

tffsmount -o 0x1000 /image /mountpoint

-o 4096 gives the same result.

tffsmount logs Mounting image /image on mount point /mountpoint and then stays in the foreground while the filesystem is mounted. Browse the mount point from another terminal or a file browser, and unmount it with:

fusermount -u /mountpoint

tffsmount then logs that the image was unmounted and exits.

Contributing and Testing

If you want to develop the tool and run tests, first fork the repository. Contributions can be submitted as a merge request.

To get started clone the forked repository and install it with the test dependencies. The project is managed with pdm, which creates the virtual environment and installs the versions pinned in pdm.lock:

pdm install -G test

Without pdm, pip install .[test] in a virtual environment of your own works as well.

The folder tests contains functional tests to test the parser against known input data. To run these tests you need a file system image and an accompanying tar archive. The tests run are functional tests that check whether the parsed data from the test image is equal to the data stored in the archive. Default test_images are located in the folders test_data. If you want to test your own image replace the files test_image.bin and test_image.tar.gz with your own.

A test image can be created by running the script make_test_fs.sh inside an environment where you have access to mktffs and the Tuxera kernel module (tffs.ko) loaded. The script will create the desired files and directories which you will then need to tar as well as use dd to create a physical image.

To run the tests in this repo navigate to the main directory of the repo and run:

pdm run pytest

or plain pytest inside the virtual environment.

Regenerating the parser

tffsmount/parser.py is generated from tffsmount/parser.ksy and must not be edited by hand. After changing the .ksy, rebuild it with kaitai-struct-compiler 0.11, the version matching the kaitaistruct runtime:

cd tffsmount && ksc --target python --outdir . parser.ksy

Metadata

Release files for tffsmount 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tffsmount 0.1.0
File Size Uploaded Provenance Actions
tffsmount-0.1.0.tar.gz 206.6 kB Without provenance Details for tffsmount-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for tffsmount 0.1.0
File Interpreter ABI Platform Actions
tffsmount-0.1.0-py3-none-any.whl Python 3 none any Details for tffsmount-0.1.0-py3-none-any.whl

Total release size: 248.6 kB

Release files / tffsmount-0.1.0.tar.gz

Download URL tffsmount-0.1.0.tar.gz
Size 206.6 kB
Tags Source
SHA-256 checksum
How to use checksums
6c18fb3fa1049267c0e624a3c702cb231661d755ffd8473bdc4506401affa72f
BLAKE2b-256 checksum
How to use checksums
c791cb3fdf742f0104b3c6b2bee9441be931330ad29e3f2b89d5f6cfe247c349
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.29.0 CPython/3.13.7 Linux/6.17.0-41-generic

Release files / tffsmount-0.1.0-py3-none-any.whl

Download URL tffsmount-0.1.0-py3-none-any.whl
Size 42.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2c7524d2055c956410f925ceed379988c419bef97174083a4cbe61a31eb5f382
BLAKE2b-256 checksum
How to use checksums
ee645f8cd4ce8410b17f3301368b653e9aedfb460a183f787bf93c6498dd4534
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.29.0 CPython/3.13.7 Linux/6.17.0-41-generic

Security for tffsmount 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page