darwin: Fix app listing and launching on iOS >= 16

Some Mach services that were previously running as “root” are now
running as “mobile”. This means they're not in the same launchd domain,
and lookups fail.

While we could run as “mobile” too, our system session would no longer
be running as root, and that would break scripts that assume root
access. Though we could solve that by running multiple daemons, it
would introduce a lot of complexity.

So to solve this we re-route our local process' Mach service lookups
for the service names we know that SpringBoardServices and friends are
using.

Co-authored-by: Håvard Sørbø <[email protected]>
This commit is contained in:
Ole André Vadla RavnåsandHåvard Sørbø committed 2023-02-10 19:23:26 +01:00
1 parent 310ff06b54
commit dccb612f65
2 files changed
+104

No files matched your search

+1
View File
@@ -64,6 +64,7 @@ struct _FridaSpringboardApi
void * fbs;
void * mcs;
mach_port_t (* SBSSpringBoardBackgroundServerPort) (void);
NSString * (* SBSCopyFrontmostApplicationDisplayIdentifier) (void);
NSArray * (* SBSCopyApplicationDisplayIdentifiers) (BOOL active, BOOL debuggable);
NSString * (* SBSCopyDisplayIdentifierForProcessID) (UInt32 pid);
+103
View File
@@ -1,6 +1,7 @@
#import "springboard.h"
#include <dlfcn.h>
#include <gum/gum.h>
#define FRIDA_ASSIGN_SBS_FUNC(N) \
api->N = dlsym (api->sbs, G_STRINGIFY (N)); \
@@ -14,7 +15,25 @@
g_assert (str != NULL); \
api->N = *str
#define FRIDA_IOS_MOBILE_USER_ID 501
extern kern_return_t bootstrap_look_up (mach_port_t bp, const char * service_name, mach_port_t * sp);
extern kern_return_t bootstrap_look_up_per_user (mach_port_t bp, const char * service_name, uid_t target_user, mach_port_t * sp);
extern mach_port_t bootstrap_port;
static kern_return_t frida_replacement_bootstrap_look_up (mach_port_t bp, const char * service_name, mach_port_t * sp);
static kern_return_t frida_replacement_xpc_look_up_endpoint (const char * service_name, uint32_t type, uint64_t handle,
uint64_t lookup_handle, const uint8_t * instance, uint64_t flags, void * cputypes, mach_port_t * port, bool * non_launching);
typedef kern_return_t (* FridaXpcLookUpEndpointFunc) (const char * service_name, uint32_t type, uint64_t handle, uint64_t lookup_handle,
const uint8_t * instance, uint64_t flags, void * cputypes, mach_port_t * port, bool * non_launching);
static FridaXpcLookUpEndpointFunc frida_find_xpc_look_up_endpoint_implementation (void);
static gboolean frida_is_bl_imm (guint32 insn);
static FridaSpringboardApi * frida_springboard_api = NULL;
static FridaXpcLookUpEndpointFunc frida_xpc_look_up_endpoint;
FridaSpringboardApi *
_frida_get_springboard_api (void)
@@ -32,6 +51,7 @@ _frida_get_springboard_api (void)
api->fbs = dlopen ("/System/Library/PrivateFrameworks/FrontBoardServices.framework/FrontBoardServices", RTLD_GLOBAL | RTLD_LAZY);
FRIDA_ASSIGN_SBS_FUNC (SBSSpringBoardBackgroundServerPort);
FRIDA_ASSIGN_SBS_FUNC (SBSCopyFrontmostApplicationDisplayIdentifier);
FRIDA_ASSIGN_SBS_FUNC (SBSCopyApplicationDisplayIdentifiers);
FRIDA_ASSIGN_SBS_FUNC (SBSCopyDisplayIdentifierForProcessID);
@@ -68,8 +88,91 @@ _frida_get_springboard_api (void)
api->LSApplicationProxy = objc_get_class_impl ("LSApplicationProxy");
g_assert (api->LSApplicationProxy != nil);
if (api->SBSSpringBoardBackgroundServerPort () == MACH_PORT_NULL)
{
GumInterceptor * interceptor;
interceptor = gum_interceptor_obtain ();
gum_interceptor_replace (interceptor, bootstrap_look_up, frida_replacement_bootstrap_look_up, NULL, NULL);
frida_xpc_look_up_endpoint = frida_find_xpc_look_up_endpoint_implementation ();
if (frida_xpc_look_up_endpoint != NULL)
gum_interceptor_replace (interceptor, frida_xpc_look_up_endpoint, frida_replacement_xpc_look_up_endpoint, NULL, NULL);
else
g_error ("Unable to locate _xpc_look_up_endpoint(); please file a bug");
}
frida_springboard_api = api;
}
return frida_springboard_api;
}
static kern_return_t
frida_replacement_bootstrap_look_up (mach_port_t bp, const char * service_name, mach_port_t * sp)
{
if (strcmp (service_name, "com.apple.springboard.backgroundappservices") == 0)
return bootstrap_look_up_per_user (bp, service_name, FRIDA_IOS_MOBILE_USER_ID, sp);
return bootstrap_look_up (bp, service_name, sp);
}
static kern_return_t
frida_replacement_xpc_look_up_endpoint (const char * service_name, uint32_t type, uint64_t handle, uint64_t lookup_handle,
const uint8_t * instance, uint64_t flags, void * cputypes, mach_port_t * port, bool * non_launching)
{
if (strcmp (service_name, "com.apple.containermanagerd") == 0 ||
strcmp (service_name, "com.apple.frontboard.systemappservices") == 0 ||
strcmp (service_name, "com.apple.lsd.icons") == 0 ||
strcmp (service_name, "com.apple.lsd.mapdb") == 0 ||
strcmp (service_name, "com.apple.runningboard") == 0 ||
g_str_has_prefix (service_name, "com.apple.distributed_notifications"))
{
if (non_launching != NULL)
*non_launching = false;
return bootstrap_look_up_per_user (bootstrap_port, service_name, FRIDA_IOS_MOBILE_USER_ID, port);
}
return frida_xpc_look_up_endpoint (service_name, type, handle, lookup_handle, instance, flags, cputypes, port, non_launching);
}
static FridaXpcLookUpEndpointFunc
frida_find_xpc_look_up_endpoint_implementation (void)
{
guint32 * cursor;
cursor = GSIZE_TO_POINTER (
gum_strip_code_address (gum_module_find_export_by_name ("/usr/lib/system/libxpc.dylib", "xpc_endpoint_create_bs_named")));
if (cursor == NULL)
return NULL;
do
{
guint32 insn = *cursor;
if (frida_is_bl_imm (insn))
{
union
{
gint32 i;
guint32 u;
} distance;
distance.u = insn & GUM_INT26_MASK;
if ((distance.u & (1 << (26 - 1))) != 0)
distance.u |= 0xfc000000;
return (FridaXpcLookUpEndpointFunc) (cursor + distance.i);
}
cursor++;
}
while (TRUE);
}
static gboolean
frida_is_bl_imm (guint32 insn)
{
return (insn & ~GUM_INT26_MASK) == 0x94000000;
}