add pure-python-adb interface to mvt-android

This commit is contained in:
TÓTH István 2022-05-05 00:32:35 +02:00
parent ff41efba72
commit 4feae446f0
No known key found for this signature in database
GPG Key ID: F4A7D5587B406D08
4 changed files with 46 additions and 6 deletions

View File

@ -37,6 +37,15 @@ mvt-android check-adb --serial 192.168.1.20:5555 --output /path/to/results
Where `192.168.1.20` is the correct IP address of your device.
Connection may not work and fail with STLS error messages (if the TCP connection requires encryption what is not supported in the default adb-shell Python library).
In this case switching to the [pure-python-adb (ppadb)](https://pypi.org/project/pure-python-adb/)
ADB library is preferred. It requires an already running ADB server connected to the Android device. The ADB server should be available at
`127.0.0.1:5037`. The ADB server connection to the device may be USB or Network, it does not matter. The ppadb method is included in MVT:
```bash
mvt-android check-adp --ppadb --serial 192.168.1.20:5555 --output /path/to/results
```
## MVT modules requiring root privileges
Of the currently available `mvt-android check-adb` modules a handful require root privileges to function correctly. This is because certain files, such as browser history and SMS messages databases are not accessible with user privileges through adb. These modules are to be considered OPTIONALLY available in case the device was already jailbroken. **Do NOT jailbreak your own device unless you are sure of what you are doing!** Jailbreaking your phone exposes it to considerable security risks!

View File

@ -58,6 +58,8 @@ def version():
# Command: download-apks
#==============================================================================
@cli.command("download-apks", help="Download all or only non-system installed APKs")
@click.option("--ppadb", "-p", is_flag=True,
help="Use pure-python-adb library on 127.0.0.1:5037 instead of adb-shell (useful for TCP instead of USB connection, ADB server should be up and connected)")
@click.option("--serial", "-s", type=str, help=HELP_MSG_SERIAL)
@click.option("--all-apks", "-a", is_flag=True,
help="Extract all packages installed on the phone, including system packages")
@ -90,6 +92,8 @@ def download_apks(ctx, all_apks, virustotal, koodous, all_checks, output, from_f
log=logging.getLogger(DownloadAPKs.__module__))
if serial:
download.serial = serial
if ppadb:
download.ppadb = True
download.run()
packages = download.packages
@ -111,6 +115,8 @@ def download_apks(ctx, all_apks, virustotal, koodous, all_checks, output, from_f
# Command: check-adb
#==============================================================================
@cli.command("check-adb", help="Check an Android device over adb")
@click.option("--ppadb", "-p", is_flag=True,
help="Use pure-python-adb library on 127.0.0.1:5037 instead of adb-shell (useful for TCP instead of USB connection, ADB server should be up and connected)")
@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)
@ -120,7 +126,7 @@ def download_apks(ctx, all_apks, virustotal, koodous, all_checks, output, from_f
@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_adb(ctx, iocs, output, fast, list_modules, module, serial):
def check_adb(ctx, iocs, output, fast, list_modules, module, serial, ppadb):
if list_modules:
log.info("Following is the list of available check-adb modules:")
for adb_module in ADB_MODULES:
@ -153,6 +159,8 @@ def check_adb(ctx, iocs, output, fast, list_modules, module, serial):
m.indicators.log = m.log
if serial:
m.serial = serial
if ppadb:
m.ppadb = True
run_module(m)
timeline.extend(m.timeline)

View File

@ -20,6 +20,8 @@ from adb_shell.exceptions import (AdbCommandFailureException, DeviceAuthError,
UsbDeviceNotFoundError, UsbReadFailedError)
from usb1 import USBErrorAccess, USBErrorBusy
from ppadb.client import Client as AdbClient
from mvt.android.parsers.backup import (InvalidBackupPassword, parse_ab_header,
parse_backup_file)
from mvt.common.module import InsufficientPrivileges, MVTModule
@ -41,6 +43,7 @@ class AndroidExtraction(MVTModule):
self.device = None
self.serial = None
self.ppadb = False
@staticmethod
def _adb_check_keys():
@ -55,7 +58,19 @@ class AndroidExtraction(MVTModule):
write_public_keyfile(ADB_KEY_PATH, ADB_PUB_KEY_PATH)
def _adb_connect(self):
"""Connect to the device over adb."""
"""Connect wrapper."""
if self.ppadb:
self._adb_connect_ppadb()
else:
self._adb_connect_adbshell()
def _adb_connect_ppadb(self):
"""Connect to the device over adb using ppadb."""
client = AdbClient(host="127.0.0.1", port=5037)
self.device = client.device(self.serial)
def _adb_connect_adbshell(self):
"""Connect to the device over adb using adb-shell."""
self._adb_check_keys()
with open(ADB_KEY_PATH, "rb") as handle:
@ -105,7 +120,8 @@ class AndroidExtraction(MVTModule):
def _adb_disconnect(self):
"""Close adb connection to the device."""
self.device.close()
if not self.ppadb:
self.device.close()
def _adb_reconnect(self):
"""Reconnect to device using adb."""
@ -120,7 +136,10 @@ class AndroidExtraction(MVTModule):
:returns: Output of command
"""
return self.device.shell(command, read_timeout_s=200.0)
if self.ppadb:
return self.device.shell(command)
else:
return self.device.shell(command, read_timeout_s=200.0)
def _adb_check_if_root(self):
"""Check if we have a `su` binary on the Android device.
@ -172,7 +191,10 @@ class AndroidExtraction(MVTModule):
"""
try:
self.device.pull(remote_path, local_path, progress_callback)
if self.ppadb:
self.device.pull(remote_path, local_path)
else:
self.device.pull(remote_path, local_path, progress_callback)
except AdbCommandFailureException as e:
if retry_root:
self._adb_download_root(remote_path, local_path, progress_callback)

View File

@ -29,7 +29,8 @@ requires = (
# Android dependencies:
"adb-shell>=0.4.2",
"libusb1>=2.0.1",
"cryptography>=36.0.1"
"cryptography>=36.0.1",
"pure-python-adb"
)