mirror of
https://github.com/mvt-project/mvt.git
synced 2024-06-29 07:39:00 +00:00
Adding support for iOS lockdown management
This commit is contained in:
parent
459ff8c51c
commit
a30d7b2871
|
@ -5,6 +5,7 @@
|
|||
|
||||
import datetime
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
|
@ -119,3 +120,14 @@ def keys_bytes_to_string(obj) -> str:
|
|||
new_obj[key] = value
|
||||
|
||||
return new_obj
|
||||
|
||||
|
||||
def secure_delete(file_path, rounds=10):
|
||||
file_size = os.path.getsize(file_path)
|
||||
|
||||
with open(file_path, "br+", buffering=-1) as handle:
|
||||
for i in range(rounds):
|
||||
handle.seek(0)
|
||||
handle.write(os.urandom(file_size))
|
||||
|
||||
os.remove(file_path)
|
||||
|
|
112
mvt/ios/cli.py
112
mvt/ios/cli.py
|
@ -8,7 +8,8 @@ import os
|
|||
|
||||
import click
|
||||
from rich.logging import RichHandler
|
||||
from rich.prompt import Prompt
|
||||
from rich.prompt import Confirm, Prompt
|
||||
from simple_term_menu import TerminalMenu
|
||||
|
||||
from mvt.common.cmd_check_iocs import CmdCheckIOCS
|
||||
from mvt.common.help import (HELP_MSG_FAST, HELP_MSG_IOC,
|
||||
|
@ -22,6 +23,7 @@ from .cmd_check_backup import CmdIOSCheckBackup
|
|||
from .cmd_check_fs import CmdIOSCheckFS
|
||||
from .cmd_check_usb import CmdIOSCheckUSB
|
||||
from .decrypt import DecryptBackup
|
||||
from .lockdown import Lockdown
|
||||
from .modules.backup import BACKUP_MODULES
|
||||
from .modules.fs import FS_MODULES
|
||||
from .modules.mixed import MIXED_MODULES
|
||||
|
@ -188,6 +190,83 @@ def check_fs(ctx, iocs, output, fast, list_modules, module, dump_path):
|
|||
len(cmd.timeline_detected))
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Command: check-usb
|
||||
#==============================================================================
|
||||
@cli.command("check-usb", help="Extract artifacts from a live iPhone through USB")
|
||||
@click.option("--serial", "-s", type=str, help=HELP_MSG_SERIAL)
|
||||
@click.option("--iocs", "-i", type=click.Path(exists=True), multiple=True,
|
||||
default=[], help=HELP_MSG_IOC)
|
||||
@click.option("--output", "-o", type=click.Path(exists=False), help=HELP_MSG_OUTPUT)
|
||||
@click.option("--fast", "-f", is_flag=True, help=HELP_MSG_FAST)
|
||||
@click.option("--list-modules", "-l", is_flag=True, help=HELP_MSG_LIST_MODULES)
|
||||
@click.option("--module", "-m", help=HELP_MSG_MODULE)
|
||||
@click.pass_context
|
||||
def check_usb(ctx, serial, iocs, output, fast, list_modules, module):
|
||||
cmd = CmdIOSCheckUSB(results_path=output, ioc_files=iocs,
|
||||
module_name=module, fast_mode=fast,
|
||||
serial=serial)
|
||||
|
||||
if list_modules:
|
||||
cmd.list_modules()
|
||||
return
|
||||
|
||||
log.info("Checking iPhone through USB, this may take a while")
|
||||
cmd.run()
|
||||
|
||||
if len(cmd.timeline_detected) > 0:
|
||||
log.warning("The analysis of the data produced %d detections!",
|
||||
len(cmd.timeline_detected))
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Command: clear-certs
|
||||
#==============================================================================
|
||||
@cli.command("clear-certs", help="Clear iOS lockdown certificates")
|
||||
@click.pass_context
|
||||
def clear_certs(ctx):
|
||||
lock = Lockdown()
|
||||
certs = lock.find_certs()
|
||||
|
||||
if not certs:
|
||||
log.info("No iOS lockdown certificates found")
|
||||
return
|
||||
|
||||
choices = []
|
||||
for cert in certs:
|
||||
choices.append(os.path.basename(cert))
|
||||
log.info("Found lockdown certificate at %s", cert)
|
||||
|
||||
choices.append("Cancel")
|
||||
|
||||
terminal_menu = TerminalMenu(
|
||||
choices,
|
||||
title="Select which certificates to delete:",
|
||||
multi_select=True,
|
||||
show_multi_select_hint=True,
|
||||
)
|
||||
terminal_menu.show()
|
||||
|
||||
if "Cancel" in terminal_menu.chosen_menu_entries:
|
||||
log.info("Cancel, not proceeding")
|
||||
return
|
||||
|
||||
confirmed = Confirm.ask(f"You have selected {', '.join(terminal_menu.chosen_menu_entries)}. "
|
||||
"Are you sure you want to proceed deleting them?")
|
||||
if not confirmed:
|
||||
log.info("Not proceeding")
|
||||
return
|
||||
|
||||
for choice in terminal_menu.chosen_menu_entries:
|
||||
try:
|
||||
lock.delete_cert(choice)
|
||||
except PermissionError:
|
||||
log.error("Not enough permissions to delete certificate at \"%s\": "
|
||||
"try launching this command with sudo", choice)
|
||||
else:
|
||||
log.info("Deleted lockdown certificate \"%s\"", choice)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Command: check-iocs
|
||||
#==============================================================================
|
||||
|
@ -216,34 +295,3 @@ def check_iocs(ctx, iocs, list_modules, module, folder):
|
|||
def download_iocs():
|
||||
ioc_updates = IndicatorsUpdates()
|
||||
ioc_updates.update()
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Command: check-usb
|
||||
#==============================================================================
|
||||
@cli.command("check-usb", help="Extract artifacts from a live iPhone through USB / lockdown")
|
||||
@click.option("--serial", "-s", type=str, help=HELP_MSG_SERIAL)
|
||||
@click.option("--iocs", "-i", type=click.Path(exists=True), multiple=True,
|
||||
default=[], help=HELP_MSG_IOC)
|
||||
@click.option("--output", "-o", type=click.Path(exists=False), help=HELP_MSG_OUTPUT)
|
||||
@click.option("--fast", "-f", is_flag=True, help=HELP_MSG_FAST)
|
||||
@click.option("--list-modules", "-l", is_flag=True, help=HELP_MSG_LIST_MODULES)
|
||||
@click.option("--module", "-m", help=HELP_MSG_MODULE)
|
||||
# TODO: serial
|
||||
# @click.argument("BACKUP_PATH", type=click.Path(exists=True))
|
||||
@click.pass_context
|
||||
def check_usb(ctx, serial, iocs, output, fast, list_modules, module):
|
||||
cmd = CmdIOSCheckUSB(results_path=output, ioc_files=iocs,
|
||||
module_name=module, fast_mode=fast,
|
||||
serial=serial)
|
||||
|
||||
if list_modules:
|
||||
cmd.list_modules()
|
||||
return
|
||||
|
||||
log.info("Checking iPhone through USB, this may take a while")
|
||||
cmd.run()
|
||||
|
||||
if len(cmd.timeline_detected) > 0:
|
||||
log.warning("The analysis of the data produced %d detections!",
|
||||
len(cmd.timeline_detected))
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
import logging
|
||||
import sys
|
||||
|
||||
from pymobiledevice3.exceptions import ConnectionFailedError
|
||||
from pymobiledevice3.exceptions import (ConnectionFailedError,
|
||||
FatalPairingError, NotTrustedError)
|
||||
from pymobiledevice3.lockdown import LockdownClient
|
||||
|
||||
from mvt.common.command import Command
|
||||
|
@ -35,11 +36,11 @@ class CmdIOSCheckUSB(Command):
|
|||
self.lockdown = LockdownClient(udid=self.serial)
|
||||
else:
|
||||
self.lockdown = LockdownClient()
|
||||
except ConnectionRefusedError:
|
||||
log.error("Unable to connect to the device over USB. Try to unplug, plug the device and start again.")
|
||||
except NotTrustedError:
|
||||
log.error("Trust this computer from the prompt appearing on the iOS device and try again")
|
||||
sys.exit(-1)
|
||||
except ConnectionFailedError:
|
||||
log.error("Unable to connect to the device %s", self.serial)
|
||||
except (ConnectionRefusedError, ConnectionFailedError, FatalPairingError):
|
||||
log.error("Unable to connect to the device over USB: try to unplug, plug the device and start again")
|
||||
sys.exit(-1)
|
||||
|
||||
def module_init(self, module):
|
||||
|
|
58
mvt/ios/lockdown.py
Normal file
58
mvt/ios/lockdown.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2022 Claudio Guarnieri.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
import os
|
||||
import platform
|
||||
|
||||
from mvt.common.utils import secure_delete
|
||||
|
||||
|
||||
class Lockdown:
|
||||
|
||||
def __init__(self, uuids: list = []) -> None:
|
||||
self.uuids = uuids
|
||||
self.lockdown_folder = self._get_lockdown_folder()
|
||||
|
||||
@staticmethod
|
||||
def _get_lockdown_folder():
|
||||
system = platform.system()
|
||||
if system == "Linux":
|
||||
return "/var/lib/lockdown/"
|
||||
elif system == "Darwin":
|
||||
return "/var/db/lockdown/"
|
||||
elif system == "Windows":
|
||||
return os.path.join(os.environ.get("ALLUSERSPROFILE", ""),
|
||||
"Apple", "Lockdown")
|
||||
|
||||
@staticmethod
|
||||
def _get_pymobiledevice_folder():
|
||||
return os.path.expanduser("~/.pymobiledevice3")
|
||||
|
||||
def delete_cert(self, cert_file) -> None:
|
||||
if not self.lockdown_folder:
|
||||
return
|
||||
|
||||
cert_path = os.path.join(self.lockdown_folder, cert_file)
|
||||
if not os.path.exists(cert_path):
|
||||
return
|
||||
|
||||
secure_delete(cert_path)
|
||||
|
||||
def find_certs(self) -> list:
|
||||
if not self.lockdown_folder or not os.path.exists(self.lockdown_folder):
|
||||
return []
|
||||
|
||||
lockdown_certs = []
|
||||
for file_name in os.listdir(self.lockdown_folder):
|
||||
if not file_name.endswith(".plist"):
|
||||
continue
|
||||
|
||||
if file_name == "SystemConfiguration.plist":
|
||||
continue
|
||||
|
||||
file_path = os.path.join(self.lockdown_folder, file_name)
|
||||
lockdown_certs.append(file_path)
|
||||
|
||||
return sorted(lockdown_certs)
|
Loading…
Reference in New Issue
Block a user