Merge branch 'extract-key' of https://github.com/pkirkovsky/mvt into pkirkovsky-extract-key

This commit is contained in:
Nex
2021-07-30 18:29:47 +02:00
4 changed files with 101 additions and 1 deletions
+1
View File
@@ -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
+27 -1
View File
@@ -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
+21
View File
@@ -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
+52
View File
@@ -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)