diff --git a/README.md b/README.md index a9a90af..9dae751 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,10 @@ # fsdecrypt -Decryptor and extractor for SEGA arcade filesystem containers (fscrypt format). - -Handles AES-128-CBC encrypted container images used on SEGA Nu/ALLS arcade hardware, automatically parsing the embedded BootID header to identify the game and container type, then decrypting and extracting the contents. - -## Features - -- Decrypts OS, APP, and OPTION (DLC) containers -- Extracts NTFS-based containers (OS/APP) including internal VHD images -- Extracts ExFAT-based containers (OPTION/DLC packs) -- **Auto-merges delta update VHDs** with their base on Windows (Hyper-V) -- Preserves file timestamps during extraction -- Built-in key database for 70+ game titles -- Supports external key files for unlisted games -- Progress bars with transfer speed and ETA +Decryptor and extractor for SEGA arcade filesystem containers (fscrypt format). Works on Windows and Linux, no admin privileges required. ## Installation -Requires [Rust](https://www.rust-lang.org/tools/install) 1.56+ (edition 2021). +Requires [Rust](https://www.rust-lang.org/tools/install). ```bash cargo build --release @@ -27,94 +14,48 @@ The binary will be at `target/release/fsdecrypt` (or `fsdecrypt.exe` on Windows) ## Usage +```bash +fsdecrypt ... ``` -fsdecrypt [OPTIONS] ... -``` - -### Arguments - -- `...` - One or more encrypted container files (`.app`, `.opt`, etc.) - -### Options - -- `--no-extract` - Decrypt the container to a raw image file without extracting its contents -- `-h, --help` - Print help -- `-V, --version` - Print version ### Examples ```bash -# Decrypt and extract an APP container +# Extract a game APP container fsdecrypt ABCD_1.00.00_20240101120000_0.app -# Decrypt and extract an OPTION container +# Extract an OPTION/DLC container fsdecrypt ABCD_A001_20240101120000_0.opt -# Process multiple containers at once +# Extract multiple files at once fsdecrypt game_v1.app game_v2.app extras.opt -# Decrypt only, skip extraction +# Decrypt only (outputs raw .ntfs/.exfat image, no extraction) fsdecrypt --no-extract ABCD_1.00.00_20240101120000_0.app ``` ### Delta Updates -When a game ships incremental updates, you get a base `.app` (seq=0) and one or more delta `.app` files (seq>0). Pass them all together and fsdecrypt handles the rest: +Games often ship incremental updates as a separate `.app` file. Just pass the update file — fsdecrypt will automatically find the base in the same folder and merge them: + +```bash +fsdecrypt ABCD_1.01.00_20240215143000_1_1.00.00.app +``` + +You can also pass both explicitly: ```bash -# Base + delta update: fsdecrypt extracts both VHDs, then auto-merges fsdecrypt ABCD_1.00.00_20240101120000_0.app ABCD_1.01.00_20240215143000_1_1.00.00.app ``` -The merge workflow (Windows only, requires Hyper-V): -1. Both containers are decrypted and their internal VHDs extracted -2. `Set-VHD` links the delta (differencing) VHD to its parent -3. `Merge-VHD` merges the delta into the base VHD -4. A UAC prompt will appear since these cmdlets require elevation - -If you only provide the delta without its base, fsdecrypt will extract the VHD and print a warning with instructions. - -### Output - -By default, the tool extracts container contents directly: - -| Type | Extracted contents | -|--------|--------------------| -| OS | `internal_{seq}.vhd` | -| APP | `internal_{seq}.vhd` (auto-merged if delta + base provided) | -| OPTION | Directory with all DLC files | - -With `--no-extract`, a raw decrypted image is written instead: - -| Type | Output filename | -|--------|-----------------| -| OS | `{os_id}_{version}_{timestamp}_{seq}.ntfs` | -| APP | `{game_id}_{version}_{timestamp}_{seq}.ntfs` | -| OPTION | `{game_id}_{option}_{timestamp}_{seq}.exfat` | +The output folder is named after the input file (e.g. `ABCD_1.01.00_20240215143000_1_1.00.00/`). ## External Key Files -For games not in the built-in database, place a key file named `{GAME_ID}.bin` in the working directory: +For games not in the built-in key database, place a file named `{GAME_ID}.bin` in the working directory: -- **16 bytes**: AES-128 key only (IV will be derived automatically) -- **32 bytes**: AES-128 key (first 16 bytes) + IV (last 16 bytes) - -## How It Works - -1. The first 128 bytes of the container are decrypted using a hardcoded master key to obtain the **BootID** header -2. The BootID contains metadata: game ID, container type, block layout, and an IV mode flag -3. The game-specific AES-128 key is looked up from the built-in database (or read from an external `.bin` file) -4. If no IV is hardcoded or the container uses a custom IV, the IV is derived by trial-decrypting the first data page against the expected filesystem header (NTFS or ExFAT magic bytes) -5. Each 4096-byte page is decrypted independently using AES-128-CBC, with a per-page IV computed by XORing the file IV with the page's file offset -6. The decrypted stream is parsed as NTFS or ExFAT depending on container type, and contents are extracted - -## Container Types - -| Type | ID | Filesystem | Description | -|------|----|-----------|-------------| -| OS | `0x00` | NTFS | Operating system image | -| APP | `0x01` | NTFS | Game application and assets | -| OPTION | `0x02` | ExFAT | Downloadable content / option packs | +- **16 bytes** for key only (IV derived automatically) +- **32 bytes** for key + IV ## License