2026-07-21 20:22:02 -07:00
|
|
|
/*
|
|
|
|
|
* palera1n - https://palera.in
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2026 palera1n team
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
|
|
|
* copies or substantial portions of the Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
|
* SOFTWARE.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2026-06-28 22:32:34 -07:00
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <cstdlib>
|
2026-02-05 00:42:57 -08:00
|
|
|
#include <iostream>
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstdlib>
|
2026-06-28 22:32:34 -07:00
|
|
|
#include <cstring>
|
2026-07-21 20:22:02 -07:00
|
|
|
#include <inttypes.h> // PRIx64
|
2026-02-05 00:42:57 -08:00
|
|
|
|
|
|
|
|
#ifdef WITH_GUI
|
|
|
|
|
# include <wx/wx.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2026-07-21 20:22:02 -07:00
|
|
|
#include "exploit.h"
|
2026-07-06 04:05:57 -07:00
|
|
|
#ifdef WITH_TUI
|
|
|
|
|
# include "tui/Tui.hpp"
|
|
|
|
|
#endif
|
2026-07-21 20:22:02 -07:00
|
|
|
#if WITH_CIDERRAIN
|
|
|
|
|
# include <ciderra1n/log.h>
|
|
|
|
|
extern "C" {
|
|
|
|
|
# include <ciderra1n/ra1n.h>
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
# include <openra1n/utils.h>
|
|
|
|
|
#endif
|
2026-06-28 16:37:05 -07:00
|
|
|
#include "globals.h"
|
2026-06-25 21:40:01 -07:00
|
|
|
#include "paleinfo.h"
|
2026-07-21 20:22:02 -07:00
|
|
|
#include "pongo_helper.h"
|
2026-02-05 00:42:57 -08:00
|
|
|
|
2026-07-21 21:59:36 -07:00
|
|
|
// MARK: print_credits
|
|
|
|
|
|
2026-02-05 00:42:57 -08:00
|
|
|
void print_credits() {
|
|
|
|
|
printf(
|
2026-06-26 17:22:45 -07:00
|
|
|
"::\n"
|
2026-07-21 22:02:32 -07:00
|
|
|
":: Palera1n " PALERAIN_VERSION "\n"
|
2026-06-26 17:22:45 -07:00
|
|
|
"::\n"
|
2026-07-21 20:22:02 -07:00
|
|
|
":: Copyright (C) 2026 palera1n team\n"
|
2026-06-26 17:22:45 -07:00
|
|
|
"::\n"
|
2026-06-27 19:48:40 -07:00
|
|
|
":: ======== Made by =======>\n"
|
2026-06-26 17:22:45 -07:00
|
|
|
":: Made by: asdfugil, kok3shidoll, claration, mineek\n"
|
2026-07-27 16:16:21 -07:00
|
|
|
":: sarah, staturnz\n"
|
2026-06-27 19:48:40 -07:00
|
|
|
":: ======== Thanks to =======>\n"
|
2026-07-06 04:05:57 -07:00
|
|
|
":: Thanks to: itsnebulalol, llsc12, lrdsnow, dedbeddedbed\n"
|
|
|
|
|
":: kirb, ehilwyma, opa334, 0x7ff, alfiecg25, sneko, sbingner\n"
|
|
|
|
|
":: nikias, tihmstar\n"
|
2026-06-26 17:22:45 -07:00
|
|
|
":: Checkra1n (Siguza, axi0mx, littlelailo et al.)\n"
|
|
|
|
|
":: Procursus (Hayden Seay, Cameron Katri, Keto et al.)\n"
|
2026-06-27 19:48:40 -07:00
|
|
|
":: ==========================>\n\n"
|
2026-02-05 00:42:57 -08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-21 21:59:36 -07:00
|
|
|
// MARK: print_usage
|
|
|
|
|
|
2026-02-05 00:42:57 -08:00
|
|
|
void print_usage(char* argv) {
|
|
|
|
|
printf(
|
|
|
|
|
"Usage: %s [OPTIONS]\n\n"
|
|
|
|
|
" -h, --help Print usage information\n"
|
|
|
|
|
" -v, --version Print version\n\n"
|
2026-06-28 16:37:05 -07:00
|
|
|
"Options:\n\n"
|
2026-07-25 03:36:42 -07:00
|
|
|
" --cli Use command line interface\n"
|
2026-02-05 00:42:57 -08:00
|
|
|
#ifdef WITH_GUI
|
2026-07-25 03:36:42 -07:00
|
|
|
" --gui Use graphical user interface\n"
|
2026-02-05 00:42:57 -08:00
|
|
|
#endif
|
2026-06-28 16:37:05 -07:00
|
|
|
#ifdef WITH_TUI
|
2026-07-25 03:36:42 -07:00
|
|
|
" --tui Use terminal user interface\n"
|
2026-06-28 16:37:05 -07:00
|
|
|
#endif
|
2026-07-25 03:36:42 -07:00
|
|
|
" --dark-blockchain Enable dark blockchain\n"
|
|
|
|
|
" --force-revert Force environment reversion\n"
|
|
|
|
|
" --force-enable-ssv Force SSV detection to result in YES\n"
|
2026-07-25 04:14:39 -07:00
|
|
|
// TODO: add --demote
|
2026-07-25 03:36:42 -07:00
|
|
|
" -l, --rootless Enable rootless mode (standard)\n"
|
|
|
|
|
" -f, --rootful Boots fakefs\n"
|
|
|
|
|
" -c, --setup-fakefs Setup fake filesystem\n"
|
|
|
|
|
" -B, --setup-partial-fakefs Setup partial fake filesystem\n"
|
|
|
|
|
" -s, --safe-mode Enable safe mode\n"
|
|
|
|
|
" -T, --telnetd Enable TELNET daemon on port 46 (insecure)\n"
|
|
|
|
|
" -V, --verbose-boot Enable verbose booting\n"
|
|
|
|
|
" -p, --early-exit Exit after uploading Pongo\n"
|
2026-08-01 03:18:04 -07:00
|
|
|
" -P, --late-exit Exit after uploading existing images to Pongo\n"
|
2026-06-28 16:37:05 -07:00
|
|
|
" -e, --extra-bootargs <BOOTARGS> Set extra bootargs\n"
|
|
|
|
|
" -k, --override-pongo <FILE PATH> Override Pongo image\n"
|
|
|
|
|
" -K, --override-kpf <FILE PATH> Override kernel patchfinder\n"
|
|
|
|
|
" -o, --override-overlay <FILE PATH> Override overlay\n"
|
|
|
|
|
" -r, --override-ramdisk <FILE PATH> Override ramdisk\n"
|
2026-07-21 20:22:02 -07:00
|
|
|
" -d, --debug-logging Enable debug logging\n"
|
2026-07-25 03:36:42 -07:00
|
|
|
" -n, --no-colors Disable colors on the command line\n"
|
2026-07-22 18:43:58 -07:00
|
|
|
#if defined(WITH_GUI) || defined(WITH_TUI)
|
2026-07-25 03:36:42 -07:00
|
|
|
" -q, --quick Enable Quick Mode\n"
|
2026-07-22 18:43:58 -07:00
|
|
|
#endif
|
|
|
|
|
"\nEnvironment Variables:\n\n"
|
2026-07-21 21:59:36 -07:00
|
|
|
#if WITH_CIDERRAIN
|
2026-07-25 03:36:42 -07:00
|
|
|
" RA1N_ABORT_TIMEOUT=1000000 Custom timeout value for the exploit abort timer.\n"
|
2026-07-21 21:59:36 -07:00
|
|
|
#endif
|
2026-07-25 03:36:42 -07:00
|
|
|
" RA1N_CLI=1 Use command line interface\n"
|
2026-07-21 21:59:36 -07:00
|
|
|
#ifdef WITH_GUI
|
2026-07-25 03:36:42 -07:00
|
|
|
" RA1N_GUI=1 Use graphical user interface\n"
|
2026-07-21 21:59:36 -07:00
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_TUI
|
2026-07-25 03:36:42 -07:00
|
|
|
" RA1N_TUI=1 Use terminal user interface\n"
|
2026-07-21 21:59:36 -07:00
|
|
|
#endif
|
2026-07-25 03:36:42 -07:00
|
|
|
" RA1N_DARK_BLOCKCHAIN=1 Enable dark blockchain\n"
|
|
|
|
|
" RA1N_FORCE_REVERT=1 Force environment reversion\n"
|
|
|
|
|
" RA1N_FORCE_ENABLE_SSV=1 Force SSV detection to result in YES\n"
|
2026-07-25 04:14:39 -07:00
|
|
|
// TODO: add --demote
|
2026-07-25 03:36:42 -07:00
|
|
|
" RA1N_ROOTLESS=1 Enable rootless mode (standard)\n"
|
|
|
|
|
" RA1N_ROOTFUL=1 Boots fakefs\n"
|
|
|
|
|
" RA1N_SETUP_FAKEFS=1 Setup fake filesystem\n"
|
|
|
|
|
" RA1N_SETUP_PARTIAL_FAKEFS=1 Setup partial fake filesystem\n"
|
|
|
|
|
" RA1N_SAFE_MODE=1 Enable safe mode\n"
|
|
|
|
|
" RA1N_TELNETD=1 Enable TELNET daemon on port 46 (insecure)\n"
|
|
|
|
|
" RA1N_VERBOSE_BOOT=1 Enable verbose booting\n"
|
|
|
|
|
" RA1N_EARLY_EXIT=1 Exit after uploading Pongo\n"
|
2026-08-01 03:18:04 -07:00
|
|
|
" RA1N_LATE_EXIT=1 Exit after uploading existing images to Pongo\n"
|
2026-07-21 22:26:26 -07:00
|
|
|
" RA1N_EXTRA_BOOTARGS=<FILE PATH> Set extra bootargs\n"
|
|
|
|
|
" RA1N_OVERRIDE_PONGO=<FILE PATH> Override Pongo image\n"
|
|
|
|
|
" RA1N_OVERRIDE_KPF=<FILE PATH> Override kernel patchfinder\n"
|
|
|
|
|
" RA1N_OVERRIDE_OVERLAY=<FILE PATH> Override overlay\n"
|
|
|
|
|
" RA1N_OVERRIDE_RAMDISK=<FILE PATH> Override ramdisk\n"
|
|
|
|
|
" RA1N_DEBUG_LOGGING=1 Enable debug logging\n"
|
2026-07-25 03:36:42 -07:00
|
|
|
" RA1N_NO_COLORS=1 Disable colors on the command line\n"
|
2026-07-22 18:43:58 -07:00
|
|
|
#if defined(WITH_GUI) || defined(WITH_TUI)
|
2026-07-25 03:36:42 -07:00
|
|
|
" RA1N_QUICK=1 Enable Quick Mode\n"
|
2026-07-22 18:43:58 -07:00
|
|
|
#endif
|
2026-02-05 00:42:57 -08:00
|
|
|
, argv
|
|
|
|
|
);
|
2026-07-02 15:22:32 -07:00
|
|
|
|
|
|
|
|
printf(
|
|
|
|
|
"\n"
|
|
|
|
|
"Many things included in this program are made and developed by the Checkra1n team.\n"
|
|
|
|
|
"Please do NOT contact the Checkra1n team for Palera1n, they are not responsible for this program.\n"
|
|
|
|
|
"The original Checkra1n payloads are from: https://checkra.in/1337\n"
|
|
|
|
|
);
|
2026-02-05 00:42:57 -08:00
|
|
|
}
|
|
|
|
|
|
2026-07-21 21:59:36 -07:00
|
|
|
// MARK: parse_arguments
|
|
|
|
|
|
|
|
|
|
static int get_env_binary(const char *env_name) {
|
|
|
|
|
const char *val = getenv(env_name);
|
|
|
|
|
if (!val) return -1;
|
|
|
|
|
if (strcmp(val, "1") == 0) return 1;
|
|
|
|
|
if (strcmp(val, "0") == 0) return 0;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-05 00:42:57 -08:00
|
|
|
void parse_arguments(int argc, char* argv[]) {
|
|
|
|
|
int options;
|
|
|
|
|
int option_index = 0;
|
|
|
|
|
|
|
|
|
|
static struct option long_options[] = {
|
|
|
|
|
{"help", no_argument, NULL, 'h'},
|
|
|
|
|
{"version", no_argument, NULL, 'v'},
|
|
|
|
|
{"cli", no_argument, NULL, 1},
|
|
|
|
|
#ifdef WITH_GUI
|
2026-06-28 16:37:05 -07:00
|
|
|
{"gui", no_argument, NULL, 2},
|
2026-02-05 00:42:57 -08:00
|
|
|
#endif
|
2026-07-06 04:55:56 -07:00
|
|
|
#ifdef WITH_TUI
|
2026-06-28 16:37:05 -07:00
|
|
|
{"tui", no_argument, NULL, 3},
|
|
|
|
|
#endif
|
|
|
|
|
{"dark-blockchain", no_argument, NULL, 4},
|
|
|
|
|
{"force-revert", no_argument, NULL, 5},
|
2026-07-21 20:22:02 -07:00
|
|
|
{"force-enable-ssv", no_argument, NULL, 6},
|
2026-07-25 04:14:39 -07:00
|
|
|
// TODO: add --demote
|
2026-02-05 00:42:57 -08:00
|
|
|
{"rootless", no_argument, NULL, 'l'},
|
|
|
|
|
{"rootful", no_argument, NULL, 'f'},
|
|
|
|
|
{"setup-fakefs", no_argument, NULL, 'c'},
|
|
|
|
|
{"setup-partial-fakefs", no_argument, NULL, 'B'},
|
|
|
|
|
{"safe-mode", no_argument, NULL, 's'},
|
|
|
|
|
{"telnetd", no_argument, NULL, 'T'},
|
|
|
|
|
{"verbose-boot", no_argument, NULL, 'V'},
|
2026-06-28 16:37:05 -07:00
|
|
|
{"early-exit", no_argument, NULL, 'p'},
|
2026-08-01 03:18:04 -07:00
|
|
|
{"late-exit", no_argument, NULL, 'P'},
|
2026-06-28 16:37:05 -07:00
|
|
|
{"extra-bootargs", required_argument, NULL, 'e'},
|
|
|
|
|
{"override-pongo", required_argument, NULL, 'k'},
|
|
|
|
|
{"override-kpf", required_argument, NULL, 'K'},
|
|
|
|
|
{"override-overlay", required_argument, NULL, 'o'},
|
|
|
|
|
{"override-ramdisk", required_argument, NULL, 'r'},
|
2026-07-21 20:22:02 -07:00
|
|
|
{"debug-logging", no_argument, NULL, 'd'},
|
2026-06-28 16:37:05 -07:00
|
|
|
{"no-colors", no_argument, NULL, 'n'},
|
2026-07-22 18:43:58 -07:00
|
|
|
#if defined(WITH_GUI) || defined(WITH_TUI)
|
2026-06-28 16:37:05 -07:00
|
|
|
{"quick", no_argument, NULL, 'q'},
|
2026-07-22 18:43:58 -07:00
|
|
|
#endif
|
2026-02-05 00:42:57 -08:00
|
|
|
{NULL, 0, NULL, 0}
|
|
|
|
|
};
|
|
|
|
|
|
2026-07-06 04:50:40 -07:00
|
|
|
#ifndef _WIN32
|
2026-02-05 00:42:57 -08:00
|
|
|
if (isatty(STDIN_FILENO) && getenv("LLVM_PROFILE_FILE") == nullptr) {
|
2026-06-28 16:37:05 -07:00
|
|
|
#ifdef WITH_TUI
|
|
|
|
|
palerain_flags |= palerain_option_tui;
|
|
|
|
|
#else
|
2026-02-05 00:42:57 -08:00
|
|
|
palerain_flags |= palerain_option_cli;
|
2026-06-28 16:37:05 -07:00
|
|
|
#endif
|
2026-02-05 00:42:57 -08:00
|
|
|
} else {
|
2026-07-06 04:50:40 -07:00
|
|
|
#ifdef WITH_GUI
|
2026-02-05 00:42:57 -08:00
|
|
|
palerain_flags |= palerain_option_gui;
|
2026-06-28 17:14:49 -07:00
|
|
|
// xcode doesn't know how to display colors
|
|
|
|
|
palerain_flags |= palerain_option_no_colors;
|
2026-07-06 04:50:40 -07:00
|
|
|
#else
|
|
|
|
|
palerain_flags |= palerain_option_cli;
|
|
|
|
|
#endif
|
2026-02-05 00:42:57 -08:00
|
|
|
}
|
|
|
|
|
#else
|
2026-07-06 04:50:40 -07:00
|
|
|
# ifdef WITH_GUI
|
|
|
|
|
palerain_flags |= palerain_option_gui;
|
|
|
|
|
# else
|
2026-02-05 00:42:57 -08:00
|
|
|
palerain_flags |= palerain_option_cli;
|
2026-07-06 04:50:40 -07:00
|
|
|
# endif
|
2026-02-05 00:42:57 -08:00
|
|
|
#endif
|
|
|
|
|
|
2026-07-21 21:59:36 -07:00
|
|
|
// MARK: Standard
|
|
|
|
|
|
2026-08-01 03:18:04 -07:00
|
|
|
while ((options = getopt_long(argc, argv, "hvlfcBsTVpPe:k:K:o:r:dnq", long_options, &option_index)) != -1) {
|
2026-02-05 00:42:57 -08:00
|
|
|
switch (options) {
|
|
|
|
|
case 'h': // --help
|
|
|
|
|
print_usage(argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
case 'v': // --version
|
2026-07-21 20:22:02 -07:00
|
|
|
#if WITH_CIDERRAIN
|
2026-07-21 21:59:36 -07:00
|
|
|
printf("Palera1n " PALERAIN_VERSION " [USB: %s (libcidera1n %s)]\n",
|
2026-07-21 20:22:02 -07:00
|
|
|
ra1n_show_usb_backend(),
|
|
|
|
|
ra1n_show_build_version()
|
|
|
|
|
);
|
|
|
|
|
#else
|
2026-07-21 21:59:36 -07:00
|
|
|
printf("Palera1n " PALERAIN_VERSION " [USB: %s (libopenra1n)]\n",
|
2026-07-02 15:22:32 -07:00
|
|
|
#ifdef __APPLE__
|
|
|
|
|
"IOKit"
|
|
|
|
|
#else
|
|
|
|
|
"libusb"
|
|
|
|
|
#endif
|
|
|
|
|
);
|
2026-07-21 20:22:02 -07:00
|
|
|
#endif
|
2026-07-02 15:22:32 -07:00
|
|
|
printf("%s (%s)\n", GIT_HASH, GIT_BRANCH);
|
|
|
|
|
printf("Git: %s\n", GIT_URL);
|
|
|
|
|
printf("Compiled on %s at %s\n", __DATE__, __TIME__);
|
2026-02-05 00:42:57 -08:00
|
|
|
exit(0);
|
|
|
|
|
case 1: // --cli
|
|
|
|
|
palerain_flags &= ~palerain_option_tui;
|
|
|
|
|
palerain_flags &= ~palerain_option_gui;
|
|
|
|
|
palerain_flags |= palerain_option_cli;
|
|
|
|
|
break;
|
|
|
|
|
#ifdef WITH_GUI
|
2026-06-28 16:37:05 -07:00
|
|
|
case 2: // --gui
|
2026-02-05 00:42:57 -08:00
|
|
|
palerain_flags &= ~palerain_option_cli;
|
|
|
|
|
palerain_flags &= ~palerain_option_tui;
|
|
|
|
|
palerain_flags |= palerain_option_gui;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
2026-06-28 16:37:05 -07:00
|
|
|
#ifdef WITH_TUI
|
|
|
|
|
case 3: // --tui
|
|
|
|
|
palerain_flags &= ~palerain_option_cli;
|
|
|
|
|
palerain_flags &= ~palerain_option_gui;
|
|
|
|
|
palerain_flags |= palerain_option_tui;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
case 4: // --dark-blockchain
|
|
|
|
|
palerain_flags |= palerain_option_flower_chain;
|
|
|
|
|
break;
|
|
|
|
|
case 5: // --force-revert
|
2026-02-05 00:42:57 -08:00
|
|
|
palerain_flags |= palerain_option_force_revert;
|
|
|
|
|
break;
|
2026-07-21 20:22:02 -07:00
|
|
|
case 6: // --force-enable-ssv
|
|
|
|
|
palerain_flags |= palerain_option_ssv;
|
|
|
|
|
break;
|
2026-02-05 00:42:57 -08:00
|
|
|
case 'l': // --rootless
|
|
|
|
|
palerain_flags |= palerain_option_rootless;
|
|
|
|
|
break;
|
|
|
|
|
case 'f': // --rootful
|
|
|
|
|
palerain_flags |= palerain_option_rootful;
|
|
|
|
|
break;
|
|
|
|
|
case 'c': // --setup-fakefs
|
|
|
|
|
palerain_flags |= palerain_option_setup_rootful;
|
|
|
|
|
break;
|
|
|
|
|
case 'B': // --setup-partial-fakefs
|
|
|
|
|
palerain_flags |= palerain_option_setup_partial_root;
|
|
|
|
|
break;
|
|
|
|
|
case 's': // --safe-mode
|
|
|
|
|
palerain_flags |= palerain_option_safemode;
|
|
|
|
|
break;
|
|
|
|
|
case 'T': // --telnetd
|
|
|
|
|
palerain_flags |= palerain_option_telnetd;
|
|
|
|
|
break;
|
|
|
|
|
case 'V': // --verbose-boot
|
|
|
|
|
palerain_flags |= palerain_option_verbose_boot;
|
|
|
|
|
break;
|
2026-06-28 16:37:05 -07:00
|
|
|
case 'p': // --early-exit
|
|
|
|
|
palerain_flags |= palerain_option_pongo_exit;
|
|
|
|
|
break;
|
2026-08-01 03:18:04 -07:00
|
|
|
case 'P': // --late-exit
|
|
|
|
|
palerain_flags |= palerain_option_pongo_full;
|
|
|
|
|
break;
|
2026-06-28 16:37:05 -07:00
|
|
|
case 'e': // --extra-bootargs
|
|
|
|
|
if (strlen(optarg) > (sizeof(boot_args) - 0x20)) {
|
2026-07-21 20:22:02 -07:00
|
|
|
LOG_ERROR("Boot arguments too long!");
|
2026-06-28 16:37:05 -07:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-07-25 04:14:39 -07:00
|
|
|
|
|
|
|
|
// TODO: do some more checks on bootargs, like if it already
|
|
|
|
|
// contains "palerain_flags" or things like "wdt" on rootful
|
|
|
|
|
// using "-v" is also not supported
|
|
|
|
|
|
|
|
|
|
// TODO: maybe automatically "wdt=-1" when rootful, and display
|
|
|
|
|
// it through the various interfaces
|
2026-06-28 16:37:05 -07:00
|
|
|
snprintf(boot_args, sizeof(boot_args), "%s", optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'k': // --override-pongo
|
|
|
|
|
if (!override_payload_from_file(optarg, &g_payload_pongo)) {
|
2026-07-21 20:22:02 -07:00
|
|
|
LOG_ERROR("Failed to load pongo payload, is the path correct?");
|
2026-06-28 16:37:05 -07:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-08-02 20:34:22 -07:00
|
|
|
if (!check_payload_validity(&g_payload_pongo, true)) {
|
|
|
|
|
LOG_ERROR("Pongo payload is invalid or too large! %zu bytes", g_payload_pongo.data_len);
|
2026-06-30 22:44:34 -07:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-06-28 16:37:05 -07:00
|
|
|
LOG("Overriding pongo payload with %s", optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'K': // --override-kpf
|
|
|
|
|
if (!override_payload_from_file(optarg, &g_payload_kpf)) {
|
2026-07-21 20:22:02 -07:00
|
|
|
LOG_ERROR("Failed to load kpf payload, is the path correct?");
|
2026-06-28 16:37:05 -07:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-08-02 20:34:22 -07:00
|
|
|
if (!check_payload_validity(&g_payload_kpf, false)) {
|
|
|
|
|
LOG_ERROR("KPF payload is invalid! Is it a valid Mach-O binary?");
|
2026-06-30 22:44:34 -07:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-06-28 16:37:05 -07:00
|
|
|
LOG("Overriding kpf payload with %s", optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'o': // --override-overlay
|
|
|
|
|
if (!override_payload_from_file(optarg, &g_payload_overlay)) {
|
2026-07-21 20:22:02 -07:00
|
|
|
LOG_ERROR("Failed to load overlay payload, is the path correct?");
|
2026-06-28 16:37:05 -07:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
LOG("Overriding overlay payload with %s", optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'r': // --override-ramdisk
|
|
|
|
|
if (!override_payload_from_file(optarg, &g_payload_ramdisk)) {
|
2026-07-21 20:22:02 -07:00
|
|
|
LOG_ERROR("Failed to load ramdisk payload, is the path correct?");
|
2026-06-28 16:37:05 -07:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
LOG("Overriding ramdisk payload with %s", optarg);
|
|
|
|
|
break;
|
2026-07-21 20:22:02 -07:00
|
|
|
case 'd': // --debug-logging
|
|
|
|
|
if (gDebugLevel < 5) gDebugLevel++;
|
|
|
|
|
break;
|
2026-06-28 16:37:05 -07:00
|
|
|
case 'n': // --no-colors
|
|
|
|
|
palerain_flags |= palerain_option_no_colors;
|
|
|
|
|
break;
|
2026-07-22 18:43:58 -07:00
|
|
|
#if defined(WITH_GUI) || defined(WITH_TUI)
|
2026-06-28 16:37:05 -07:00
|
|
|
case 'q': // --quick
|
|
|
|
|
palerain_flags |= palerain_option_quick;
|
|
|
|
|
break;
|
2026-07-22 18:43:58 -07:00
|
|
|
#endif
|
2026-02-05 00:42:57 -08:00
|
|
|
case '?':
|
2026-06-27 19:48:40 -07:00
|
|
|
LOG_ERROR("Unknown option\n");
|
2026-02-05 00:42:57 -08:00
|
|
|
print_usage(argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-21 21:59:36 -07:00
|
|
|
// MARK: Environment vars
|
|
|
|
|
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_CLI") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags &= ~palerain_option_tui;
|
|
|
|
|
palerain_flags &= ~palerain_option_gui;
|
|
|
|
|
palerain_flags |= palerain_option_cli;
|
|
|
|
|
}
|
|
|
|
|
#ifdef WITH_GUI
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_GUI") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags &= ~palerain_option_cli;
|
|
|
|
|
palerain_flags &= ~palerain_option_tui;
|
|
|
|
|
palerain_flags |= palerain_option_gui;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_TUI
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_TUI") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags &= ~palerain_option_cli;
|
|
|
|
|
palerain_flags &= ~palerain_option_gui;
|
|
|
|
|
palerain_flags |= palerain_option_tui;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_DARK_BLOCKCHAIN") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_flower_chain;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_FORCE_REVERT") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_force_revert;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_FORCE_ENABLE_SSV") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_ssv;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_ROOTLESS") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_rootless;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_ROOTFUL") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_rootful;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_SETUP_FAKEFS") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_setup_rootful;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_SETUP_PARTIAL_FAKEFS") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_setup_partial_root;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_SAFE_MODE") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_safemode;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_TELNETD") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_telnetd;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_VERBOSE_BOOT") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_verbose_boot;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_EARLY_EXIT") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_pongo_exit;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_LATE_EXIT") == 1) {
|
2026-08-01 03:18:04 -07:00
|
|
|
palerain_flags |= palerain_option_pongo_full;
|
|
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_NO_COLORS") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_no_colors;
|
|
|
|
|
}
|
2026-07-22 18:43:58 -07:00
|
|
|
#if defined(WITH_GUI) || defined(WITH_TUI)
|
2026-08-01 03:47:54 -07:00
|
|
|
if (get_env_binary("RA1N_QUICK") == 1) {
|
2026-07-21 21:59:36 -07:00
|
|
|
palerain_flags |= palerain_option_quick;
|
|
|
|
|
}
|
2026-07-22 18:43:58 -07:00
|
|
|
#endif
|
2026-07-21 21:59:36 -07:00
|
|
|
|
|
|
|
|
const char *env_debug = getenv("RA1N_DEBUG_LOGGING");
|
|
|
|
|
if (env_debug) {
|
|
|
|
|
int lvl = atoi(env_debug);
|
|
|
|
|
if (lvl > 0) {
|
|
|
|
|
gDebugLevel = (lvl > 5) ? 5 : lvl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-01 03:47:54 -07:00
|
|
|
const char *env_bootargs = getenv("RA1N_EXTRA_BOOTARGS");
|
|
|
|
|
if (env_bootargs) {
|
|
|
|
|
if (strlen(env_bootargs) > (sizeof(boot_args) - 0x20)) {
|
|
|
|
|
LOG_ERROR("Boot arguments too long!");
|
|
|
|
|
exit(1);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
snprintf(boot_args, sizeof(boot_args), "%s", env_bootargs);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
|
|
|
|
|
2026-08-01 03:47:54 -07:00
|
|
|
const char *env_pongo = getenv("RA1N_OVERRIDE_PONGO");
|
|
|
|
|
if (env_pongo) {
|
|
|
|
|
if (!override_payload_from_file(env_pongo, &g_payload_pongo)) {
|
|
|
|
|
LOG_ERROR("Failed to load pongo payload from env, is the path correct?");
|
|
|
|
|
exit(1);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
2026-08-02 20:34:22 -07:00
|
|
|
if (!check_payload_validity(&g_payload_pongo, true)) {
|
|
|
|
|
LOG_ERROR("Pongo payload is invalid or too large! %zu bytes", g_payload_pongo.data_len);
|
2026-08-01 03:47:54 -07:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
LOG("Overriding pongo payload with %s (from env)", env_pongo);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
|
|
|
|
|
2026-08-01 03:47:54 -07:00
|
|
|
const char *env_kpf = getenv("RA1N_OVERRIDE_KPF");
|
|
|
|
|
if (env_kpf) {
|
|
|
|
|
if (!override_payload_from_file(env_kpf, &g_payload_kpf)) {
|
|
|
|
|
LOG_ERROR("Failed to load kpf payload from env, is the path correct?");
|
|
|
|
|
exit(1);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
2026-08-02 20:34:22 -07:00
|
|
|
if (!check_payload_validity(&g_payload_kpf, false)) {
|
2026-08-01 03:47:54 -07:00
|
|
|
LOG_ERROR("Invalid kpf payload from env, is it macho?");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
LOG("Overriding kpf payload with %s (from env)", env_kpf);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
|
|
|
|
|
2026-08-01 03:47:54 -07:00
|
|
|
const char *env_overlay = getenv("RA1N_OVERRIDE_OVERLAY");
|
|
|
|
|
if (env_overlay) {
|
|
|
|
|
if (!override_payload_from_file(env_overlay, &g_payload_overlay)) {
|
|
|
|
|
LOG_ERROR("Failed to load overlay payload from env, is the path correct?");
|
|
|
|
|
exit(1);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
LOG("Overriding overlay payload with %s (from env)", env_overlay);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
|
|
|
|
|
2026-08-01 03:47:54 -07:00
|
|
|
const char *env_ramdisk = getenv("RA1N_OVERRIDE_RAMDISK");
|
|
|
|
|
if (env_ramdisk) {
|
|
|
|
|
if (!override_payload_from_file(env_ramdisk, &g_payload_ramdisk)) {
|
|
|
|
|
LOG_ERROR("Failed to load ramdisk payload from env, is the path correct?");
|
|
|
|
|
exit(1);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
2026-08-01 03:47:54 -07:00
|
|
|
LOG("Overriding ramdisk payload with %s (from env)", env_ramdisk);
|
2026-07-21 21:59:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: Flag checks
|
|
|
|
|
|
2026-08-01 03:18:04 -07:00
|
|
|
if ((palerain_flags & palerain_option_pongo_exit) &&
|
|
|
|
|
(palerain_flags & palerain_option_pongo_full))
|
2026-06-28 22:55:46 -07:00
|
|
|
{
|
2026-08-01 03:18:04 -07:00
|
|
|
LOG_ERROR("You cannot specify both early-exit and late-exit modes.\n");
|
|
|
|
|
print_usage(argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pongo exit modes are standalone and cannot be combined with root modes
|
|
|
|
|
if (palerain_flags & (palerain_option_pongo_exit | palerain_option_pongo_full))
|
|
|
|
|
{
|
|
|
|
|
if (palerain_flags & (palerain_option_rootful | palerain_option_rootless))
|
2026-06-28 22:55:46 -07:00
|
|
|
{
|
2026-08-01 03:18:04 -07:00
|
|
|
LOG_ERROR("Pongo exit modes cannot be used with [-l, --rootless] or [-f, --rootful].\n");
|
2026-02-05 00:42:57 -08:00
|
|
|
print_usage(argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-07-06 04:13:54 -07:00
|
|
|
|
2026-08-01 03:18:04 -07:00
|
|
|
goto skip_root_types;
|
|
|
|
|
}
|
2026-07-09 15:44:35 -07:00
|
|
|
|
2026-08-01 03:18:04 -07:00
|
|
|
// Normal root checks
|
|
|
|
|
if (!(palerain_flags & palerain_option_gui) &&
|
|
|
|
|
!(palerain_flags & palerain_option_tui) &&
|
|
|
|
|
!(palerain_flags & palerain_option_rootful) &&
|
|
|
|
|
!(palerain_flags & palerain_option_rootless))
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR("You must specify either [-l, --rootless] or [-f, --rootful].\n");
|
|
|
|
|
print_usage(argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-07-06 04:13:54 -07:00
|
|
|
|
2026-08-01 03:18:04 -07:00
|
|
|
if ((palerain_flags & palerain_option_rootful) &&
|
|
|
|
|
(palerain_flags & palerain_option_rootless))
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR("You cannot specify both [-l, --rootless] and [-f, --rootful].\n");
|
|
|
|
|
print_usage(argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-07-06 04:13:54 -07:00
|
|
|
|
2026-08-01 03:18:04 -07:00
|
|
|
skip_root_types:
|
|
|
|
|
|
|
|
|
|
if ((palerain_flags & palerain_option_setup_rootful) &&
|
|
|
|
|
(palerain_flags & palerain_option_setup_partial_root))
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR("You cannot specify both [-c, --setup-fakefs] and [-B, --setup-partial-fakefs].\n");
|
|
|
|
|
print_usage(argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((palerain_flags & palerain_option_setup_rootful) ||
|
|
|
|
|
(palerain_flags & palerain_option_setup_partial_root))
|
|
|
|
|
{
|
|
|
|
|
if (!(palerain_flags & palerain_option_rootful))
|
2026-07-06 04:13:54 -07:00
|
|
|
{
|
2026-07-09 15:44:35 -07:00
|
|
|
LOG_ERROR("[-c, --setup-fakefs] or [-B, --setup-partial-fakefs] require [-f, --rootful].\n");
|
2026-07-06 04:13:54 -07:00
|
|
|
print_usage(argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2026-02-05 00:42:57 -08:00
|
|
|
}
|
2026-07-21 20:22:02 -07:00
|
|
|
|
|
|
|
|
// controls logging settings in our checkm8 libraries
|
2026-07-22 21:02:34 -07:00
|
|
|
if (palerain_flags & palerain_option_no_colors) gColoredLogs = false;
|
2026-07-21 20:22:02 -07:00
|
|
|
if (palerain_flags & palerain_option_tui) gSilentLogs = true;
|
2026-02-05 00:42:57 -08:00
|
|
|
}
|
|
|
|
|
|
2026-07-21 21:59:36 -07:00
|
|
|
// MARK: main
|
|
|
|
|
|
2026-02-05 00:42:57 -08:00
|
|
|
int main(int argc, char* argv[], char* envp[]) {
|
|
|
|
|
print_credits();
|
|
|
|
|
parse_arguments(argc, argv);
|
2026-07-21 20:22:02 -07:00
|
|
|
|
|
|
|
|
LOG("Welcome to palera1n!");
|
|
|
|
|
LOG("Reminder, this jailbreak IS designed for iOS 15+");
|
|
|
|
|
LOG_DEBUG("palera1n_flags: 0x%" PRIx64, palerain_flags);
|
2026-02-05 00:42:57 -08:00
|
|
|
|
2026-07-02 15:22:32 -07:00
|
|
|
// communicating with libusb on linux needs root
|
|
|
|
|
#ifdef __linux__
|
|
|
|
|
if (geteuid() != 0) {
|
2026-07-21 20:22:02 -07:00
|
|
|
LOG_ERROR("You are not running as root, this may cause issues when exploiting...");
|
2026-07-02 15:22:32 -07:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2026-02-05 00:42:57 -08:00
|
|
|
#ifdef WITH_GUI
|
|
|
|
|
if (palerain_flags & palerain_option_gui) {
|
|
|
|
|
wxEntryStart(argc, argv);
|
|
|
|
|
wxTheApp->CallOnInit();
|
|
|
|
|
wxTheApp->OnRun();
|
|
|
|
|
wxTheApp->OnExit();
|
|
|
|
|
wxEntryCleanup();
|
|
|
|
|
return 0;
|
2026-07-06 04:29:53 -07:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_TUI
|
|
|
|
|
if (palerain_flags & palerain_option_tui) {
|
2026-07-06 05:20:09 -07:00
|
|
|
// if terminfo is not set, set one
|
|
|
|
|
if (getenv("TERMINFO") == nullptr) {
|
|
|
|
|
// (at least on my environment) the terminal would fail to run
|
|
|
|
|
// with sudo unless this is set, so if its not set correctly
|
|
|
|
|
// just use a standard path on lunix
|
|
|
|
|
setenv("TERMINFO", "/usr/share/terminfo", 1);
|
|
|
|
|
}
|
2026-07-06 04:05:57 -07:00
|
|
|
ui_run();
|
|
|
|
|
return 0;
|
2026-02-05 00:42:57 -08:00
|
|
|
}
|
2026-07-06 04:29:53 -07:00
|
|
|
#endif
|
|
|
|
|
|
2026-07-21 20:22:02 -07:00
|
|
|
int stage;
|
|
|
|
|
bool ret = exploit(&stage);
|
|
|
|
|
LOG("Thank you for using palera1n!");
|
|
|
|
|
return ret;
|
2026-02-05 00:42:57 -08:00
|
|
|
}
|