diff --git a/.gitignore b/.gitignore index d7ba3c0..f7c8fbc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ contrib/** +dep_root/** !dep_root/.keep !contrib/.keep contrib/ @@ -18,4 +19,4 @@ Payload docs/*.html build src/*.dmg.c -.idea \ No newline at end of file +.idea diff --git a/Makefile b/Makefile index 8b10d47..fb69edb 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ STRIP = strip CC ?= cc CFLAGS += -I$(DEP)/include -I$(SRC)/include -I$(SRC) CFLAGS += -Wall -Wextra -DPALERAIN_VERSION=\"2.0.0\" -Wall -Wextra -Wno-unused-parameter -CFLAGS += -Wno-unused-variable -I$(SRC)/src -std=c99 -pedantic-errors -D_C99_SOURCE -D_POSIX_C_SOURCE=199506L +CFLAGS += -Wno-unused-variable -I$(SRC)/src -std=c99 -pedantic-errors -D_C99_SOURCE -D_POSIX_C_SOURCE=199506L -D_DARWIN_C_SOURCE LIBS += $(DEP)/lib/libimobiledevice-1.0.a $(DEP)/lib/libirecovery-1.0.a $(DEP)/lib/libusbmuxd-2.0.a LIBS += $(DEP)/lib/libimobiledevice-glue-1.0.a $(DEP)/lib/libplist-2.0.a -pthread ifeq ($(TARGET_OS),) diff --git a/docs/palera1n.1 b/docs/palera1n.1 index cc47d4c..5895661 100644 --- a/docs/palera1n.1 +++ b/docs/palera1n.1 @@ -11,7 +11,7 @@ .Nd iOS 15+ arm64 iOS/iPadOS jailbreaking tool .Sh SYNOPSIS .Nm -.Op Fl cCdDfhlLOpsvV +.Op Fl cCdDEfhlnLOpRsvV .Op Fl e Ar Boot arguments .Op Fl k Ar Pongo image .Op Fl o Ar overlay file @@ -122,6 +122,8 @@ argument is used by and cannot be overriden. Additionally, the .Em wdt=-1 argument is used during fakefs setup. +.It Fl E , -enter-recovery +Exit after entering recovery mode.q .It Fl f , -fakefs Jailbreak in rootful mode. .It Fl h , -help @@ -149,6 +151,8 @@ is specified. Makes jbinit log to .Em /cores/jbinit.log This file may be viewed from sandboxed applications while jailbroken. +.It Fl n , -exit-recovery +Exit recovery mode and exit. .It Fl o , -override-overlay Ar overlay file Specify the path to a custom overlay file, which is then mounted onto /cores/binpack during boot, if the default ramdisk is used. The default ramdisk expects the overlay @@ -172,6 +176,8 @@ Override the ramdisk. At a very minimum, it should contain a as well as a fake dyld .Em /usr/lib/dyld where the logic is expected to be in. +.It Fl R , -reboot-device +Reboot device in normal mode and exit. .It Fl s , -safe-mode Enter safe mode. An alert will be displayed. Jailbreak daemons nor early boot executable files specified (see @@ -188,7 +194,7 @@ Boots the device in verbose mode, allowing boot logs to be seen. .It TMPDIR This environmental variable should contain the a directory for temporary files. Without the -.Fl 1 , -override-checkra1n +.Fl i , -override-checkra1n option, files must be executable from it as the built-in checkra1n file is extracted and executed here. When not set, /tmp is used. .El @@ -219,6 +225,10 @@ To verbose boot in rootful mode: .Pp .Dl "palera1n -Vf" .Pp +To exit recovery mode: +.Pp +.Dl "palera1n -n" +.Pp .Sh CAVEATS .Pp .Em -v diff --git a/include/kerninfo.h b/include/kerninfo.h index 1d1bd1b..1f6f0c9 100644 --- a/include/kerninfo.h +++ b/include/kerninfo.h @@ -64,6 +64,22 @@ #define palerain_option_test2 (1 << 30) #endif +// palerain host options +#define host_option_dfuhelper_only (1 << 0) /* dfuhelper only */ +#define host_option_pongo_exit (1 << 1) /* boot to clean pongo shell */ +#ifdef DEV_BUILD +#define host_option_tui (1 << 2) /* use terminal user interface */ +#else +#define host_option_res1 (1 << 2) /* reserved */ +#endif +#define host_option_demote (1 << 3) /* Demote effective production fuse status */ +#define host_option_no_ohio (1 << 4) /* Disable Ohio (Analytics) */ +#define host_option_pongo_full (1 << 5) /* Boot to pongo with default images and options */ +#define host_option_palerain_version (1 << 6) /* Print version */ +#define host_option_exit_recovery (1 << 7) /* Exit recovery mode */ +#define host_option_reboot_device (1 << 8) /* Reboot device in normal mode */ +#define host_option_enter_recovery (1 << 9) /* Enter recovery mode */ + #define PALEINFO_MAGIC 'PLSH' #define PALEINFO_CIGAM 'HSLP' diff --git a/include/palerain.h b/include/palerain.h index 5cc7f35..527fee9 100644 --- a/include/palerain.h +++ b/include/palerain.h @@ -140,15 +140,15 @@ typedef struct { typedef unsigned char niarelap_file_t[]; extern unsigned int verbose; -extern int demote; extern char* pongo_path; - -extern bool dfuhelper_only, pongo_exit; #ifdef DEV_BUILD -extern bool use_tui, tui_started; +extern bool tui_started; #endif +extern checkrain_option_t host_flags; +extern checkrain_option_p host_flags_p; + extern pthread_t dfuhelper_thread, pongo_thread; extern int pongo_thr_running, dfuhelper_thr_running; @@ -161,9 +161,8 @@ extern pthread_mutex_t log_mutex; extern pthread_mutex_t spin_mutex, found_pongo_mutex, ecid_dfu_wait_mutex; -extern int enable_rootful, demote; extern int pongo_thr_running, dfuhelper_thr_running; -extern bool ohio, pongo_full, device_has_booted; +extern bool device_has_booted; extern char xargs_cmd[0x270]; extern char checkrain_flags_cmd[0x20]; extern char palerain_flags_cmd[0x20]; @@ -172,8 +171,6 @@ extern char dtpatch_cmd[0x20]; extern char rootfs_cmd[512]; extern char* ext_checkra1n; -extern bool palerain_version; - void thr_cleanup(void* ptr); void* dfuhelper(void* ptr); int p1_log(log_level_t loglevel, const char *fname, int lineno, const char *fxname, char* __restrict format, ...); diff --git a/src/dfuhelper.c b/src/dfuhelper.c index 8a3e2ad..67c0876 100644 --- a/src/dfuhelper.c +++ b/src/dfuhelper.c @@ -77,6 +77,11 @@ int connected_normal_mode(const usbmuxd_device_info_t *usbmuxd_device) { LOG(LOG_INFO, "Telling device with udid %s to enter recovery mode immediately", usbmuxd_device->udid); enter_recovery_cmd(usbmuxd_device->udid); devinfo_free(&dev); + if (checkrain_option_enabled(host_flags, host_option_enter_recovery)) { + device_has_booted = true; + set_spin(0); + unsubscribe_cmd(); + } return 0; } @@ -144,8 +149,8 @@ void* connected_dfu_mode(struct irecv_device_info* info) { puts(""); LOG(LOG_INFO, "Device entered DFU mode successfully"); } - unsubscribe_cmd(); set_spin(0); + unsubscribe_cmd(); pthread_exit(NULL); return NULL; } @@ -155,6 +160,16 @@ void device_event_cb(const usbmuxd_event_t *event, void* userdata) { switch (event->event) { case UE_DEVICE_ADD: LOG(LOG_VERBOSE, "Normal mode device connected"); + if (checkrain_option_enabled(host_flags, host_option_exit_recovery)) { + break; + } else if (checkrain_option_enabled(host_flags, host_option_reboot_device)) { + reboot_cmd(event->device.udid); + LOG(LOG_INFO, "Restarted device"); + set_spin(0); + unsubscribe_cmd(); + pthread_exit(NULL); + break; + } connected_normal_mode(&event->device); break; case UE_DEVICE_REMOVE: @@ -170,9 +185,27 @@ void irecv_device_event_cb(const irecv_device_event_t *event, void* userdata) { case IRECV_DEVICE_ADD: if (event->mode == IRECV_K_RECOVERY_MODE_1 || event->mode == IRECV_K_RECOVERY_MODE_2 || event->mode == IRECV_K_RECOVERY_MODE_3 || event->mode == IRECV_K_RECOVERY_MODE_4) { LOG(LOG_VERBOSE, "Recovery mode device %ld connected", event->device_info->ecid); + if (checkrain_option_enabled(host_flags, host_option_exit_recovery)) { + exitrecv_cmd(event->device_info->ecid); + LOG(LOG_INFO, "Exited recovery mode"); + device_has_booted = true; + set_spin(0); + unsubscribe_cmd(); + if (dfuhelper_thr_running) pthread_cancel(dfuhelper_thread); + pthread_exit(NULL); + break; + } + if (checkrain_option_enabled(host_flags, host_option_enter_recovery) || + checkrain_option_enabled(host_flags, host_option_reboot_device)) return; pthread_create(&recovery_thread, NULL, (void* (*)(void*))connected_recovery_mode, event->device_info); } else if (event->mode == IRECV_K_DFU_MODE) { LOG(LOG_VERBOSE, "DFU mode device %ld connected", event->device_info->ecid); + if ( + checkrain_option_enabled(host_flags, host_option_exit_recovery) || + checkrain_option_enabled(host_flags, host_option_enter_recovery) || + checkrain_option_enabled(host_flags, host_option_reboot_device)) { + break; + } pthread_create(&dfu_thread, NULL, (void* (*)(void*))connected_dfu_mode, event->device_info); } break; diff --git a/src/exec_checkra1n.c b/src/exec_checkra1n.c index 2b2594d..ee91dde 100644 --- a/src/exec_checkra1n.c +++ b/src/exec_checkra1n.c @@ -55,7 +55,7 @@ int exec_checkra1n() { } checkra1n_exec: {}; char args[0x10] = "-pE"; - if (demote) strncat(args, "d", 0xf); + if (checkrain_option_enabled(host_flags, host_option_demote)) strncat(args, "d", 0xf); if (verbose >= 2) strncat(args, "v", 0xf); if (pongo_path != NULL) strncat(args, "k", 0xf); // keep this at last pid_t pid; diff --git a/src/log.c b/src/log.c index 1bf0c35..ccc2f02 100644 --- a/src/log.c +++ b/src/log.c @@ -12,7 +12,7 @@ int p1_log(log_level_t loglevel, const char *fname, int lineno, const char *fxna { if (verbose >= 5 #ifdef DEV_BUILD - && !use_tui + && !checkrain_option_enabled(host_flags, host_option_tui) #endif ) fprintf(stderr, "p1_log: loglevel %d from %s:%d:%s()\n", loglevel, fname, lineno, fxname); int ret = 0; @@ -58,7 +58,7 @@ int p1_log(log_level_t loglevel, const char *fname, int lineno, const char *fxna break; } #ifdef DEV_BUILD - if (use_tui && tui_started) { + if (checkrain_option_enabled(host_flags, host_option_tui) && tui_started) { newtComponent co = get_tui_log(); if (co == NULL) { return 0; /* 0 bytes printed */ diff --git a/src/main.c b/src/main.c index 9632fb0..64ec829 100644 --- a/src/main.c +++ b/src/main.c @@ -33,8 +33,6 @@ #define OVERRIDE_MAGIC 0xd803b376 unsigned int verbose = 0; -int enable_rootful = 0, demote = 0; -bool ohio = true; char xargs_cmd[0x270] = "xargs ", checkrain_flags_cmd[0x20] = "deadbeef", palerain_flags_cmd[0x20] = "deadbeef"; char kpf_flags_cmd[0x20] = "deadbeef", dtpatch_cmd[0x20] = "deadbeef", rootfs_cmd[512] = "deadbeef"; extern char** environ; @@ -84,9 +82,8 @@ int build_checks() { return 0; } -bool dfuhelper_only = false, pongo_exit = false, palerain_version = false; #ifdef DEV_BUILD -bool use_tui = false, tui_started = false; +bool tui_started = false; #endif int palera1n(int argc, char *argv[]) { @@ -97,9 +94,9 @@ int palera1n(int argc, char *argv[]) { pthread_mutex_init(&ecid_dfu_wait_mutex, NULL); if ((ret = build_checks())) return ret; if ((ret = optparse(argc, argv))) goto cleanup; - if (palerain_version) goto normal_exit; + if (checkrain_option_enabled(host_flags, host_option_palerain_version)) goto normal_exit; #ifdef DEV_BUILD - if (use_tui) { + if (checkrain_option_enabled(host_flags, host_option_tui)) { ret = tui(); if (ret) goto cleanup; else goto normal_exit; @@ -110,10 +107,14 @@ int palera1n(int argc, char *argv[]) { pthread_create(&dfuhelper_thread, NULL, dfuhelper, NULL); pthread_join(dfuhelper_thread, NULL); set_spin(0); - if (dfuhelper_only || device_has_booted) + if (checkrain_option_enabled(host_flags, host_option_dfuhelper_only) || + checkrain_option_enabled(host_flags, host_option_reboot_device) || + checkrain_option_enabled(host_flags, host_option_exit_recovery) || + checkrain_option_enabled(host_flags, host_option_enter_recovery) || + device_has_booted) goto normal_exit; if (exec_checkra1n()) goto cleanup; - if (pongo_exit || demote) + if (checkrain_option_enabled(host_flags, host_option_pongo_exit) || checkrain_option_enabled(host_flags, host_option_demote)) goto normal_exit; set_spin(1); sleep(2); @@ -124,7 +125,7 @@ int palera1n(int argc, char *argv[]) { sleep(1); } normal_exit: - if (access("/usr/bin/curl", F_OK) == 0 && ohio) { + if (access("/usr/bin/curl", F_OK) == 0 && !checkrain_option_enabled(host_flags, host_option_no_ohio)) { LOG(LOG_VERBOSE4, "Ohio"); char* ohio_argv[] = { "/usr/bin/curl", diff --git a/src/optparse.c b/src/optparse.c index d3d4562..e30ac5e 100644 --- a/src/optparse.c +++ b/src/optparse.c @@ -12,6 +12,8 @@ #include #include +checkrain_option_t host_flags = 0; +checkrain_option_p host_flags_p = &host_flags; static struct option longopts[] = { {"setup-fakefs", no_argument, NULL, 'c'}, @@ -36,6 +38,9 @@ static struct option longopts[] = { {"override-kpf", required_argument, NULL, 'K'}, {"disable-ohio", no_argument, NULL, 'O'}, {"override-checkra1n", required_argument, NULL, 'i'}, + {"reboot-device", no_argument, NULL, 'R'}, + {"exit-recovery", no_argument, NULL, 'n'}, + {"enter-recovery", no_argument, NULL, 'E'}, #ifdef DEV_BUILD {"test1", no_argument, NULL, '1'}, {"test2", no_argument, NULL, '2'}, @@ -48,9 +53,9 @@ static int usage(int e, char* prog_name) { fprintf(stderr, #ifdef DEV_BUILD - "Usage: %s [-12cCdDfhlLOpstvV]" + "Usage: %s [-12cCdDEfhlLnOpRstvV]" #else - "Usage: %s [-cCdDfhlLOpsvV]" + "Usage: %s [-cCdDEfhlLnOpRsvV]" #endif " [-e boot arguments] [-k Pongo image] [-o overlay file] [-r ramdisk file] [-K KPF file] [-i checkra1n file]\n" "Copyright (C) 2023, palera1n team, All Rights Reserved.\n\n" @@ -66,6 +71,7 @@ static int usage(int e, char* prog_name) "\t-d, --demote\t\t\t\tDemote\n" "\t-D, --dfuhelper-only\t\t\tExit after entering DFU\n" "\t-e, --boot-args \tXNU boot arguments\n" + "\t-E, --enter-recovery\t\t\tEnter recovery mode\n" "\t-f, --fakefs \t\t\t\tBoots fakefs\n" "\t-h, --help\t\t\t\tShow this help\n" "\t-i, --override-checkra1n \t\tOverride checkra1n\n" @@ -73,11 +79,13 @@ static int usage(int e, char* prog_name) "\t-K, --override-kpf \t\tOverride kernel patchfinder\n" "\t-l, --rootless\t\t\t\tBoots rootless. This is the default\n" "\t-L, --jbinit-log-to-file\t\tMake jbinit log to /cores/jbinit.log (can be read from sandbox while jailbroken)\n" + "\t-n, --exit-recovery\t\t\tExit recovery mode\n" "\t-o, --override-overlay \t\tOverride overlay\n" "\t-O, --disable-ohio\t\t\tDisable Ohio\n" "\t-p, --pongo-shell\t\t\tBoots to PongoOS shell\n" "\t-P, --pongo-full\t\t\tBoots to a PongoOS shell with default images already uploaded\n" "\t-r, --override-ramdisk \t\tOverride ramdisk\n" + "\t-R, --reboot-device\t\t\tReboot connected device in normal mode\n" "\t-s, --safe-mode\t\t\t\tEnter safe mode\n" "\t-v, --debug-logging\t\t\tEnable debug logging\n" "\t\tThis option can be repeated for extra verbosity.\n" @@ -98,9 +106,9 @@ int optparse(int argc, char* argv[]) { int index; while ((opt = getopt_long(argc, argv, #ifdef DEV_BUILD - "12cCDhpvVldsOLtfPe:o:r:K:k:i:", + "12cCDEhpvVldsOLftRnPe:o:r:K:k:i:", #else - "cCDhpvVldsOLfPe:o:r:K:k:i:", + "cCDEhpvVldsOLfRnPe:o:r:K:k:i:", #endif longopts, NULL)) != -1) { @@ -115,13 +123,13 @@ int optparse(int argc, char* argv[]) { kpf_flags |= checkrain_option_verbose_boot; break; case 'p': - pongo_exit = true; + host_flags |= host_option_pongo_exit; break; case 'P': - pongo_full = 1; + host_flags |= host_option_pongo_full; break; case 'D': - dfuhelper_only = true; + host_flags |= host_option_dfuhelper_only; break; case 'h': usage(0, argv[0]); @@ -145,16 +153,19 @@ int optparse(int argc, char* argv[]) { case 'f': snprintf(rootfs_cmd, sizeof(rootfs_cmd), "rootfs %s", optarg); snprintf(dtpatch_cmd, 0x20, "dtpatch %s", optarg); - enable_rootful = 1; + palerain_flags |= palerain_option_rootful; break; case 'l': - enable_rootful = 0; + palerain_flags &= ~palerain_option_rootful; break; case 'L': palerain_flags |= palerain_option_jbinit_log_to_file; break; case 'd': - demote = 1; + host_flags |= host_option_demote; + break; + case 'E': + host_flags |= host_option_enter_recovery; break; case 's': checkrain_flags |= checkrain_option_safemode; @@ -202,12 +213,18 @@ int optparse(int argc, char* argv[]) { ext_checkra1n = calloc(1, strlen(optarg) + 1); snprintf(ext_checkra1n, strlen(optarg) + 1, "%s", optarg); break; + case 'R': + host_flags |= host_option_reboot_device; + break; + case 'n': + host_flags |= host_option_exit_recovery; + break; case 'O': - ohio = false; + host_flags |= host_option_no_ohio; break; #ifdef DEV_BUILD case 't': - use_tui = true; + host_flags |= host_option_tui; break; case '1': palerain_flags |= palerain_option_test1; @@ -220,22 +237,18 @@ int optparse(int argc, char* argv[]) { checkrain_flags |= checkrain_option_force_revert; break; case palerain_option_version: - palerain_version = true; + host_flags |= host_option_palerain_version; break; default: usage(1, argv[0]); break; } } - if (palerain_version) { + if (checkrain_option_enabled(host_flags, host_option_palerain_version)) { printf("palera1n version " PALERAIN_VERSION ": " BUILD_DATE "; " BUILD_WHOAMI ":" BUILD_TAG "/" BUILD_STYLE "\n"); return 0; } - if (enable_rootful) { - palerain_flags |= palerain_option_rootful; - } - if (checkrain_option_enabled(checkrain_flags, checkrain_option_force_revert) && checkrain_option_enabled(palerain_flags, palerain_option_setup_rootful)) { LOG(LOG_WARNING, "force revert and setup rootful requested at the same time, behaviour here is undefined"); } @@ -246,6 +259,7 @@ int optparse(int argc, char* argv[]) { LOG(LOG_VERBOSE3, "checkrain_flags: %s", checkrain_flags_cmd); LOG(LOG_VERBOSE3, "palerain_flags: %s", palerain_flags_cmd); LOG(LOG_VERBOSE3, "kpf_flags: %s", kpf_flags_cmd); + LOG(LOG_VERBOSE3, "host_flags: 0x%x", host_flags); if (override_kpf.magic == OVERRIDE_MAGIC) { LOG(LOG_VERBOSE4, "kpf override length %u -> %u", override_kpf.orig_len, checkra1n_kpf_pongo_len); LOG(LOG_VERBOSE4, "kpf override ptr %p -> %p", override_kpf.orig_ptr, **kpf_to_upload); diff --git a/src/pongo_helper.c b/src/pongo_helper.c index b4eeb41..94796e2 100644 --- a/src/pongo_helper.c +++ b/src/pongo_helper.c @@ -12,7 +12,7 @@ #include -bool pongo_full, device_has_booted = 0; +bool device_has_booted = 0; int pongo_thr_running = 0; #define ERR(...) LOG(LOG_VERBOSE, __VA_ARGS__) @@ -46,7 +46,7 @@ void *pongo_usb_callback(void *arg) { issue_pongo_command(handle, kpf_flags_cmd); issue_pongo_command(handle, checkrain_flags_cmd); issue_pongo_command(handle, palerain_flags_cmd); - if (enable_rootful) + if (checkrain_option_enabled(palerain_flags, palerain_option_rootful)) { issue_pongo_command(handle, "rootfs"); } @@ -55,7 +55,7 @@ void *pongo_usb_callback(void *arg) { upload_pongo_file(handle, **overlay_to_upload, binpack_dmg_len); issue_pongo_command(handle, "overlay"); issue_pongo_command(handle, xargs_cmd); - if (pongo_full) goto done; + if (checkrain_option_enabled(host_flags, host_option_pongo_full)) goto done; issue_pongo_command(handle, "bootx"); LOG(LOG_INFO, "Booting Kernel..."); if (dfuhelper_thr_running) {