From 6536ff3cd2b2fac8a2068058735e77479341f19f Mon Sep 17 00:00:00 2001 From: comex Date: Wed, 28 Jan 2015 02:54:21 -0500 Subject: ***yawn*** --- Makefile | 8 +++- ios-bootstrap/generic-dyld-inserted.m | 5 +++ ios-bootstrap/inject-into-launchd.c | 77 +++++++++++++++++++++++++++++++++++ ios-bootstrap/posixspawn-hook.c | 10 +++-- ios-bootstrap/unrestrict-me.c | 11 +++++ lib/darwin/inject.c | 2 + lib/darwin/unrestrict.c | 21 +++++----- script/gen-deb.sh | 2 + 8 files changed, 122 insertions(+), 14 deletions(-) create mode 100644 ios-bootstrap/generic-dyld-inserted.m create mode 100644 ios-bootstrap/inject-into-launchd.c diff --git a/Makefile b/Makefile index 9fd0c34..b11646e 100644 --- a/Makefile +++ b/Makefile @@ -171,9 +171,15 @@ all: safety-dance out/posixspawn-hook.dylib: ios-bootstrap/posixspawn-hook.c out/libsubstitute.dylib $(CC) -dynamiclib -o $@ $< -Lout -lsubstitute +out/generic-dyld-inserted.dylib: ios-bootstrap/generic-dyld-inserted.m out/libsubstitute.dylib + $(CC) -dynamiclib -o $@ $< -Lout -lsubstitute out/unrestrict-me: ios-bootstrap/unrestrict-me.c out/libsubstitute.dylib $(CC) -o $@ $< -Lout -lsubstitute -all: out/posixspawn-hook.dylib out/unrestrict-me + ldid -Sent.plist $@ +out/inject-into-launchd: ios-bootstrap/inject-into-launchd.c out/libsubstitute.dylib + $(CC) -o $@ $< -Lout -lsubstitute -framework IOKit -framework CoreFoundation + ldid -Sent.plist $@ +all: out/posixspawn-hook.dylib out/generic-dyld-inserted.dylib out/unrestrict-me out/inject-into-launchd endif diff --git a/ios-bootstrap/generic-dyld-inserted.m b/ios-bootstrap/generic-dyld-inserted.m new file mode 100644 index 0000000..532b844 --- /dev/null +++ b/ios-bootstrap/generic-dyld-inserted.m @@ -0,0 +1,5 @@ +#include +__attribute__((constructor)) +static void init() { + syslog(LOG_WARNING, "Hi!"); +} diff --git a/ios-bootstrap/inject-into-launchd.c b/ios-bootstrap/inject-into-launchd.c new file mode 100644 index 0000000..1da4a02 --- /dev/null +++ b/ios-bootstrap/inject-into-launchd.c @@ -0,0 +1,77 @@ +#include "substitute.h" +#include "substitute-internal.h" +#include +#include +#include +#include +#include +#include + +void *IOHIDEventCreateKeyboardEvent(CFAllocatorRef, uint64_t, uint32_t, uint32_t, bool, uint32_t); +void *IOHIDEventSystemCreate(CFAllocatorRef); +void *IOHIDEventSystemCopyEvent(void *, uint32_t, void *, uint32_t); + +CFIndex IOHIDEventGetIntegerValue(void *, uint32_t); +enum { + kIOHIDEventTypeKeyboard = 3, + kIOHIDEventFieldKeyboardDown = 3 << 16 | 2, +}; + +static bool button_pressed(uint32_t usage_page, uint32_t usage) { + /* This magic comes straight from Substrate... I don't really understand + * what it's doing. In particular, where is the equivalent kernel + * implementation on OS X? Does it not exist? But I guess Substrate is + * emulating backboardd. */ + void *dummy = IOHIDEventCreateKeyboardEvent(NULL, mach_absolute_time(), + usage_page, usage, + 0, 0); + if (!dummy) { + syslog(LOG_EMERG, "couldn't create dummy HID event"); + return false; + } + void *event_system = IOHIDEventSystemCreate(NULL); + if (!event_system) { + syslog(LOG_EMERG, "couldn't create HID event system"); + return false; + } + void *event = IOHIDEventSystemCopyEvent(event_system, + kIOHIDEventTypeKeyboard, + dummy, 0); + if (!event) { + syslog(LOG_EMERG, "couldn't copy HID event"); + return false; + } + CFIndex ival = IOHIDEventGetIntegerValue(event, kIOHIDEventFieldKeyboardDown); + return ival; +} + +int main(UNUSED int argc, char **argv) { + pid_t pid = argv[1] ? atoi(argv[1]) : 1; /* for testing */ + + if (button_pressed(0x0c, 0xe9) || /* consumer page -> Volume Increment */ + button_pressed(0x0b, 0x21)) { /* telephony page -> Flash */ + syslog(LOG_WARNING, "disabling due to button press"); + return 0; + } + mach_port_t port = 0; + kern_return_t kr = mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_RECEIVE, + &port); + if (kr) { + syslog(LOG_EMERG, "mach_port_allocate: %x", kr); + return 0; + } + const char *lib = "/Library/Substitute/posixspawn-hook.dylib"; + struct shuttle shuttle = { + .type = SUBSTITUTE_SHUTTLE_MACH_PORT, + .u.mach.right_type = MACH_MSG_TYPE_MAKE_SEND, + .u.mach.port = port + }; + char *error; + int ret = substitute_dlopen_in_pid(pid, lib, 0, &shuttle, 1, &error); + if (ret) { + syslog(LOG_EMERG, "substitute_dlopen_in_pid: %s/%s", + substitute_strerror(ret), error); + return 0; + } +} diff --git a/ios-bootstrap/posixspawn-hook.c b/ios-bootstrap/posixspawn-hook.c index 525b597..25c7973 100644 --- a/ios-bootstrap/posixspawn-hook.c +++ b/ios-bootstrap/posixspawn-hook.c @@ -67,7 +67,6 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old, const char *p = orig_dyld_insert; while (*p) { /* W.N.H. */ const char *next = strchr(p, ':') ?: (p + strlen(p)); - printf("p:%s next:%s\n", p, next); /* append if it isn't a copy of ours */ if (!(next - p == sizeof(my_dylib) - 1 && memcmp(next, my_dylib, sizeof(my_dylib) - 1))) { @@ -76,9 +75,10 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old, memcpy(newp, p, next - p); newp += next - p; } - p = next; + if (!*next) + break; + p = next + 1; } - printf("ok\n"); /* append ours if necessary */ if (!safe_mode) { if (newp != newp_orig) @@ -138,6 +138,10 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old, "posixspawn-hook: couldn't start unrestrict-me - oh well..."); goto skip; } + int xstat; + /* reap intermediate to avoid zombie - if it doesn't work, not a big deal */ + if (waitpid(prog_pid, &xstat, 0)) + syslog(LOG_ERR, "posixspawn-hook: couldn't waitpid"); } int ret = old(pid, path, file_actions, &my_attr, argv, envp_to_use); diff --git a/ios-bootstrap/unrestrict-me.c b/ios-bootstrap/unrestrict-me.c index a297471..5a2c6dd 100644 --- a/ios-bootstrap/unrestrict-me.c +++ b/ios-bootstrap/unrestrict-me.c @@ -2,6 +2,8 @@ #include "substitute-internal.h" #include #include +#include +#include int main(int argc, char **argv) { if (argc != 3) { @@ -22,6 +24,15 @@ int main(int argc, char **argv) { return 1; } + /* double fork to avoid zombies */ + int ret = fork(); + if (ret == -1) { + syslog(LOG_EMERG, "unrestrict-me: fork: %s", strerror(errno)); + return 1; + } else if (ret) { + return 0; + } + char *err = NULL; int sret = substitute_ios_unrestrict((pid_t) pid, should_resume[0] == '1', &err); if (sret) { diff --git a/lib/darwin/inject.c b/lib/darwin/inject.c index 76ecbcb..6ec07fa 100644 --- a/lib/darwin/inject.c +++ b/lib/darwin/inject.c @@ -397,6 +397,7 @@ static int do_baton(const char *filename, size_t filelen, bool is64, size_t filelen_rounded = (filelen + 7) & ~7; size_t total_len = baton_len + shuttles_len + filelen_rounded; mach_vm_address_t target_stack_top = target_stackpage_end - total_len; + target_stack_top &= ~7; *target_stack_top_p = target_stack_top; char *stackbuf = calloc(total_len, 1); if (!stackbuf) { @@ -505,6 +506,7 @@ fail: return ret; } +EXPORT int substitute_dlopen_in_pid(int pid, const char *filename, int options, const struct shuttle *shuttle, size_t nshuttle, char **error) { diff --git a/lib/darwin/unrestrict.c b/lib/darwin/unrestrict.c index 6526019..dd852bc 100644 --- a/lib/darwin/unrestrict.c +++ b/lib/darwin/unrestrict.c @@ -2,6 +2,9 @@ #include "substitute-internal.h" #include "darwin/mach-decls.h" #include +#include +#include +#include #include static int unrestrict_macho_header(void *header, size_t size, bool *did_modify_p, @@ -73,21 +76,19 @@ setback: while (1) { /* if calling from unrestrict-me, the process might not have transitioned * yet. if it has, then TASK_DYLD_INFO will be filled with 0. */ - struct task_dyld_info tdi; - mach_msg_type_number_t cnt = TASK_DYLD_INFO_COUNT; + task_basic_info_data_t tbi; + mach_msg_type_number_t cnt = TASK_BASIC_INFO_COUNT; - kern_return_t kr = task_info(task, TASK_DYLD_INFO, (void *) &tdi, &cnt); - if (kr || cnt != TASK_DYLD_INFO_COUNT) { + kern_return_t kr = task_info(task, TASK_BASIC_INFO, (void *) &tbi, &cnt); + if (kr || cnt != TASK_BASIC_INFO_COUNT) { asprintf(error, "task_info: %x", kr); ret = SUBSTITUTE_ERR_MISC; goto fail; } - printf("=>%llx\n", tdi.all_image_info_addr); - printf("=>%llx\n", tdi.all_image_info_size); - if (tdi.all_image_info_size == 0) + if (tbi.user_time.seconds == 0 && tbi.user_time.microseconds == 0) break; if (retries++ == 20) { - asprintf(error, "all_image_info_size was not 0 after 20 retries"); + asprintf(error, "user_time was not 0 after 20 retries"); ret = SUBSTITUTE_ERR_MISC; goto fail; } @@ -168,8 +169,8 @@ setback: ret = SUBSTITUTE_OK; fail: if (should_resume) { - if ((kr = task_resume(task))) { - asprintf(error, "task_resume: %x", kr); + if ((kill(pid, SIGCONT))) { + asprintf(error, "kill: %s", strerror(errno)); ret = SUBSTITUTE_ERR_MISC; } } diff --git a/script/gen-deb.sh b/script/gen-deb.sh index d817ad2..656e61d 100755 --- a/script/gen-deb.sh +++ b/script/gen-deb.sh @@ -13,6 +13,8 @@ ln -s libsubstitute.0.dylib $debroot/usr/lib/libsubstitute.dylib mkdir -p $debroot/usr/include/substitute cp lib/substitute.h $debroot/usr/include/substitute/ cp substrate/substrate.h $debroot/usr/include/substitute/ +mkdir -p $debroot/Library/Substitute +cp out/{posixspawn-hook.dylib,generic-dyld-inserted.dylib,unrestrict-me,inject-into-launchd} $debroot/Library/Substitute/ cp -a DEBIAN $debroot/ sed "s#{VERSION}#$version#g" DEBIAN/control > $debroot/DEBIAN/control #... add bootstrap stuff -- cgit v1.2.3