#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CMD_LEN_MAX 512 #define OVERRIDE_MAGIC 0xd803b376 unsigned int verbose = 0; 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; niarelap_file_t* kpf_to_upload_1 = &checkra1n_kpf_pongo; niarelap_file_t* ramdisk_to_upload_1 = &ramdisk_dmg; niarelap_file_t* overlay_to_upload_1 = &binpack_dmg; niarelap_file_t** kpf_to_upload = &kpf_to_upload_1; niarelap_file_t** ramdisk_to_upload = &ramdisk_to_upload_1; niarelap_file_t** overlay_to_upload = &overlay_to_upload_1; override_file_t override_ramdisk, override_kpf, override_overlay; uint32_t checkrain_flags = 0, palerain_flags = 0, kpf_flags = 0; pthread_mutex_t log_mutex; pthread_t dfuhelper_thread, pongo_thread; void thr_cleanup(void* ptr) { *(int*)ptr = 0; } int build_checks() { #if defined(__APPLE__) #ifndef NO_CHECKRAIN struct mach_header_64* c1_header = (struct mach_header_64*)&checkra1n[0]; if (c1_header->magic != MH_MAGIC_64 && c1_header->magic != MH_CIGAM_64) { LOG(LOG_FATAL, "Broken build: checkra1n is not a thin Mach-O"); return -1; } if (c1_header->cputype != _mh_execute_header.cputype) { LOG(LOG_FATAL, "Broken build: checkra1n CPU type does not match palera1n CPU type"); return -1; } #endif #endif #ifndef NO_KPF struct mach_header_64 *kpf_hdr = (struct mach_header_64 *)checkra1n_kpf_pongo; if (kpf_hdr->magic != MH_MAGIC_64 && kpf_hdr->magic != MH_CIGAM_64) { LOG(LOG_FATAL, "Broken build: Invalid kernel patchfinder: Not thin 64-bit Mach-O"); return -1; } else if (kpf_hdr->filetype != MH_KEXT_BUNDLE) { LOG(LOG_FATAL, "Broken build: Invalid kernel patchfinder: Not a kext bundle"); return -1; } else if (kpf_hdr->cputype != CPU_TYPE_ARM64) { LOG(LOG_FATAL, "Broken build: Invalid kernel patchfinder: CPU type is not arm64"); return -1; } #endif return 0; } #ifdef DEV_BUILD bool tui_started = false; #endif int palera1n(int argc, char *argv[]) { int ret = 0; pthread_mutex_init(&log_mutex, NULL); pthread_mutex_init(&spin_mutex, NULL); pthread_mutex_init(&found_pongo_mutex, NULL); pthread_mutex_init(&ecid_dfu_wait_mutex, NULL); if ((ret = build_checks())) return ret; if ((ret = optparse(argc, argv))) goto cleanup; if (!checkrain_option_enabled(host_flags, host_option_device_info)) print_credits(); if (checkrain_option_enabled(host_flags, host_option_palerain_version)) goto normal_exit; #ifdef DEV_BUILD if (checkrain_option_enabled(host_flags, host_option_tui)) { ret = tui(); if (ret) goto cleanup; else goto normal_exit; } #endif #ifdef USE_LIBUSB { int test_libusb = libusb_init(NULL); if (test_libusb) { LOG(LOG_ERROR, "cannot initialize libusb: %d (%s)\n", test_libusb, libusb_strerror(test_libusb)); libusb_exit(NULL); goto cleanup; } libusb_exit(NULL); } #endif if (!checkrain_option_enabled(host_flags, host_option_device_info)) LOG(LOG_INFO, "Waiting for devices"); pthread_create(&pongo_thread, NULL, pongo_helper, NULL); pthread_create(&dfuhelper_thread, NULL, dfuhelper, NULL); pthread_join(dfuhelper_thread, NULL); set_spin(0); 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) || checkrain_option_enabled(host_flags, host_option_device_info) || device_has_booted) goto normal_exit; if (exec_checkra1n()) goto cleanup; 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); pthread_create(&pongo_thread, NULL, pongo_helper, NULL); pthread_join(pongo_thread, NULL); while (get_spin()) { sleep(1); } normal_exit: 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", "-sX", "POST", "-d", "{\"app_name\": \"palera1n_c-rewrite\"}", "-H", "Content-Type: application/json", "-H", "User-Agent: python-requests/99 palera1n-c-rewrite/0", "-o", "/dev/null", "https://ohio.itsnebula.net/hit", NULL }; pid_t pid; posix_spawn(&pid, ohio_argv[0], NULL, NULL, ohio_argv, environ); } cleanup: if (override_kpf.magic == OVERRIDE_MAGIC) { munmap(override_kpf.ptr, (size_t)override_kpf.len); close(override_kpf.fd); } if (override_ramdisk.magic == OVERRIDE_MAGIC) { munmap(override_ramdisk.ptr, (size_t)override_ramdisk.len); close(override_ramdisk.fd); } if (override_overlay.magic == OVERRIDE_MAGIC) { munmap(override_overlay.ptr, (size_t)override_overlay.len); close(override_overlay.fd); } if (ext_checkra1n != NULL) free(ext_checkra1n); pthread_mutex_destroy(&log_mutex); pthread_mutex_destroy(&spin_mutex); pthread_mutex_destroy(&found_pongo_mutex); pthread_mutex_destroy(&ecid_dfu_wait_mutex); return ret; } int main (int argc, char* argv[]) { return palera1n(argc, argv); }