mirror of https://github.com/mvt-project/mvt.git
parent
9d9b77e02e
commit
7fffef77ce
|
@ -7,7 +7,7 @@ Before proceeding, please note that mvt requires Python 3.6+ to run. While it sh
|
||||||
First install some basic dependencies that will be necessary to build all required tools:
|
First install some basic dependencies that will be necessary to build all required tools:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt install python3 python3-pip libusb-1.0-0
|
sudo apt install python3 python3-pip libusb-1.0-0 sqlite3
|
||||||
```
|
```
|
||||||
|
|
||||||
*libusb-1.0-0* is not required if you intend to only use `mvt-ios` and not `mvt-android`.
|
*libusb-1.0-0* is not required if you intend to only use `mvt-ios` and not `mvt-android`.
|
||||||
|
@ -19,7 +19,7 @@ Running MVT on Mac requires Xcode and [homebrew](https://brew.sh) to be installe
|
||||||
In order to install dependencies use:
|
In order to install dependencies use:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
brew install python3 libusb
|
brew install python3 libusb sqlite3
|
||||||
```
|
```
|
||||||
|
|
||||||
*libusb* is not required if you intend to only use `mvt-ios` and not `mvt-android`.
|
*libusb* is not required if you intend to only use `mvt-ios` and not `mvt-android`.
|
||||||
|
|
|
@ -13,6 +13,12 @@ import simplejson as json
|
||||||
|
|
||||||
from .indicators import Indicators
|
from .indicators import Indicators
|
||||||
|
|
||||||
|
class DatabaseNotFoundError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class DatabaseCorruptedError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
class MVTModule(object):
|
class MVTModule(object):
|
||||||
"""This class provides a base for all extraction modules."""
|
"""This class provides a base for all extraction modules."""
|
||||||
|
|
||||||
|
@ -136,9 +142,12 @@ def run_module(module):
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
module.log.exception("The run() procedure of module %s was not implemented yet!",
|
module.log.exception("The run() procedure of module %s was not implemented yet!",
|
||||||
module.__class__.__name__)
|
module.__class__.__name__)
|
||||||
except FileNotFoundError as e:
|
except DatabaseNotFoundError as e:
|
||||||
module.log.info("There might be no data to extract by module %s: %s",
|
module.log.info("There might be no data to extract by module %s: %s",
|
||||||
module.__class__.__name__, e)
|
module.__class__.__name__, e)
|
||||||
|
except DatabaseCorruptedError as e:
|
||||||
|
module.log.error("The %s module database seems to be corrupted and recovery failed: %s",
|
||||||
|
module.__class__.__name__, e)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
module.log.exception("Error in running extraction from module %s: %s",
|
module.log.exception("Error in running extraction from module %s: %s",
|
||||||
module.__class__.__name__, e)
|
module.__class__.__name__, e)
|
||||||
|
|
|
@ -3,10 +3,15 @@
|
||||||
# See the file 'LICENSE' for usage and copying permissions, or find a copy at
|
# See the file 'LICENSE' for usage and copying permissions, or find a copy at
|
||||||
# https://github.com/mvt-project/mvt/blob/main/LICENSE
|
# https://github.com/mvt-project/mvt/blob/main/LICENSE
|
||||||
|
|
||||||
|
import io
|
||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
|
import shutil
|
||||||
|
import sqlite3
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from mvt.common.module import MVTModule
|
from mvt.common.module import MVTModule
|
||||||
|
from mvt.common.module import DatabaseNotFoundError, DatabaseCorruptedError
|
||||||
|
|
||||||
class IOSExtraction(MVTModule):
|
class IOSExtraction(MVTModule):
|
||||||
"""This class provides a base for all iOS filesystem/backup extraction modules."""
|
"""This class provides a base for all iOS filesystem/backup extraction modules."""
|
||||||
|
@ -15,6 +20,31 @@ class IOSExtraction(MVTModule):
|
||||||
is_fs_dump = False
|
is_fs_dump = False
|
||||||
is_sysdiagnose = False
|
is_sysdiagnose = False
|
||||||
|
|
||||||
|
def _recover_database(self, file_path):
|
||||||
|
"""Tries to recover a malformed database by running a .clone command.
|
||||||
|
:param file_path: Path to the malformed database file.
|
||||||
|
"""
|
||||||
|
# TODO: Find a better solution.
|
||||||
|
|
||||||
|
self.log.info("Database at path %s is malformed. Trying to recover...", file_path)
|
||||||
|
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
return
|
||||||
|
|
||||||
|
if not shutil.which("sqlite3"):
|
||||||
|
raise DatabaseCorruptedError("Unable to recover without sqlite3 binary. Please install sqlite3!")
|
||||||
|
|
||||||
|
bak_path = f"{file_path}.bak"
|
||||||
|
shutil.move(file_path, bak_path)
|
||||||
|
|
||||||
|
cmd = f"sqlite3 {bak_path} '.clone {file_path}'"
|
||||||
|
ret = subprocess.call(cmd, shell=True, stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
if ret != 0:
|
||||||
|
raise DatabaseCorruptedError("Recovery of database failed")
|
||||||
|
|
||||||
|
self.log.info("Database at path %s recovered successfully!", file_path)
|
||||||
|
|
||||||
def _find_ios_database(self, backup_ids=None, root_paths=[]):
|
def _find_ios_database(self, backup_ids=None, root_paths=[]):
|
||||||
"""Try to locate the module's database file from either an iTunes
|
"""Try to locate the module's database file from either an iTunes
|
||||||
backup or a full filesystem dump.
|
backup or a full filesystem dump.
|
||||||
|
@ -52,4 +82,20 @@ class IOSExtraction(MVTModule):
|
||||||
if file_path:
|
if file_path:
|
||||||
self.file_path = file_path
|
self.file_path = file_path
|
||||||
else:
|
else:
|
||||||
raise FileNotFoundError("Unable to find the module's database file")
|
raise DatabaseNotFoundError("Unable to find the module's database file")
|
||||||
|
|
||||||
|
# Check if the database is corrupted.
|
||||||
|
conn = sqlite3.connect(self.file_path)
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
try:
|
||||||
|
recover = False
|
||||||
|
cur.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
||||||
|
except sqlite3.DatabaseError as e:
|
||||||
|
if "database disk image is malformed" in str(e):
|
||||||
|
recover = True
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if recover:
|
||||||
|
self._recover_database(self.file_path)
|
||||||
|
|
Loading…
Reference in New Issue