From 3f2f5a6e7515087e6834e7957c845d5e6d7c31c6 Mon Sep 17 00:00:00 2001 From: Netanel Cohen Date: Wed, 21 Feb 2024 19:06:55 +0200 Subject: [PATCH] processes: Add `launch` process using `BackBoardService --- src/rpcclient/rpcclient/exceptions.py | 5 ++++ src/rpcclient/rpcclient/ios/client.py | 2 ++ src/rpcclient/rpcclient/ios/processes.py | 37 ++++++++++++++++++++++++ src/rpcclient/tests/test_processes.py | 15 ++++++++++ src/rpcserver/ents.plist | 4 +++ 5 files changed, 63 insertions(+) create mode 100644 src/rpcclient/rpcclient/ios/processes.py diff --git a/src/rpcclient/rpcclient/exceptions.py b/src/rpcclient/rpcclient/exceptions.py index ca14b5ba..29774255 100644 --- a/src/rpcclient/rpcclient/exceptions.py +++ b/src/rpcclient/rpcclient/exceptions.py @@ -105,6 +105,11 @@ class LastElementNotFoundError(ElementNotFoundError): pass +class LaunchError(BadReturnValueError): + """ failed to launch a child process """ + pass + + class RpcFileExistsError(BadReturnValueError): """ RPC version for FileExistsError (errno = EEXIST) """ pass diff --git a/src/rpcclient/rpcclient/ios/client.py b/src/rpcclient/rpcclient/ios/client.py index 92d53d71..b02b3b51 100644 --- a/src/rpcclient/rpcclient/ios/client.py +++ b/src/rpcclient/rpcclient/ios/client.py @@ -7,6 +7,7 @@ from rpcclient.ios.backlight import Backlight from rpcclient.ios.lockdown import Lockdown from rpcclient.ios.mobile_gestalt import MobileGestalt +from rpcclient.ios.processes import IosProcesses from rpcclient.ios.screen_capture import ScreenCapture from rpcclient.ios.sprinboard import SpringBoard from rpcclient.ios.telephony import Telephony @@ -21,6 +22,7 @@ def __init__(self, sock, sysname: str, arch, create_socket_cb: typing.Callable): self.backlight = Backlight(self) self.reports = Reports(self, CRASH_REPORTS_DIR) self.mobile_gestalt = MobileGestalt(self) + self.processes = IosProcesses(self) self.lockdown = Lockdown(self) self.telephony = Telephony(self) self.screen_capture = ScreenCapture(self) diff --git a/src/rpcclient/rpcclient/ios/processes.py b/src/rpcclient/rpcclient/ios/processes.py new file mode 100644 index 00000000..a0fddb93 --- /dev/null +++ b/src/rpcclient/rpcclient/ios/processes.py @@ -0,0 +1,37 @@ +from typing import Optional + +from rpcclient.darwin.processes import DarwinProcesses +from rpcclient.exceptions import LaunchError + + +class IosProcesses(DarwinProcesses): + + def launch(self, bundle_id: str, unlock_device: bool = True, disable_aslr: bool = False, + wait_for_debugger: bool = False, stdout: Optional[str] = None, + stderr: Optional[str] = None) -> int: + """ launch process using BackBoardService + https://github.com/swigger/debugserver-ios/blob/master/inc/BackBoardServices.framework/Headers + /BackBoardServices.h""" + debug_options = {} + options = {} + sym = self._client.symbols + debug_options[sym.BKSDebugOptionKeyDisableASLR[0].py()] = disable_aslr + debug_options[sym.BKSDebugOptionKeyWaitForDebugger[0].py()] = wait_for_debugger + if stdout is not None: + debug_options[sym.BKSDebugOptionKeyStandardOutPath[0].py()] = stdout + if stderr is not None: + debug_options[sym.BKSDebugOptionKeyStandardErrorPath[0].py()] = stderr + + options[sym.BKSOpenApplicationOptionKeyUnlockDevice[0].py()] = unlock_device + options[sym.BKSOpenApplicationOptionKeyDebuggingOptions[0].py()] = debug_options + + bkssystem_service = self._client.objc_get_class('BKSSystemService').new().objc_symbol + bkssystem_service.openApplication_options_clientPort_withResult_(self._client.cf(bundle_id), + self._client.cf(options), + bkssystem_service.createClientPort(), + self._client.get_dummy_block()) + + pid = bkssystem_service.pidForApplication_(self._client.cf(bundle_id)).c_int32 + if pid == -1: + raise LaunchError() + return pid diff --git a/src/rpcclient/tests/test_processes.py b/src/rpcclient/tests/test_processes.py index 64047335..ecca3a50 100644 --- a/src/rpcclient/tests/test_processes.py +++ b/src/rpcclient/tests/test_processes.py @@ -1,6 +1,9 @@ from pathlib import Path +import pytest + from rpcclient.client_factory import DEFAULT_PORT +from rpcclient.exceptions import LaunchError LAUNCHD_PID = 1 LAUNCHD_PATH = '/sbin/launchd' @@ -29,3 +32,15 @@ def test_process_object(client): assert fds[0].fd == 0 assert fds[1].fd == 1 assert fds[2].fd == 2 + + +@pytest.mark.ios +def test_launch_process(client): + pid = client.processes.launch('com.apple.MobileAddressBook') + client.processes.kill(pid) + + +@pytest.mark.ios +def test_launch_invalid_process(client): + with pytest.raises(LaunchError): + client.processes.launch('com.apple.cyber') diff --git a/src/rpcserver/ents.plist b/src/rpcserver/ents.plist index e3c0273e..356ef390 100644 --- a/src/rpcserver/ents.plist +++ b/src/rpcserver/ents.plist @@ -90,6 +90,10 @@ com.apple.backboardd.launchapplications + com.apple.frontboard.debugapplications + + com.apple.frontboard.launchapplications + com.apple.private.logging.admin com.apple.security.exception.shared-preference.read-write