From b5b10b9ae143494b2fc0db50b8e28a0db2196763 Mon Sep 17 00:00:00 2001 From: betameta123 Date: Sun, 9 Mar 2025 19:52:43 -0500 Subject: [PATCH 1/4] change scanning to use pymobiledevice3 --- config.py | 4 ++-- phone_scanner/__init__.py | 4 ++-- scripts/ios_dump.sh | 15 +++++++++------ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/config.py b/config.py index 65688fd6..4d7786ba 100644 --- a/config.py +++ b/config.py @@ -57,8 +57,8 @@ def setup_logger(): IOS_DUMPFILES = { "Jailbroken-FS": "ios_jailbroken.log", "Jailbroken-SSH": "ios_jailbreak_ssh.retcode", - "Apps": "ios_apps.plist", - "Info": "ios_info.xml", + "Apps": "ios_apps.json", + "Info": "ios_info.json", } TEST_APP_LIST = "static_data/android.test.apps_list" diff --git a/phone_scanner/__init__.py b/phone_scanner/__init__.py index 991aa365..717e8983 100644 --- a/phone_scanner/__init__.py +++ b/phone_scanner/__init__.py @@ -524,8 +524,8 @@ def _is_device(x): """Is it looks like a serial number""" return re.match(r"[a-f0-9]+", x) is not None - # cmd = '{cli} --detect -t1 | tail -n 1' - cmd = "{}idevice_id -l | tail -n 1".format(self.cli) + # cmd = "{}idevice_id -l | tail -n 1".format(self.cli) + cmd = "{}pymobiledevice3 usbmux list | awk -F'\"' '/Identifier/ {{print $4}}'".format(self.cli) self.serialno = None s = catch_err(run_command(cmd), cmd=cmd, msg="") diff --git a/scripts/ios_dump.sh b/scripts/ios_dump.sh index 421ff569..2511c5c4 100755 --- a/scripts/ios_dump.sh +++ b/scripts/ios_dump.sh @@ -12,26 +12,29 @@ fi echo "$platform" "$adb" -serial=$(idevice_id -l 2>&1 | tail -n 1) +# serial=$(idevice_id -l 2>&1 | tail -n 1) +serial=$(pymobiledevice3 usbmux list | awk -F'"' '/Identifier/ {print $4}') mkdir -p phone_dumps/"$1"_ios cd phone_dumps/"$1"_ios # gets all of the details about each app (basically what ios_deploy does but with extra fields) -ideviceinstaller -u "$serial" -l -o xml -o list_all > "$2" +# ideviceinstaller -u "$serial" -l -o xml -o list_all > "$2" +pymobiledevice3 apps list > "$2" # get around bug in Python 3 that doesn't recognize utf-8 encodings. # sed -i -e 's///g' $2 # sed -i -e 's/<\/data>/<\/string>/g' $2 # maybe for macOS... -# plutil -convert json $2 +# plutil -convert json $2 # gets OS version, serial, etc. -x for xml. Raw is easy to parse, too. -ideviceinfo -u "$serial" -x > $3 +# ideviceinfo -u "$serial" -x > $3 +pymobiledevice3 lockdown info > "$3" # sed -i -e 's///g' $3 # sed -i -e 's/<\/data>/<\/string>/g' $3 -# remove identifying info (delete file after saving +# remove identifying info (delete file after saving # relevant bits of scan in server.py, actually) #sed -i -e '/<\key>DeviceName<\/key>/,+1d' $3 #sed -i -e '/<\key>MobileEquipmentIdentifier<\/key>/,+1d' $3 @@ -45,7 +48,7 @@ ideviceinfo -u "$serial" -x > $3 # delete this after hashing when session ends. #sed -i -e '/<\key>InternationalMobileEquipmentIdentity<\/key>/,+1d' $3 -# try to check for jailbroken by mounting the entire filesystem. +# try to check for jailbroken by mounting the entire filesystem. # Gets output: # "Failed to start AFC service 'com.apple.afc2' on the device. # This service enables access to the root filesystem of your device. From deca021bf081b9c3cc2c10651ccd492024823e57 Mon Sep 17 00:00:00 2001 From: betameta123 Date: Sun, 9 Mar 2025 20:10:54 -0500 Subject: [PATCH 2/4] add parsing new parsing logic for json files to be compatible with pymobiledevice3 --- phone_scanner/parse_dump.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/phone_scanner/parse_dump.py b/phone_scanner/parse_dump.py index 2b319717..0f0f5fa9 100644 --- a/phone_scanner/parse_dump.py +++ b/phone_scanner/parse_dump.py @@ -9,7 +9,7 @@ from collections import OrderedDict from functools import reduce from pathlib import Path -from plistlib import load +# from plistlib import load from typing import List, Dict import pandas as pd from rsonlite import simpleparse @@ -463,7 +463,7 @@ def __len__(self): def load_device_info(self): try: with open(self.finfo, "rb") as data: - device_info = load(data) + device_info = json.load(data) return device_info except Exception as ex: @@ -479,11 +479,14 @@ def load_device_info(self): def load_file(self): # d = pd.read_json(self.fname)[self.COLS].set_index(self.INDEX) try: - # FIXME: somehow, get the ios_apps.plist into a dataframe. print("fname is: {}".format(self.fname)) - with open(self.fname, "rb") as app_data: - apps_plist = load(app_data) - d = pd.DataFrame(apps_plist) + apps_list = [] + with open(self.fname, "r") as app_data: + apps_json = json.load(app_data) + for k in apps_json: + apps_list.append(apps_json[k]) + + d = pd.DataFrame(apps_list) d["appId"] = d["CFBundleIdentifier"] return d except Exception as ex: From 48804073e6346b962e43047bdfac1bade796ff91 Mon Sep 17 00:00:00 2001 From: betameta123 Date: Sun, 9 Mar 2025 20:20:36 -0500 Subject: [PATCH 3/4] preform IOS scanning using pymobiledevice3 --- phone_scanner/__init__.py | 2 +- requirements.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/phone_scanner/__init__.py b/phone_scanner/__init__.py index 717e8983..0d543f8c 100644 --- a/phone_scanner/__init__.py +++ b/phone_scanner/__init__.py @@ -525,7 +525,7 @@ def _is_device(x): return re.match(r"[a-f0-9]+", x) is not None # cmd = "{}idevice_id -l | tail -n 1".format(self.cli) - cmd = "{}pymobiledevice3 usbmux list | awk -F'\"' '/Identifier/ {{print $4}}'".format(self.cli) + cmd = "pymobiledevice3 usbmux list | awk -F'\"' '/Identifier/ {{print $4}}'" self.serialno = None s = catch_err(run_command(cmd), cmd=cmd, msg="") diff --git a/requirements.txt b/requirements.txt index e95412bb..67ddb4ef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,6 +18,7 @@ Mako>=1.2.4 MarkupSafe>=2.1.1 numpy>=1.23.5 pandas>=1.5.2 +pymobiledevice3==4.20.17 pycodestyle>=2.10.0 python-dateutil>=2.8.2 python-dotenv>=0.10.3 From 0a575211788cf6cc99eb50fdddd56b362a4805c7 Mon Sep 17 00:00:00 2001 From: betameta123 Date: Sun, 9 Mar 2025 20:27:05 -0500 Subject: [PATCH 4/4] implement uninstall apps using pymobiledevice3 --- phone_scanner/__init__.py | 40 +-------------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/phone_scanner/__init__.py b/phone_scanner/__init__.py index 0d543f8c..173765b9 100644 --- a/phone_scanner/__init__.py +++ b/phone_scanner/__init__.py @@ -461,39 +461,6 @@ def __init__(self): self.serialno = None self.parse_dump = None - def setup(self, attempt_remount=False): - """FIXME: iOS setup.""" - if config.PLATFORM == "linux" and attempt_remount: - # should show GUI prompt for password. sudo apt install policykit-1 if not there. - cmd = "pkexec '" + config.SCRIPT_DIR + "/ios_mount_linux.sh' mount" - # mountmsg = run_command(cmd).stderr.read().decode('utf-8') - if catch_err(run_command(cmd)) == -1: - return ( - False, - "Couldn't detect device. See {}/ios_mount_linux.sh.".format( - config.SCRIPT_DIR - ), - ) - cmd = "{}idevicepair pair".format(self.cli) - pairmsg = run_command(cmd).stdout.read().decode("utf-8") - if "No device found, is it plugged in?" in pairmsg: - return (False, pairmsg) - elif "Please enter the passcode on the device and retry." in pairmsg: - return ( - False, - "Please unlock your device and follow the trust dialog" - " (you will need to enter your passcode). Then try to scan again.", - ) - elif "SUCCESS: Paired with device" in pairmsg: - return (True, "Device successfully paired. Setup complete.") - elif "said that the user denied the trust dialog." in pairmsg: - return ( - False, - "The trust dialog was denied. Please unplug the device" - ", reconnect it, and scan again -- accept the trust dialog to proceed.", - ) - return (True, "Follow trust dialog on iOS device to continue.") - # TODO: This might send titles out of order. Fix this to send both appid and # titles. def get_app_titles(self, serialno): @@ -557,11 +524,6 @@ def _load_dump(self, serial) -> parse_dump.IosDump: def _dump_phone(self, serial: str) -> bool: print("DUMPING iOS INFO...") - connected, connected_reason = self.setup() - if not connected: - print("Couldn't connect to the device. Trying to reconnect. Over here.") - print(connected_reason) - return False hmac_serial = config.hmac_serial(serial) cmd = ( "'{}/ios_dump.sh' {} {Apps} {Info} {Jailbroken-FS} {Jailbroken-SSH}".format( @@ -583,7 +545,7 @@ def _dump_phone(self, serial: str) -> bool: def uninstall(self, serial, appid): # cmd = '{cli} -i {serial} --uninstall_only --bundle_id {appid!r}' # cmd = 'ideviceinstaller --udid {} --uninstall {appid!r}'.format(serial, appid) - cmd = f"{self.cli}ideviceinstaller --uninstall {appid!r}" + cmd = f"pymobiledevice3 apps uninstall {appid!r}" s = catch_err(run_command(cmd, appid=appid), cmd=cmd, msg="Could not uninstall") return s != -1