mirror of
https://github.com/mvt-project/mvt.git
synced 2026-07-07 05:27:55 +02:00
Merge branch 'extract-key' of https://github.com/pkirkovsky/mvt into pkirkovsky-extract-key
This commit is contained in:
@@ -35,6 +35,7 @@ MVT provides two commands `mvt-ios` and `mvt-android` with the following subcomm
|
|||||||
* `check-fs`: Extract artifacts from a full filesystem dump
|
* `check-fs`: Extract artifacts from a full filesystem dump
|
||||||
* `check-iocs`: Compare stored JSON results to provided indicators
|
* `check-iocs`: Compare stored JSON results to provided indicators
|
||||||
* `decrypt-backup`: Decrypt an encrypted iTunes backup
|
* `decrypt-backup`: Decrypt an encrypted iTunes backup
|
||||||
|
* `extract-key`: Extract decryption key from an iTunes backup
|
||||||
* `mvt-android`:
|
* `mvt-android`:
|
||||||
* `check-backup`: Check an Android Backup
|
* `check-backup`: Check an Android Backup
|
||||||
* `download-apks`: Download all or non-safelisted installed APKs
|
* `download-apks`: Download all or non-safelisted installed APKs
|
||||||
|
|||||||
@@ -2,6 +2,32 @@
|
|||||||
|
|
||||||
The backup might take some time. It is best to make sure the phone remains unlocked during the backup process. Afterwards, a new folder will be created under the path you specified using the UDID of the iPhone you backed up.
|
The backup might take some time. It is best to make sure the phone remains unlocked during the backup process. Afterwards, a new folder will be created under the path you specified using the UDID of the iPhone you backed up.
|
||||||
|
|
||||||
|
## Extracting and saving the decryption key (optional)
|
||||||
|
|
||||||
|
If you do not wish to enter a password every time when decrypting a backup, MVT can accept a key file instead. This key can be used with the `decrypt-backup` command.
|
||||||
|
|
||||||
|
To generate a key file, you will need your device backup and the backup password:
|
||||||
|
|
||||||
|
$ mvt-ios extract-key --help
|
||||||
|
Usage: mvt-ios extract-key [OPTIONS] BACKUP_PATH
|
||||||
|
|
||||||
|
Extract decryption key from an iTunes backup
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-p, --password TEXT Password to use to decrypt the backup [required]
|
||||||
|
-k, --key-file FILE Key file to be written (if unset, will print to STDOUT)
|
||||||
|
--help Show this message and exit.
|
||||||
|
|
||||||
|
You can specify the password on the command line, or omit the `-p` option to have MVT prompt for a password. The `-k` option specifies where to save the file containing the decryption key. If `-k` is omitted, MVT will display the decryption key without saving.
|
||||||
|
|
||||||
|
_Note_: This decryption key is sensitive data! Keep the file safe.
|
||||||
|
|
||||||
|
To extract the key and have MVT prompt for a password:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvt-ios extract-key -k /path/to/save/key /path/to/backup
|
||||||
|
```
|
||||||
|
|
||||||
## Decrypting a backup
|
## Decrypting a backup
|
||||||
|
|
||||||
In case you have an encrypted backup, you will need to decrypt it first. This can be done with `mvt-ios` as well:
|
In case you have an encrypted backup, you will need to decrypt it first. This can be done with `mvt-ios` as well:
|
||||||
@@ -25,7 +51,7 @@ In case you have an encrypted backup, you will need to decrypt it first. This ca
|
|||||||
|
|
||||||
--help Show this message and exit.
|
--help Show this message and exit.
|
||||||
|
|
||||||
You can specify either a password via command-line or pass a key file, and you need to specify a destination path where the decrypted backup will be stored. Following is an example usage of `decrypt-backup`:
|
You can specify either a password via command-line or pass a key file, and you need to specify a destination path where the decrypted backup will be stored. If `-p` is omitted, MVT will ask for a password. Following is an example usage of `decrypt-backup`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mvt-ios decrypt-backup -p password -d /path/to/decrypted /path/to/backup
|
mvt-ios decrypt-backup -p password -d /path/to/decrypted /path/to/backup
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from mvt.common.module import run_module, save_timeline
|
|||||||
from mvt.common.options import MutuallyExclusiveOption
|
from mvt.common.options import MutuallyExclusiveOption
|
||||||
|
|
||||||
from .decrypt import DecryptBackup
|
from .decrypt import DecryptBackup
|
||||||
|
from .keyutils import KeyUtils
|
||||||
from .modules.fs import BACKUP_MODULES, FS_MODULES
|
from .modules.fs import BACKUP_MODULES, FS_MODULES
|
||||||
|
|
||||||
# Setup logging using Rich.
|
# Setup logging using Rich.
|
||||||
@@ -62,6 +63,26 @@ def decrypt_backup(destination, password, key_file, backup_path):
|
|||||||
raise click.ClickException("Missing required option. Specify either "
|
raise click.ClickException("Missing required option. Specify either "
|
||||||
"--password or --key-file.")
|
"--password or --key-file.")
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# Command: extract-key
|
||||||
|
#==============================================================================
|
||||||
|
@cli.command("extract-key", help="Extract decryption key from an iTunes backup")
|
||||||
|
@click.option("--password", "-p",
|
||||||
|
help="Password to use to decrypt the backup",
|
||||||
|
prompt="Backup password",
|
||||||
|
hide_input=True, prompt_required=False, required=True)
|
||||||
|
@click.option("--key-file", "-k",
|
||||||
|
help="Key file to be written (if unset, will print to STDOUT)",
|
||||||
|
required=False,
|
||||||
|
type=click.Path(exists=False, file_okay=True, dir_okay=False, writable=True))
|
||||||
|
@click.argument("BACKUP_PATH", type=click.Path(exists=True))
|
||||||
|
def extract_key(password, backup_path, key_file):
|
||||||
|
key_utils = KeyUtils(password, backup_path)
|
||||||
|
if key_file:
|
||||||
|
key_utils.write_key(key_file)
|
||||||
|
else:
|
||||||
|
key_utils.print_key()
|
||||||
|
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
# Command: check-backup
|
# Command: check-backup
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import os
|
||||||
|
import logging
|
||||||
|
from iOSbackup import iOSbackup
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class KeyUtils:
|
||||||
|
"""This class provides functions to extract a backup key from a password.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, password, backup_path):
|
||||||
|
"""Generates a key file for an iOS backup.
|
||||||
|
:param password: Backup encryption password
|
||||||
|
:param key_file: Path to the file where to store the generated key file
|
||||||
|
"""
|
||||||
|
self.password = password
|
||||||
|
self.backup_path = backup_path
|
||||||
|
self._backup = None
|
||||||
|
|
||||||
|
def get_key(self):
|
||||||
|
try:
|
||||||
|
self._backup = iOSbackup(udid=os.path.basename(self.backup_path),
|
||||||
|
cleartextpassword=self.password,
|
||||||
|
backuproot=os.path.dirname(self.backup_path))
|
||||||
|
except Exception as e:
|
||||||
|
log.exception(e)
|
||||||
|
log.critical("Failed to decrypt backup. Did you provide the correct password?")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.decryption_key = self._backup.getDecryptionKey()
|
||||||
|
log.info("Extracted decryption key.")
|
||||||
|
|
||||||
|
def print_key(self):
|
||||||
|
self.get_key()
|
||||||
|
log.info("Decryption key for backup at path %s is:\n %s",
|
||||||
|
self.backup_path, self.decryption_key)
|
||||||
|
|
||||||
|
def write_key(self, key_file):
|
||||||
|
self.get_key()
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(key_file, 'w') as writer:
|
||||||
|
writer.write(self.decryption_key)
|
||||||
|
except Exception as e:
|
||||||
|
log.exception(e)
|
||||||
|
log.critical("Failed to write key file.")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.info("Wrote decryption key for backup at path %s to file %s",
|
||||||
|
self.backup_path, key_file)
|
||||||
|
log.warn("The file %s is equivalent to a plaintext password. Keep this file safe!",
|
||||||
|
key_file)
|
||||||
Reference in New Issue
Block a user