mirror of
https://github.com/mvt-project/mvt.git
synced 2024-06-24 05:18:55 +00:00
Refactored to include functionality in existing DecryptBackup class
This commit is contained in:
parent
bfcfb3aa06
commit
b264ae946d
|
@ -17,7 +17,6 @@ from mvt.common.module import run_module, save_timeline
|
|||
from mvt.common.options import MutuallyExclusiveOption
|
||||
|
||||
from .decrypt import DecryptBackup
|
||||
from .keyutils import KeyUtils
|
||||
from .modules.fs import BACKUP_MODULES, FS_MODULES
|
||||
|
||||
# Setup logging using Rich.
|
||||
|
@ -55,6 +54,7 @@ def cli():
|
|||
@click.argument("BACKUP_PATH", type=click.Path(exists=True))
|
||||
def decrypt_backup(destination, password, key_file, backup_path):
|
||||
backup = DecryptBackup(backup_path, destination)
|
||||
|
||||
if password:
|
||||
backup.decrypt_with_password(password)
|
||||
elif key_file:
|
||||
|
@ -63,13 +63,16 @@ def decrypt_backup(destination, password, key_file, backup_path):
|
|||
raise click.ClickException("Missing required option. Specify either "
|
||||
"--password or --key-file.")
|
||||
|
||||
backup.process_backup()
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# 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",
|
||||
prompt="Enter 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)",
|
||||
|
@ -77,11 +80,12 @@ def decrypt_backup(destination, password, key_file, backup_path):
|
|||
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)
|
||||
backup = DecryptBackup(backup_path)
|
||||
backup.decrypt_with_password(password)
|
||||
backup.get_key()
|
||||
|
||||
if key_file:
|
||||
key_utils.write_key(key_file)
|
||||
else:
|
||||
key_utils.print_key()
|
||||
backup.write_key(key_file)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
|
|
|
@ -18,7 +18,7 @@ class DecryptBackup:
|
|||
using either a password or a key file.
|
||||
"""
|
||||
|
||||
def __init__(self, backup_path, dest_path):
|
||||
def __init__(self, backup_path, dest_path=None):
|
||||
"""Decrypts an encrypted iOS backup.
|
||||
:param backup_path: Path to the encrypted backup folder
|
||||
:param dest_path: Path to the folder where to store the decrypted backup
|
||||
|
@ -26,8 +26,12 @@ class DecryptBackup:
|
|||
self.backup_path = backup_path
|
||||
self.dest_path = dest_path
|
||||
self._backup = None
|
||||
self._decryption_key = None
|
||||
|
||||
def process_backup(self):
|
||||
if not os.path.exists(self.dest_path):
|
||||
os.makedirs(self.dest_path)
|
||||
|
||||
def _process_backup(self):
|
||||
manifest_path = os.path.join(self.dest_path, "Manifest.db")
|
||||
# We extract a decrypted Manifest.db.
|
||||
self._backup.getManifestDB()
|
||||
|
@ -69,9 +73,6 @@ class DecryptBackup:
|
|||
"""
|
||||
log.info("Decrypting iOS backup at path %s with password", self.backup_path)
|
||||
|
||||
if not os.path.exists(self.dest_path):
|
||||
os.makedirs(self.dest_path)
|
||||
|
||||
try:
|
||||
self._backup = iOSbackup(udid=os.path.basename(self.backup_path),
|
||||
cleartextpassword=password,
|
||||
|
@ -79,9 +80,6 @@ class DecryptBackup:
|
|||
except Exception as e:
|
||||
log.exception(e)
|
||||
log.critical("Failed to decrypt backup. Did you provide the correct password?")
|
||||
return
|
||||
else:
|
||||
self._process_backup()
|
||||
|
||||
def decrypt_with_key_file(self, key_file):
|
||||
"""Decrypts an encrypted iOS backup using a key file.
|
||||
|
@ -90,9 +88,6 @@ class DecryptBackup:
|
|||
log.info("Decrypting iOS backup at path %s with key file %s",
|
||||
self.backup_path, key_file)
|
||||
|
||||
if not os.path.exists(self.dest_path):
|
||||
os.makedirs(self.dest_path)
|
||||
|
||||
with open(key_file, "rb") as handle:
|
||||
key_bytes = handle.read()
|
||||
|
||||
|
@ -109,6 +104,31 @@ class DecryptBackup:
|
|||
except Exception as e:
|
||||
log.exception(e)
|
||||
log.critical("Failed to decrypt backup. Did you provide the correct key file?")
|
||||
|
||||
def get_key(self):
|
||||
"""Retrieve and prints the encryption key.
|
||||
"""
|
||||
if not self._backup:
|
||||
return
|
||||
|
||||
self._decryption_key = self._backup.getDecryptionKey()
|
||||
log.info("Derived decryption key for backup at path %s is: \"%s\"",
|
||||
self.backup_path, self._decryption_key)
|
||||
|
||||
def write_key(self, key_path):
|
||||
"""Save extracted key to file.
|
||||
:param key_path: Path to the file where to write the derived decryption key.
|
||||
"""
|
||||
if not self._decryption_key:
|
||||
return
|
||||
|
||||
try:
|
||||
with open(key_path, 'w') as handle:
|
||||
handle.write(self._decryption_key)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
log.critical("Failed to write key to file: %s", key_path)
|
||||
return
|
||||
else:
|
||||
self._process_backup()
|
||||
log.info("Wrote decryption key to file: %s. This file is equivalent to a plaintext password. Keep it safe!",
|
||||
key_path)
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
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)
|
Loading…
Reference in New Issue
Block a user