Files
palera1n/src/main.cpp
T

381 lines
14 KiB
C++
Raw Normal View History

#include <unistd.h>
#include <cstdlib>
2026-02-05 00:42:57 -08:00
#include <iostream>
#include <getopt.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
2026-02-05 00:42:57 -08:00
#ifdef WITH_GUI
# include <wx/wx.h>
#endif
2026-06-25 21:40:01 -07:00
#include "m8/run.h"
2026-07-06 04:05:57 -07:00
#ifdef WITH_TUI
# include "tui/Tui.hpp"
#endif
2026-06-25 21:40:01 -07:00
#include "utils.h"
#include "globals.h"
2026-06-25 21:40:01 -07:00
#include "paleinfo.h"
2026-06-27 19:48:40 -07:00
#ifdef _WIN32
# include "usb/driver.h"
#endif
2026-06-30 22:44:34 -07:00
#include "usb/pongo_helper.h"
2026-02-05 00:42:57 -08:00
void print_credits() {
printf(
2026-06-26 17:22:45 -07:00
"::\n"
":: Palera1n beta " PALERAIN_VERSION "\n"
"::\n"
":: (c) 2026\n"
"::\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"
":: nekohaxx, plooshi, 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
);
}
void print_usage(char* argv) {
printf(
"Usage: %s [OPTIONS]\n\n"
" -h, --help Print usage information\n"
" -v, --version Print version\n\n"
"Options:\n\n"
" --cli [f] Use command line interface\n"
2026-02-05 00:42:57 -08:00
#ifdef WITH_GUI
" --gui [f] Use graphical user interface\n"
2026-02-05 00:42:57 -08:00
#endif
#ifdef WITH_TUI
" --tui [f] Use terminal user interface\n"
#endif
" --dark-blockchain [f] Enable dark blockchain\n"
" --force-revert [f] Force environment reversion\n"
" -l, --rootless [f] Enable rootless mode (standard)\n"
" -f, --rootful [f] Boots fakefs\n"
" -c, --setup-fakefs [f] Setup fake filesystem\n"
" -B, --setup-partial-fakefs [f] Setup partial fake filesystem\n"
" -s, --safe-mode [f] Enable safe mode\n"
" -T, --telnetd [f] Enable TELNET daemon on port 46 (insecure)\n"
" -V, --verbose-boot [f] Enable verbose booting\n"
" -p, --early-exit [f] Exit after uploading Pongo\n"
" -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"
" -n, --no-colors [f] Disable colors on the command line\n"
" -q, --quick [f] Enable Quick Mode\n"
2026-06-27 19:48:40 -07:00
#ifdef _WIN32
" --install-drivers <PID> Install libusbK drivers for PID\n"
" --remove-drivers <PID> Remove libusbK drivers for PID\n"
2026-06-27 19:48:40 -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
}
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
{"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
{"tui", no_argument, NULL, 3},
#endif
{"dark-blockchain", no_argument, NULL, 4},
{"force-revert", no_argument, NULL, 5},
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'},
{"early-exit", no_argument, NULL, 'p'},
{"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'},
{"no-colors", no_argument, NULL, 'n'},
{"quick", no_argument, NULL, 'q'},
2026-06-27 19:48:40 -07:00
#ifdef _WIN32
{"install-drivers", required_argument, NULL, 6},
{"remove-drivers", required_argument, NULL, 7},
2026-06-27 19:48:40 -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) {
#ifdef WITH_TUI
palerain_flags |= palerain_option_tui;
#else
2026-02-05 00:42:57 -08:00
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
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
while ((options = getopt_long(argc, argv, "hvlfcBsTVpe:k:K:o:r:nq", 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-02 15:22:32 -07:00
printf("Palera1n beta " PALERAIN_VERSION " [USB: %s (openra1n)]\n",
#ifdef __APPLE__
"IOKit"
#else
"libusb"
#endif
);
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
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
#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;
case 'l': // --rootless
palerain_flags &= ~palerain_option_rootful;
palerain_flags |= palerain_option_rootless;
break;
case 'f': // --rootful
palerain_flags &= ~palerain_option_rootless;
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;
case 'p': // --early-exit
palerain_flags |= palerain_option_pongo_exit;
break;
case 'e': // --extra-bootargs
if (strlen(optarg) > (sizeof(boot_args) - 0x20)) {
LOG_ERROR("Boot arguments too long");
exit(1);
}
snprintf(boot_args, sizeof(boot_args), "%s", optarg);
break;
case 'k': // --override-pongo
if (!override_payload_from_file(optarg, &g_payload_pongo)) {
LOG_ERROR("Failed to load pongo payload\n");
exit(1);
}
2026-06-30 22:44:34 -07:00
if (g_payload_pongo.data_len > PONGO_MAX_SZ) {
LOG_ERROR("Pongo payload too large: %zu bytes (max %zu)", g_payload_pongo.data_len, PONGO_MAX_SZ);
exit(1);
}
LOG("Overriding pongo payload with %s", optarg);
break;
case 'K': // --override-kpf
if (!override_payload_from_file(optarg, &g_payload_kpf)) {
LOG_ERROR("Failed to load kpf payload\n");
exit(1);
}
2026-06-30 22:44:34 -07:00
if (g_payload_kpf.data_len < 4
2026-06-30 23:01:15 -07:00
|| (memcmp(g_payload_kpf.data, MACHO_MAGIC_64, 4) != 0
&& memcmp(g_payload_kpf.data, MACHO_MAGIC_32, 4) != 0))
2026-06-30 22:44:34 -07:00
{
LOG_ERROR("Invalid kpf payload, is it macho?");
exit(1);
}
LOG("Overriding kpf payload with %s", optarg);
break;
case 'o': // --override-overlay
if (!override_payload_from_file(optarg, &g_payload_overlay)) {
LOG_ERROR("Failed to load overlay payload\n");
exit(1);
}
LOG("Overriding overlay payload with %s", optarg);
break;
case 'r': // --override-ramdisk
if (!override_payload_from_file(optarg, &g_payload_ramdisk)) {
LOG_ERROR("Failed to load ramdisk payload\n");
exit(1);
}
LOG("Overriding ramdisk payload with %s", optarg);
break;
case 'n': // --no-colors
palerain_flags |= palerain_option_no_colors;
break;
case 'q': // --quick
palerain_flags |= palerain_option_quick;
break;
2026-06-27 19:48:40 -07:00
#ifdef _WIN32
case 6: { // --install-drivers <PID>
2026-06-27 19:48:40 -07:00
unsigned short parsed_pid = (unsigned short)strtol(optarg, NULL, 16);
if (parsed_pid == 0) {
LOG_ERROR("Invalid PID value provided\n");
exit(1);
}
install_libusbk_target(0x05AC, parsed_pid);
exit(0);
}
case 7: { // --remove-drivers <PID>
2026-06-27 19:48:40 -07:00
unsigned short parsed_pid = (unsigned short)strtol(optarg, NULL, 16);
if (parsed_pid == 0) {
LOG_ERROR("Invalid PID value provided\n");
exit(1);
}
uninstall_libusbk_target(0x05AC, parsed_pid);
exit(0);
}
#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;
}
}
if (!(palerain_flags & palerain_option_gui) && !(palerain_flags & palerain_option_tui))
2026-06-28 22:55:46 -07:00
{
bool is_rootful = (palerain_flags & palerain_option_rootful);
bool is_rootless = (palerain_flags & palerain_option_rootless);
bool has_setup = (palerain_flags & palerain_option_setup_rootful) ||
(palerain_flags & palerain_option_setup_partial_root);
2026-06-28 22:55:46 -07:00
if (!is_rootful && !is_rootless)
2026-06-28 22:55:46 -07:00
{
LOG_ERROR("You must specify either -l, --rootless or -f, --rootful.\n");
2026-02-05 00:42:57 -08:00
print_usage(argv[0]);
exit(1);
}
if (is_rootful && is_rootless)
{
LOG_ERROR("You cannot specify both -l, --rootless and -f, --rootful.\n");
print_usage(argv[0]);
exit(1);
}
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 (has_setup && !is_rootful)
{
if (is_rootless) {
LOG_ERROR("-c, --setup-fakefs or -B, --setup-partial-fakefs cannot be used with -l, --rootless.\n");
} else {
LOG_ERROR("-c, --setup-fakefs or -B, --setup-partial-fakefs require -f, --rootful.\n");
}
print_usage(argv[0]);
exit(1);
}
2026-02-05 00:42:57 -08:00
}
}
int main(int argc, char* argv[], char* envp[]) {
print_credits();
parse_arguments(argc, argv);
LOG("palera1n_flags: %llu", palerain_flags);
2026-07-02 15:22:32 -07:00
// communicating with libusb on linux needs root
#ifdef __linux__
if (geteuid() != 0) {
LOG_WARN("You are not running as root, this may cause issues when exploiting");
}
#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;
}
#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
}
#endif
2026-06-28 22:55:46 -07:00
shared_t state{};
2026-06-26 20:55:55 -07:00
return exploit(&state);
2026-02-05 00:42:57 -08:00
}