This commit is contained in:
khcrysalis committed 2026-02-05 00:44:36 -08:00
1 parent 62e03acf81
commit 19347caeaa
82 files changed
+374 -8419

No files matched your search

-197
View File
@@ -1,197 +0,0 @@
all: palera1n
OBJDIR = obj
GENDIR = gen
RESOURCES_DIR = resources
C_SRC = $(wildcard *.c)
OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o))
ifeq (,$(findstring macosx, $(CFLAGS)))
ifneq (,$(findstring version-min=, $(CFLAGS)))
ifneq ($(NO_EMBED_HELPER),1)
C_SRC += $(GENDIR)/gen-libcheckra1nhelper.dylib.c
endif
endif
endif
ifeq ($(NO_EMBED_HELPER),1)
CFLAGS += -DNO_EMBED_HELPER
endif
ifeq ($(DFUHELPER_AUTO_ONLY),1)
CFLAGS += -DDFUHELPER_AUTO_ONLY
endif
ifeq ($(FORCE_HELPER),1)
ifneq ($(NO_EMBED_HELPER),1)
C_SRC += $(GENDIR)/gen-libcheckra1nhelper.dylib.c
endif
CFLAGS += -DFORCE_HELPER
BUILD_OPTIONS += FORCE_HELPER
endif
ifneq ($(NO_RAMDISK),1)
C_SRC += $(GENDIR)/gen-ramdisk.dmg.lzma.c
else
CFLAGS += -DNO_RAMDISK -DRAMDISK_COMPRESSED_SIZE=\"0\"
BUILD_OPTIONS += NO_RAMDISK
endif
ifneq ($(NO_KPF),1)
C_SRC += $(GENDIR)/gen-checkra1n-kpf-pongo.lzma.c
else
CFLAGS += -DNO_KPF
BUILD_OPTIONS += NO_KPF
endif
ifneq ($(NO_OVERLAY),1)
C_SRC += $(GENDIR)/gen-binpack.dmg.c
else
CFLAGS += -DNO_OVERLAY
BUILD_OPTIONS += NO_OVERLAY
endif
ifneq ($(NO_CHECKRAIN),1)
C_SRC += $(GENDIR)/gen-checkra1n.c
else
CFLAGS += -DNO_CHECKRAIN
BUILD_OPTIONS += NO_CHECKRAIN
endif
ifneq ($(NO_CUSTOM_PONGO),1)
C_SRC += $(GENDIR)/gen-Pongo.bin.c
else
CFLAGS += -DNO_CUSTOM_PONGO
BUILD_OPTIONS += NO_CUSTOM_PONGO
endif
ifeq ($(TUI),1)
BUILD_OPTIONS += TUI
CFLAGS += -DTUI
endif
CHECKRA1N_VERSION ?= 0.1337.3
LIPO = lipo
LDID = ldid
ifeq ($(TARGET_OS),Darwin)
ifneq ($(USE_LIBUSB),1)
else
LIBS += -framework SystemConfiguration -framework Security
BUILD_OPTIONS += USE_LIBUSB
endif
# add lto and debug symbols for lto
CFLAGS += -flto=full -g
LDFLAGS += -Wl,-object_path_lto,obj/lto.o
else
USE_LIBUSB = 1
endif
ifeq ($(USE_LIBUSB),1)
CFLAGS += -DUSE_LIBUSB=1
LIBS += $(DEP)/lib/libusb-1.0.a
endif
ifneq ($(ROOTFUL),0)
CFLAGS += -DROOTFUL=1
BUILD_OPTIONS += ROOTFUL
endif
ifeq ($(BUILD_OPTIONS),)
BUILD_OPTIONS = (none)
endif
CFLAGS += -DBUILD_OPTIONS=\""$(BUILD_OPTIONS)"\"
ifeq ($(TARGET_OS),Linux)
ifeq ($(UNAME),Linux)
ifeq ($(CHECKRA1N_NAME),)
ifeq ($(shell arch),x86_64)
CHECKRA1N_NAME := linux-x86_64
else ifeq ($(shell arch | grep -q 'i[3-7]86' && echo 1),1)
CHECKRA1N_NAME := linux-x86
else ifeq ($(shell arch | grep -v '\(arm\|aarch\)[a-z]\?\+64' | grep -q arm && echo 1),1)
CHECKRA1N_NAME := linux-armel
else ifeq ($(shell arch | grep -q '\(arm\|aarch\)[a-z]\?\+64' && echo 1),1)
CHECKRA1N_NAME := linux-arm64
endif
endif
endif
endif
$(RESOURCES_DIR)/checkra1n-%:
curl -Lfo $@ https://assets.checkra.in/downloads/preview/$(CHECKRA1N_VERSION)/$$(echo $@ | cut -d/ -f2)
chmod 755 $@
$(RESOURCES_DIR)/checkra1n: $(RESOURCES_DIR)/checkra1n-macos usb.xml
ifeq ($(TARGET_OS),Darwin)
ifneq (,$(findstring arm64, $(CFLAGS)))
$(LIPO) -thin arm64 -output $(RESOURCES_DIR)/checkra1n $(RESOURCES_DIR)/checkra1n-macos
else ifneq (,$(findstring x86_64, $(CFLAGS)))
$(LIPO) -thin x86_64 -output $(RESOURCES_DIR)/checkra1n $(RESOURCES_DIR)/checkra1n-macos
else ifeq ($(shell arch),i386)
$(LIPO) -thin x86_64 -output $(RESOURCES_DIR)/checkra1n $(RESOURCES_DIR)/checkra1n-macos
else
$(LIPO) -thin $(shell arch) -output $(RESOURCES_DIR)/checkra1n $(RESOURCES_DIR)/checkra1n-macos
endif
ifeq (,$(findstring macosx, $(CFLAGS)))
ifneq (,$(findstring version-min=, $(CFLAGS)))
vtool -remove-build-version 1 -replace -output $(RESOURCES_DIR)/checkra1n $(RESOURCES_DIR)/checkra1n
vtool -set-build-version $(FAKE_PLATFORM) $(FAKE_MINOS) $(FAKE_SDK) -replace -output $(RESOURCES_DIR)/checkra1n $(RESOURCES_DIR)/checkra1n
install_name_tool -change /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit /System/Library/Frameworks/IOKit.framework/IOKit $(RESOURCES_DIR)/checkra1n
install_name_tool -change /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation $(RESOURCES_DIR)/checkra1n
$(LDID) -Susb.xml $(RESOURCES_DIR)/checkra1n
endif
endif
else
cp $(RESOURCES_DIR)/checkra1n-$(CHECKRA1N_NAME) $(RESOURCES_DIR)/checkra1n
endif
$(GENDIR)/gen-%.c: $(RESOURCES_DIR)/%
echo '#include <stdint.h>' > $(RESOURCES_DIR)/../$@
cd $(RESOURCES_DIR) && xxd -iC $$(echo $< | cut -d/ -f2) | sed -e 's/unsigned int/uint32_t/' -e 's/unsigned char/uint8_t/' >> ../$@
$(OBJDIR)/pongo_helper.c.o: pongo_helper.c $(wildcard ../include/*.h) $(RESOURCES_DIR)/ramdisk.dmg $(RESOURCES_DIR)/checkra1n-kpf-pongo
$(CC) -c -o $@ $(CFLAGS) -DRAMDISK_UNCOMPRESSED_SIZE="\"$$(wc -c < $(RESOURCES_DIR)/ramdisk.dmg | tr -d ' ')\"" -DKPF_UNCOMPRESSED_SIZE="\"$$(wc -c < $(RESOURCES_DIR)/checkra1n-kpf-pongo | tr -d ' ')\"" $<
$(OBJDIR)/%.c.o: $(GENDIR)/gen-%.c $(wildcard ../include/*.h)
$(CC) $(CFLAGS) -c -o $<
$(OBJDIR)/%.c.o: %.c $(wildcard ../include/*.h)
$(CC) $(CFLAGS) -c -o $@ $<
palera1n: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o palera1n
ifeq (,$(findstring macosx, $(CFLAGS)))
ifneq (,$(findstring version-min=, $(CFLAGS)))
$(LDID) -Susb.xml palera1n
endif
endif
$(RESOURCES_DIR)/libcheckra1nhelper.dylib: chkstk.S
$(CC) $(CFLAGS) $(LDFLAGS) -shared chkstk.S -o $@
$(RESOURCES_DIR)/checkra1n-kpf-pongo:
curl -Lfo $@ https://cdn.nickchan.lol/palera1n/artifacts/kpf/iOS15/checkra1n-kpf-pongo
$(RESOURCES_DIR)/ramdisk.dmg.lzma: $(RESOURCES_DIR)/ramdisk.dmg
xz --format=lzma -vfc6ekT 0 $< > $@
$(RESOURCES_DIR)/checkra1n-kpf-pongo.lzma: $(RESOURCES_DIR)/checkra1n-kpf-pongo
xz --format=lzma -vfc6ekT 0 $< > $@
$(RESOURCES_DIR)/ramdisk.dmg:
curl -Lfo $@ https://cdn.nickchan.lol/palera1n/c-rewrite/deps/ramdisk.dmg
$(RESOURCES_DIR)/binpack.dmg:
curl -Lfo $@ https://cdn.nickchan.lol/palera1n/c-rewrite/deps/binpack.dmg
$(RESOURCES_DIR)/Pongo.bin:
curl -Lfo $@ https://cdn.nickchan.lol/palera1n/artifacts/kpf/iOS15/Pongo.bin
clean:
rm -rf $(OBJDIR)/*.o $(GENDIR)/*.c $(GENDIR)/*.o palera1n palera1n.dSYM libcheckra1nhelper.dylib
distclean: clean
rm -rf $(RESOURCES_DIR)/*
.PHONY: all clean
-59
View File
@@ -1,59 +0,0 @@
#include <limits.h>
#include <stdlib.h>
const unsigned char *
boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen,
const unsigned char* needle, size_t nlen)
{
size_t scan = 0;
size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called:
* bad character shift */
/* Sanity checks on the parameters */
if (nlen <= 0 || !haystack || !needle)
return NULL;
/* ---- Preprocess ---- */
/* Initialize the table to default value */
/* When a character is encountered that does not occur
* in the needle, we can safely skip ahead for the whole
* length of the needle.
*/
for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1)
bad_char_skip[scan] = nlen;
/* C arrays have the first byte at [0], therefore:
* [nlen - 1] is the last byte of the array. */
size_t last = nlen - 1;
/* Then populate it with the analysis of the needle */
for (scan = 0; scan < last; scan = scan + 1)
bad_char_skip[needle[scan]] = last - scan;
/* ---- Do the matching ---- */
/* Search the haystack, while the needle can still be within it. */
while (hlen >= nlen)
{
/* scan from the end of the needle */
for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1)
if (scan == 0) /* If the first byte matches, we've found it. */
{
return haystack;
}
/* otherwise, we need to skip some bytes and start again.
Note that here we are getting the skip value based on the last byte
of needle, no matter where we didn't match. So if needle is: "abcd"
then we are skipping based on 'd' and that value will be 4, and
for "abcdd" we again skip on 'd' but the value will be only 1.
The alternative of pretending that the mismatched character was
the last character is slower in the normal case (E.g. finding
"abcd" in "...azcd..." gives 4 by using 'd' but only
4-2==2 using 'z'. */
hlen -= bad_char_skip[haystack[last]];
haystack += bad_char_skip[haystack[last]];
}
return NULL;
}
-65
View File
@@ -1,65 +0,0 @@
#define _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET -48
#define _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET -40
.align 4
_thread_chkstk_darwin:
.globl ___chkstk_darwin
___chkstk_darwin: // %w9/x9 == alloca size
stp x10, x11, [sp, #-16]
// validate that the frame pointer is on our stack (no alt stack)
mrs x10, TPIDRRO_EL0
// (%sp - pthread_self()->stackaddr) > 0 ?
#if defined(__ARM64_ARCH_8_32__)
ubfx x9, x9, #0, #32
ldur w11, [x10, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET]
#else
ldur x11, [x10, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET]
#endif
subs x11, sp, x11
b.hs Lprobe
// %sp <= pthread_self()->stackbottom ?
#if defined(__ARM64_ARCH_8_32__)
ldur w11, [x10, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET]
#else
ldur x11, [x10, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET]
#endif
mov x10, sp
cmp x10, x11
b.ls Lprobe
// %sp - (uintptr_t)%x9 < pthread_self()->stackbottom ?
subs x10, x10, x9
b.lo Lcrash
cmp x10, x11
b.lo Lcrash
Lexit:
ldp x10, x11, [sp, #-16]
ret
Lcrash:
// POSIX mandates that stack overflow crashes with SIGSEGV
// so load an address in the guard page and dereference it
//
// x11 contains pthread_self()->stackbottom already
ldr x11, [x11, #-8]
// if main_thread caused stack growth with setrlimit()
// fall into Lprobe and eventually cause SIGSEGV.
Lprobe:
mov x10, sp
cmp x9, #0x1000
b.lo Lend
Lloop:
sub x10, x10, #0x1000
ldr x11, [x10]
sub x9, x9, #0x1000
cmp x9, #0x1000
b.hi Lloop
Lend:
sub x10, x10, x9
ldr x11, [x10]
b Lexit
-25
View File
@@ -1,25 +0,0 @@
#include <stdio.h>
#ifndef BAKERAIN_DEVELOPE_R
#define BAKERAIN_DEVELOPE_R "kok3shidoll"
#endif
#define THE_PLUSH "Ploosh"
#define NEKO_DEVELOPE_R "HAHALOSAH"
#define T void
#define R print_credits(void) {
#define O fprintf(
#define U stderr,
#define B "#\n# palera1n: " BUILD_TAG " \n#\n"
#define L "# ======== Made by =======\n"
#define E "# Made by: Nick Chan, " THE_PLUSH ", Khcrysalis, Mineek, staturnz, " BAKERAIN_DEVELOPE_R ", " NEKO_DEVELOPE_R " \n"
#define M "# ======== Thanks to =======\n"
#define A "# Thanks to: llsc12, Nebula, Lrdsnow, nikias (libimobiledevice),\n"
#define K "# checkra1n team (Siguza, axi0mx, littlelailo et al.),\n"
#define I "# Procursus Team (Hayden Seay, Cameron Katri, Keto et.al)\n"
#define N "# ==========================\n\n"
#define G );
#define S }
T R O U B L E M A K I N G S
-405
View File
@@ -1,405 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <fcntl.h>
#include <stddef.h>
#include <unistd.h>
#include <ctype.h>
#ifdef WIN32
#include <windows.h>
#include <winsock2.h>
#else
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <signal.h>
#endif
#include <pthread.h>
#include <inttypes.h>
#include <libirecovery.h>
#include <usbmuxd.h>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libimobiledevice/diagnostics_relay.h>
#include <plist/plist.h>
#ifdef HAVE_LIB_TV_CONTROL
#include <libtvcontrol.h>
#endif
#include <palerain.h>
irecv_device_event_context_t irecvctx = NULL;
usbmuxd_subscription_context_t usbmuxdctx = NULL;
void devinfo_free(devinfo_t *dev) {
free(dev->buildVersion);
free(dev->productType);
free(dev->productVersion);
free(dev->CPUArchitecture);
return;
}
bool cpid_is_arm64(unsigned int cpid) {
/*
* ========== 0x6000 ===========
* M1 Pro, M1 Max, etc.
* ========== 0x7000 ===========
* (ARM64) A8(X)
* ========== 0x7002 ===========
* S1
* ========== 0x8000 ===========
* (ARM64) A9 (Samsung), A9X
* ========== 0x8002 ===========
* S1P, S2, T1
* ========== 0x8003 ===========
* (ARM64) A9 (TSMC)
* ========== 0x8004 ===========
* S3 - S5
* ========== 0x8010 ===========
* (ARM64) A10(X) - A11, T2
* ========== 0x8020 ===========
* A12, M1, M2, etc
* ========== 0x8700 ===========
* iPod SoCs
* ========== 0x8747 ===========
* Haywire
* ========== 0x8900 ===========
* S5L8900 - A6(X)
* ========== 0x8960 ===========
* (ARM64) A7
*/
return (
cpid == 0x8960 || cpid == 0x7000 || cpid == 0x7001 ||
cpid == 0x8000 || cpid == 0x8001 || cpid == 0x8003 ||
cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8012 ||
cpid == 0x8015
);
}
int subscribe_cmd(usbmuxd_event_cb_t device_event_cb, irecv_device_event_cb_t irecv_event_cb)
{
int ret;
if ((ret = usbmuxd_events_subscribe(&usbmuxdctx, device_event_cb, NULL))) return ret;
if ((ret = irecv_device_event_subscribe(&irecvctx, irecv_event_cb, NULL))) return ret;
return 0;
}
int unsubscribe_cmd(void)
{
int ret;
if ((ret = usbmuxd_events_unsubscribe(usbmuxdctx))) return ret;
if ((ret = irecv_device_event_unsubscribe(irecvctx))) return ret;
irecvctx = NULL;
usbmuxdctx = NULL;
return 0;
}
int devinfo_cmd(devinfo_t *dev, const char *udid)
{
int ret;
uint64_t this_ecid = 0;
char *productType = NULL;
char *productVersion = NULL;
char *buildVersion = NULL;
const char *displayName = NULL;
char *CPUArchitecture = NULL;
idevice_t device = NULL;
lockdownd_client_t lockdown = NULL;
if ((ret = idevice_new_with_options(&device, udid, IDEVICE_LOOKUP_USBMUX)) != IDEVICE_E_SUCCESS)
{
LOG(LOG_ERROR, "Error connecting to device: %d (%s)", ret, lockdownd_strerror(ret));
return -1;
}
if ((ret = lockdownd_client_new_with_handshake(device, &lockdown, "palera1n")) != LOCKDOWN_E_SUCCESS)
{
(void)idevice_free(device);
LOG(LOG_ERROR, "Device is not in normal mode: %d (%s)", ret, lockdownd_strerror(ret));
return -1;
}
plist_t node = NULL;
if ((ret = lockdownd_get_value(lockdown, NULL, "UniqueChipID", &node)) != LOCKDOWN_E_SUCCESS)
{
(void)lockdownd_client_free(lockdown);
(void)idevice_free(device);
LOG(LOG_ERROR, "Error getting ECID: %d (%s)", ret, lockdownd_strerror(ret));
return -1;
}
plist_get_uint_val(node, &this_ecid);
plist_free(node);
node = NULL;
if ((ret = lockdownd_get_value(lockdown, NULL, "ProductType", &node)) != LOCKDOWN_E_SUCCESS)
{
(void)lockdownd_client_free(lockdown);
(void)idevice_free(device);
LOG(LOG_ERROR, "Error getting product type: %d (%s)", ret, lockdownd_strerror(ret));
return -1;
}
plist_get_string_val(node, &productType);
plist_free(node);
node = NULL;
if ((ret = lockdownd_get_value(lockdown, NULL, "CPUArchitecture", &node)) != LOCKDOWN_E_SUCCESS)
{
(void)lockdownd_client_free(lockdown);
(void)idevice_free(device);
LOG(LOG_ERROR, "Error getting CPU type: %d (%s)", ret, lockdownd_strerror(ret));
return -1;
}
plist_get_string_val(node, &CPUArchitecture);
plist_free(node);
node = NULL;
if ((ret = lockdownd_get_value(lockdown, NULL, "ProductVersion", &node)) != LOCKDOWN_E_SUCCESS)
{
(void)lockdownd_client_free(lockdown);
(void)idevice_free(device);
LOG(LOG_ERROR, "Error getting product version: %d (%s)", ret, lockdownd_strerror(ret));
return -1;
}
plist_get_string_val(node, &productVersion);
plist_free(node);
node = NULL;
if ((ret = lockdownd_get_value(lockdown, NULL, "BuildVersion", &node)) != LOCKDOWN_E_SUCCESS)
{
(void)lockdownd_client_free(lockdown);
(void)idevice_free(device);
LOG(LOG_ERROR, "Error getting build version: %d (%s)", ret, lockdownd_strerror(ret));
return -1;
}
plist_get_string_val(node, &buildVersion);
plist_free(node);
(void)lockdownd_client_free(lockdown);
(void)idevice_free(device);
irecv_device_t rcvydev;
if (irecv_devices_get_device_by_product_type(productType, &rcvydev) == IRECV_E_SUCCESS)
{
displayName = rcvydev->display_name;
} else
{
displayName = productType;
}
dev->buildVersion = buildVersion;
dev->ecid = this_ecid;
dev->CPUArchitecture = CPUArchitecture;
dev->displayName = displayName;
dev->productType = productType;
dev->productVersion = productVersion;
return 0;
}
int enter_recovery_cmd(const char* udid) {
idevice_t device = NULL;
lockdownd_client_t lockdown = NULL;
if (idevice_new(&device, udid) != IDEVICE_E_SUCCESS) {
LOG(LOG_ERROR, "Could not connect to device");
return -1;
}
lockdownd_error_t ldret = lockdownd_client_new(device, &lockdown, "palera1n");
if (ldret != LOCKDOWN_E_SUCCESS) {
LOG(LOG_ERROR, "Could not connect to lockdownd: %s", lockdownd_strerror(ldret));
return -1;
}
ldret = lockdownd_enter_recovery(lockdown);
if (ldret == LOCKDOWN_E_SESSION_INACTIVE) {
lockdownd_client_free(lockdown);
lockdown = NULL;
ldret = lockdownd_client_new_with_handshake(device, &lockdown, "palera1n");
if (ldret != LOCKDOWN_E_SUCCESS) {
LOG(LOG_ERROR, "Could not connect to lockdownd: %s", lockdownd_strerror(ldret));
return -1;
}
ldret = lockdownd_enter_recovery(lockdown);
}
if (ldret != LOCKDOWN_E_SUCCESS) {
LOG(LOG_ERROR, "Could not trigger entering recovery mode: %s", lockdownd_strerror(ldret));
return -1;
}
lockdownd_client_free(lockdown);
idevice_free(device);
return 0;
}
int reboot_cmd(const char* udid) {
idevice_t device = NULL;
lockdownd_client_t lockdown = NULL;
if (idevice_new(&device, udid) != IDEVICE_E_SUCCESS) {
LOG(LOG_ERROR, "Could not connect to device");
return -1;
} else {
diagnostics_relay_client_t diag = NULL;
if (diagnostics_relay_client_start_service(device, &diag, "palera1n") == DIAGNOSTICS_RELAY_E_SUCCESS) {
if (diagnostics_relay_restart(diag, DIAGNOSTICS_RELAY_ACTION_FLAG_WAIT_FOR_DISCONNECT) != DIAGNOSTICS_RELAY_E_SUCCESS) {
LOG(LOG_ERROR, "Could not reboot device.");
}
(void)diagnostics_relay_goodbye(diag);
(void)diagnostics_relay_client_free(diag);
} else {
LOG(LOG_ERROR, "Could not connect to device.");
return -1;
}
idevice_free(device);
}
return 0;
}
int passstat_cmd(unsigned char* status, const char* udid) {
lockdownd_error_t lerr = LOCKDOWN_E_SUCCESS;
diagnostics_relay_error_t derr = DIAGNOSTICS_RELAY_E_SUCCESS;
idevice_t dev = NULL;
lockdownd_client_t lockdown = NULL;
lockdownd_service_descriptor_t service = NULL;
diagnostics_relay_client_t diagnostics_client = NULL;
plist_t node = NULL;
plist_t keys = NULL;
plist_t status_node = NULL;
plist_t value_node = NULL;
if (idevice_new(&dev, udid) != IDEVICE_E_SUCCESS)
{
LOG(LOG_ERROR, "Error detecting device type");
return -1;
}
lerr = lockdownd_client_new_with_handshake(dev, &lockdown, "idevicediagnostics");
if ((lerr != LOCKDOWN_E_SUCCESS) || !lockdown)
{
idevice_free(dev);
LOG(LOG_ERROR, "Error connecting to lockdownd (lockdownd error %d: (%s))", lerr, lockdownd_strerror(lerr));
return -1;
}
lerr = lockdownd_start_service(lockdown, "com.apple.mobile.diagnostics_relay", &service);
if ((lerr != LOCKDOWN_E_SUCCESS) || !service)
lerr = lockdownd_start_service(lockdown, "com.apple.iosdiagnostics.relay", &service);
lockdownd_client_free(lockdown);
if ((lerr != LOCKDOWN_E_SUCCESS) || !service)
{
idevice_free(dev);
LOG(LOG_ERROR, "Error starting diagnostics service (lockdownd error %d: (%s))\nUnlock the device and try again.", lerr, lockdownd_strerror(lerr));
return -1;
}
derr = diagnostics_relay_client_new(dev, service, &diagnostics_client);
if ((derr != DIAGNOSTICS_RELAY_E_SUCCESS) || !diagnostics_client)
{
lockdownd_service_descriptor_free(service);
idevice_free(dev);
LOG(LOG_ERROR, "Error starting diagnostics client (diagnostics error %d)", derr);
return -1;
}
keys = plist_new_array();
plist_array_append_item(keys, plist_new_string("xsaMbRQ5rQ+eyKMKG+ZSSg"));
derr = diagnostics_relay_query_mobilegestalt(diagnostics_client, keys, &node);
plist_free(keys);
(void)diagnostics_relay_client_free(diagnostics_client);
(void)lockdownd_service_descriptor_free(service);
(void)idevice_free(dev);
if (derr != DIAGNOSTICS_RELAY_E_SUCCESS || !node)
{
LOG(LOG_ERROR, "Error getting passcode state (lockdownd error %d: (%s))", lerr, lockdownd_strerror(lerr));
return -1;
}
status_node = plist_access_path(node, 2, "MobileGestalt", "Status");
if (!status_node)
{
plist_free(node);
LOG(LOG_ERROR, "Error getting passcode state (invalid status node)");
return -1;
}
char* passstat_status;
plist_get_string_val(status_node, &passstat_status);
if (!status || strncmp(passstat_status, "Succ", 4))
{
if (passstat_status)
free(passstat_status);
passstat_status = NULL;
plist_free(node);
LOG(LOG_ERROR, "Error getting passcode state (invalid status)");
return -1;
}
free(passstat_status);
value_node = plist_access_path(node, 2, "MobileGestalt", "xsaMbRQ5rQ+eyKMKG+ZSSg");
if (!value_node)
{
plist_free(node);
LOG(LOG_ERROR, "Error getting passcode state (invalid value node)");
return -1;
}
uint8_t passcode_state = 2;
plist_get_bool_val(value_node, &passcode_state);
plist_free(node);
*status = passcode_state;
LOG(LOG_VERBOSE4, "Passcode state: %hhu", *status);
return 0;
}
int recvinfo_cmd(recvinfo_t* info, const uint64_t ecid) {
irecv_client_t client = NULL;
irecv_error_t err = irecv_open_with_ecid(&client, ecid);
if (err != IRECV_E_SUCCESS) goto err;
int mode = 0;
err = irecv_get_mode(client, &mode);
if (err != IRECV_E_SUCCESS) goto err;
char *ibootver = NULL;
err = irecv_getenv(client, "build-version", &ibootver);
if (err != IRECV_E_SUCCESS) goto err;
irecv_device_t device;
err = irecv_devices_get_device_by_client(client, &device);
if (err != IRECV_E_SUCCESS) goto err;
info->mode = mode;
info->cpid = device->chip_id;
snprintf(info->product_type, 0x20, "%s", device->product_type);
snprintf(info->display_name, 0x20, "%s", device->display_name);
snprintf(info->iboot_ver, 0x20, "%s", (ibootver) ? ibootver : "");
free(ibootver);
irecv_close(client);
return 0;
err:
LOG(LOG_ERROR, "libirecovery error: %d (%s)", err, irecv_strerror(err));
return -1;
}
int autoboot_cmd(const uint64_t ecid) {
irecv_client_t client = NULL;
irecv_error_t err = irecv_open_with_ecid(&client, ecid);
if (err != IRECV_E_SUCCESS) goto err;
err = irecv_setenv(client, "auto-boot", "true");
if (err != IRECV_E_SUCCESS) goto err;
err = irecv_saveenv(client);
if (err != IRECV_E_SUCCESS) goto err;
err = irecv_close(client);
if (err != IRECV_E_SUCCESS) goto err;
return 0;
err:
LOG(LOG_ERROR, "libirecovery error: %d (%s)", err, irecv_strerror(err));
return -1;
}
int exitrecv_cmd(const uint64_t ecid) {
irecv_client_t client = NULL;
irecv_error_t err = irecv_open_with_ecid(&client, ecid);
if (err != IRECV_E_SUCCESS) goto err;
err = irecv_setenv(client, "auto-boot", "true");
if (err != IRECV_E_SUCCESS) goto err;
err = irecv_saveenv(client);
if (err != IRECV_E_SUCCESS) goto err;
err = irecv_reboot(client);
if (err != IRECV_E_SUCCESS) goto err;
err = irecv_close(client);
if (err != IRECV_E_SUCCESS) goto err;
return 0;
err:
LOG(LOG_ERROR, "libirecovery error: %d (%s)", err, irecv_strerror(err));
return -1;
}
-364
View File
@@ -1,364 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdbool.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <inttypes.h>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libimobiledevice/diagnostics_relay.h>
#include <plist/plist.h>
#include <libirecovery.h>
#include <usbmuxd.h>
#include <ANSI-color-codes.h>
#include <palerain.h>
#define FORMAT_KEY_VALUE 1
#define FORMAT_XML 2
#define NO_PHYSICAL_HOME_BUTTON (cpid == 0x8015 || (cpid == 0x8010 && (bdid == 0x08 || bdid == 0x0a || bdid == 0x0c || bdid == 0x0e)))
#define IS_APPLE_TV_HD (cpid == 0x7000 && bdid == 0x34)
#define IS_APPLE_TV_4K (cpid == 0x8011 && bdid == 0x02)
#define IS_APPLE_HOME1 (cpid == 0x7000 && bdid == 0x38)
#define IS_APPLE_HOME2 (cpid == 0x7000 && bdid == 0x1a)
#define IS_APPLE_HOME (IS_APPLE_HOME1 || IS_APPLE_HOME1)
#define IS_APPLETV (IS_APPLE_TV_4K || IS_APPLE_TV_HD || IS_APPLE_HOME)
int dfuhelper_thr_running = false;
static void step(int time, int time2, char *text, bool (*cond)(uint64_t), uint64_t cond_arg) {
for (int i = time2; i < time; i++) {
printf(
(palerain_flags & palerain_option_no_colors)
? "\r\033[K%s (%d)"
: BCYN "\r\033[K%s (%d)" CRESET, text, time - i + time2
);
fflush(stdout);
sleep(1);
if (cond != NULL && cond(cond_arg)) pthread_exit(NULL);
}
printf(
(palerain_flags & palerain_option_no_colors)
? "\r%s (%d)"
: CYN "\r%s (%d)" CRESET, text, time2
);
if (time2 == 0) puts("");
}
static int connected_normal_mode(const usbmuxd_device_info_t *usbmuxd_device) {
devinfo_t dev;
int ret;
ret = devinfo_cmd(&dev, usbmuxd_device->udid);
if (ret != 0) {
LOG(LOG_ERROR, "Unable to get device information");
return 0;
}
if (strcmp(dev.CPUArchitecture, "arm64")) {
devinfo_free(&dev);
LOG(LOG_WARNING, "Ignoring non-arm64 device...");
LOG(LOG_WARNING, "palera1n doesn't and never will work on A12+ (arm64e)");
return -1;
}
if ((palerain_flags & palerain_option_device_info)) {
printf("Mode: normal\n");
printf("ProductType: %s\n", dev.productType);
printf("Architecture: %s\n", dev.CPUArchitecture);
printf("Version: %s\n", dev.productVersion);
printf("DisplayName: %s\n", dev.displayName);
device_has_booted = true;
set_spin(0);
unsubscribe_cmd();
return 0;
}
/* For Booting Linux etc */
if (!getenv("PALERA1N_BYPASS_PASSCODE_CHECK") &&
!strncmp(dev.productType, "iPhone10,", strlen("iPhone10,")
)) {
if (!(palerain_flags & palerain_option_device_info))
LOG(LOG_VERBOSE2, "Product %s requires passcode to be disabled", dev.productType);
unsigned char passcode_state = 0;
ret = passstat_cmd(&passcode_state, usbmuxd_device->udid);
if (ret != 0) {
LOG(LOG_ERROR, "Failed to get passcode state");
devinfo_free(&dev);
return -1;
}
if (passcode_state) {
LOG(LOG_ERROR, "Passcode must be disabled on this device");
if (!(palerain_flags & palerain_option_device_info))
LOG(LOG_ERROR, "Additionally, passcode must never be set since a restore on iOS 16+");
devinfo_free(&dev);
return -1;
}
}
if (getenv("PALERA1N_BYPASS_PASSCODE_CHECK"))
LOG(LOG_WARNING, "Bypassed passcode check");
if (verbose > 1) {
/* (LOG_VERBOSE - 3) or below*/
LOG(LOG_INFO, "Telling device with udid %s to enter recovery mode immediately", usbmuxd_device->udid);
} else {
/* At least (LOG_VERBOSE2 - 3) */
LOG(LOG_INFO, "Entering recovery mode");
}
enter_recovery_cmd(usbmuxd_device->udid);
devinfo_free(&dev);
if ((palerain_flags & palerain_option_enter_recovery)) {
device_has_booted = true;
set_spin(0);
unsubscribe_cmd();
}
return 0;
}
static bool conditional(uint64_t ecid) {
return get_ecid_wait_for_dfu() != ecid;
}
static void* connected_recovery_mode(struct irecv_device_info* info) {
int ret;
uint64_t ecid;
uint32_t cpid, bdid;
cpid = info->cpid;
ecid = info->ecid;
bdid = info->bdid;
info = NULL;
if (!cpid_is_arm64(cpid)) {
LOG(LOG_WARNING, "Ignoring non-arm64 device...");
return NULL;
}
sleep(1);
ret = autoboot_cmd(ecid);
if (ret) {
LOG(LOG_ERROR, "Cannot set auto-boot back to true");
return NULL;
}
#if !defined(DFUHELPER_AUTO_ONLY)
if (IS_APPLE_TV_4K) {
LOG(LOG_INFO, "Depending on your connection method, you might need to press a button on your cable/board during reboot");
}
LOG(LOG_INFO, "Press Enter when ready for DFU mode");
getchar();
#endif
if (IS_APPLETV) {
if (IS_APPLE_TV_HD) {
step(10, 8, "Hold menu + play button", NULL, 0);
set_ecid_wait_for_dfu(ecid);
ret = exitrecv_cmd(ecid);
if (ret) {
LOG(LOG_ERROR, "Cannot exit recovery mode");
set_ecid_wait_for_dfu(0);
return NULL;
}
printf("\r\033[K");
step(8, 0, "Hold menu + play button", conditional, ecid);
} else if (IS_APPLE_TV_4K) {
step(2, 0, "About to reboot device", NULL, 0);
set_ecid_wait_for_dfu(ecid);
ret = exitrecv_cmd(ecid);
if (ret) {
LOG(LOG_ERROR, "Cannot exit recovery mode");
set_ecid_wait_for_dfu(0);
return NULL;
}
step(4, 0, "Waiting for device to reconnect in DFU mode", conditional, ecid);
} else if (IS_APPLE_HOME) {
step(6, 4, "Put device in upside down orientation", NULL, 0);
set_ecid_wait_for_dfu(ecid);
ret = exitrecv_cmd(ecid);
if (ret) {
LOG(LOG_ERROR, "Cannot exit recovery mode");
set_ecid_wait_for_dfu(0);
return NULL;
}
step(4, 0, "Put device upside down orientation", conditional, ecid);
}
} else if (cpid != 0x8012) {
if (NO_PHYSICAL_HOME_BUTTON)
step(4, 2, "Hold volume down + side button", NULL, 0);
else
step(4, 2, "Hold home + power button", NULL, 0);
set_ecid_wait_for_dfu(ecid);
ret = exitrecv_cmd(ecid);
if (ret) {
LOG(LOG_ERROR, "Cannot exit recovery mode");
set_ecid_wait_for_dfu(0);
return NULL;
}
printf("\r\033[K");
if (NO_PHYSICAL_HOME_BUTTON) {
step(2, 0, "Hold volume down + side button", NULL, 0);
step(10, 0, "Hold volume down button", conditional, ecid);
} else {
step(2, 0, "Hold home + power button", NULL, 0);
step(10, 0, "Hold home button", conditional, ecid);
}
}
if (get_ecid_wait_for_dfu() == ecid) {
LOG(LOG_WARNING, "Whoops, device did not enter DFU mode");
LOG(LOG_INFO, "Waiting for device to reconnect...");
set_ecid_wait_for_dfu(0);
return NULL;
}
set_ecid_wait_for_dfu(0);
pthread_exit(NULL);
return NULL;
}
static void* connected_dfu_mode(struct irecv_device_info* info) {
if (get_ecid_wait_for_dfu() == info->ecid) {
set_ecid_wait_for_dfu(0);
puts("");
LOG(LOG_INFO, "Device entered DFU mode successfully");
}
unsigned int bdid = info->bdid;
unsigned int cpid = info->cpid;
if (IS_APPLE_HOME) {
step(2, 0, "Put device in upright orientation", NULL, 0);
}
set_spin(0);
unsubscribe_cmd();
pthread_exit(NULL);
return NULL;
}
static void device_event_cb(const usbmuxd_event_t *event, void* userdata) {
if (event->device.conn_type != CONNECTION_TYPE_USB) return;
switch (event->event) {
case UE_DEVICE_ADD:
LOG(LOG_VERBOSE, "Normal mode device connected");
if ((palerain_flags & palerain_option_exit_recovery)) {
break;
} else if ((palerain_flags & palerain_option_reboot_device)) {
int ret = reboot_cmd(event->device.udid);
if (!ret) {
LOG(LOG_INFO, "Restarted device");
set_spin(0);
unsubscribe_cmd();
}
pthread_exit(NULL);
break;
}
connected_normal_mode(&event->device);
break;
case UE_DEVICE_REMOVE:
LOG(LOG_VERBOSE, "Normal mode device disconnected");
break;
}
}
static void irecv_device_event_cb(const irecv_device_event_t *event, void* userdata) {
pthread_t recovery_thread, dfu_thread;
int ret;
switch(event->type) {
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) {
if (!(palerain_flags & palerain_option_device_info))
LOG(LOG_VERBOSE, "Recovery mode device %" PRIu64 " connected", event->device_info->ecid);
if ((palerain_flags & palerain_option_exit_recovery)) {
ret = exitrecv_cmd(event->device_info->ecid);
if (!ret) {
LOG(LOG_INFO, "Exited recovery mode");
device_has_booted = true;
set_spin(0);
unsubscribe_cmd();
} else {
LOG(LOG_WARNING, "Could not exit recovery mode");
}
if (dfuhelper_thr_running) pthread_cancel(dfuhelper_thread);
pthread_exit(NULL);
break;
}
if ((palerain_flags & palerain_option_device_info)) {
recvinfo_t info;
ret = recvinfo_cmd(&info, event->device_info->ecid);
if (ret) {
LOG(LOG_WARNING, "Could not get info from device");
} else {
printf("Mode: Recovery\n");
printf("ProductType: %s\n", info.product_type);
printf("DisplayName: %s\n", info.display_name);
device_has_booted = true;
set_spin(0);
unsubscribe_cmd();
}
if (dfuhelper_thr_running) pthread_cancel(dfuhelper_thread);
pthread_exit(NULL);
break;
}
if ((palerain_flags & palerain_option_enter_recovery) ||
(palerain_flags & palerain_option_reboot_device)) return;
pthread_create(&recovery_thread, NULL, (pthread_start_t)connected_recovery_mode, event->device_info);
} else if (event->mode == IRECV_K_DFU_MODE) {
if (!(palerain_flags & palerain_option_device_info))
LOG(LOG_VERBOSE, "DFU mode device %" PRIu64 " connected", event->device_info->ecid);
if ((palerain_flags & palerain_option_device_info)) {
recvinfo_t info;
ret = recvinfo_cmd(&info, event->device_info->ecid);
if (ret) {
LOG(LOG_WARNING, "Could not get info from device");
} else {
printf("Mode: DFU\n");
printf("ProductType: %s\n", info.product_type);
printf("DisplayName: %s\n", info.display_name);
device_has_booted = true;
set_spin(0);
unsubscribe_cmd();
}
if (dfuhelper_thr_running) pthread_cancel(dfuhelper_thread);
pthread_exit(NULL);
break;
}
if (
(palerain_flags & palerain_option_exit_recovery) ||
(palerain_flags & palerain_option_enter_recovery) ||
(palerain_flags & palerain_option_reboot_device)) {
break;
}
pthread_create(&dfu_thread, NULL, (pthread_start_t)connected_dfu_mode, event->device_info);
}
break;
case IRECV_DEVICE_REMOVE:
LOG(LOG_VERBOSE, "Recovery mode device disconnected");
break;
}
}
void *dfuhelper(void* ptr) {
dfuhelper_thr_running = true;
set_spin(1);
subscribe_cmd(device_event_cb, irecv_device_event_cb);
while (get_spin()) {
sleep(1);
};
dfuhelper_thr_running = false;
return 0;
}
-206
View File
@@ -1,206 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdbool.h>
#include <unistd.h>
#include <spawn.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <sys/utsname.h>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
extern char **environ;
extern char* gOverrideLibcheckra1nHelper;
#include <palerain.h>
#ifdef TUI
#include <tui.h>
#endif
#include <xxd-embedded.h>
char* pongo_path = NULL;
bool external_pongo = false;
char* ext_checkra1n = NULL;
#define tmpdir getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR")
int exec_checkra1n(void) {
LOG(LOG_INFO, "About to execute checkra1n");
int fd_checkra1n, fd_pongo, ret;
char* checkra1n_path = NULL;
#ifndef NO_CUSTOM_PONGO
if (pongo_path == NULL) {
pongo_path = malloc(strlen(tmpdir) + 20);
if (pongo_path == NULL) {
LOG(LOG_FATAL, "memory allocation failed\n");
return -1;
}
snprintf(pongo_path, strlen(tmpdir) + 20, "%s/Pongo.bin.XXXXXX", tmpdir);
fd_pongo = mkstemp(pongo_path);
if (fd_pongo == -1) {
LOG(LOG_FATAL, "Cannot open temporary file %s: %d (%s)", pongo_path, errno, strerror(errno));
free(pongo_path);
return -1;
}
ssize_t didWrite_Pongo_bin = write(fd_pongo, Pongo_bin, Pongo_bin_len);
if (didWrite_Pongo_bin != (ssize_t)Pongo_bin_len) {
LOG(LOG_FATAL, "Size written to %s does not match expected: %zd != %" PRIu32 ": %d (%s)", pongo_path, didWrite_Pongo_bin, Pongo_bin_len, errno, strerror(errno));
close(fd_pongo);
unlink(pongo_path);
free(pongo_path);
pongo_path = NULL;
return -1;
}
} else external_pongo = true;
#endif
if (ext_checkra1n != NULL) {
checkra1n_path = ext_checkra1n;
} else {
checkra1n_path = malloc(strlen(tmpdir) + 20);
if (checkra1n_path == NULL) {
LOG(LOG_FATAL, "memory allocation failed\n");
return -1;
}
snprintf(checkra1n_path, strlen(tmpdir) + 20, "%s/checkra1n.XXXXXX", tmpdir);
fd_checkra1n = mkstemp(checkra1n_path);
if (fd_checkra1n == -1) {
LOG(LOG_FATAL, "Cannot open temporary file %s: %d (%s)", checkra1n_path, errno, strerror(errno));
free(checkra1n_path);
checkra1n_path = NULL;
return -1;
}
ssize_t didWrite_checkra1n = write(fd_checkra1n, checkra1n, checkra1n_len);
if (didWrite_checkra1n != (ssize_t)checkra1n_len) {
LOG(LOG_FATAL, "Size written to %s does not match expected: %zd != %" PRIu32 ": %d (%s)", checkra1n_path, didWrite_checkra1n, checkra1n_len, errno, strerror(errno));
close(fd_checkra1n);
unlink(checkra1n_path);
free(checkra1n_path);
checkra1n_path = NULL;
return -1;
}
close(fd_checkra1n);
ret = chmod(checkra1n_path, 0700);
if (ret) {
LOG(LOG_FATAL, "Cannot chmod %s: %d (%s)", checkra1n_path, errno, strerror(errno));
unlink(checkra1n_path);
free(checkra1n_path);
checkra1n_path = NULL;
return -1;
}
}
#if defined(__APPLE__) && defined(__arm64__) && (TARGET_OS_IPHONE || defined(FORCE_HELPER))
char* libcheckra1nhelper_dylib_path = NULL;
{
struct utsname name;
uname(&name);
unsigned long darwinMajor = strtoul(name.release, NULL, 10);
assert(darwinMajor != 0);
#if !defined(FORCE_HELPER)
if (darwinMajor < 20) {
#endif
if (gOverrideLibcheckra1nHelper) {
libcheckra1nhelper_dylib_path = gOverrideLibcheckra1nHelper;
goto setenv_ra1n;
}
libcheckra1nhelper_dylib_path = malloc(strlen(tmpdir) + 40);
if (libcheckra1nhelper_dylib_path == NULL) {
LOG(LOG_FATAL, "memory allocation failed\n");
return -1;
}
snprintf(libcheckra1nhelper_dylib_path, strlen(tmpdir) + 40, "%s/libcheckra1nhelper.dylib.XXXXXX", tmpdir);
int helper_fd = mkstemp(libcheckra1nhelper_dylib_path);
if (helper_fd == -1) {
LOG(LOG_FATAL, "Cannot open temporary file: %d (%s)", errno, strerror(errno));
return -1;
}
ssize_t didWrite_libcheckra1nhelper = write(helper_fd, libcheckra1nhelper_dylib, libcheckra1nhelper_dylib_len);
if ((unsigned int)didWrite_libcheckra1nhelper != libcheckra1nhelper_dylib_len) {
LOG(LOG_FATAL, "Size written does not match expected: %zd != %" PRIu32 ": %d (%s)", didWrite_libcheckra1nhelper, libcheckra1nhelper_dylib_len, errno, strerror(errno));
close(helper_fd);
unlink(libcheckra1nhelper_dylib_path);
return -1;
}
close(helper_fd);
ret = chmod(libcheckra1nhelper_dylib_path, 0700);
if (ret) {
LOG(LOG_FATAL, "Cannot chmod %s: %d (%s)", libcheckra1nhelper_dylib_path, errno, strerror(errno));
unlink(libcheckra1nhelper_dylib_path);
return -1;
}
setenv_ra1n:
setenv("DYLD_INSERT_LIBRARIES", libcheckra1nhelper_dylib_path, 1);
#if !defined(FORCE_HELPER)
}
#endif
}
#endif
char args[0x10] = "-E";
if ((palerain_flags & palerain_option_demote)) strncat(args, "d", 0xf);
if (!(palerain_flags & palerain_option_checkrain_is_clone)) {
strncat(args, "p", 0xf);
if (verbose >= 2) strncat(args, "v", 0xf);
if ((palerain_flags & palerain_option_no_colors)) strncat(args, "n", 0xf);
} else {
strncat(args, "R", 0xf);
}
LOG(LOG_VERBOSE5, "%s", args);
if (pongo_path != NULL) LOG(LOG_VERBOSE5, "%s", pongo_path);
pid_t pid;
posix_spawn_file_actions_t action;
posix_spawn_file_actions_init(&action);
#ifdef TUI
if (tui_is_jailbreaking) {
// silence checkra1n
posix_spawn_file_actions_addopen(&action, 1, "/dev/null", O_WRONLY, 0);
posix_spawn_file_actions_addopen(&action, 2, "/dev/null", O_WRONLY, 0);
}
#endif
ret = posix_spawn(&pid, checkra1n_path, &action, NULL, (char* []){
checkra1n_path,
args,
"-k",
pongo_path,
NULL
}, environ);
posix_spawn_file_actions_destroy(&action);
if (ret) {
LOG(LOG_FATAL, "Cannot posix spawn %s: %d (%s)", checkra1n_path, errno, strerror(errno));
if (ext_checkra1n != NULL) unlink(checkra1n_path);
return -1;
}
LOG(LOG_VERBOSE2, "%s spawned successfully", checkra1n_path);
sleep(2);
if (ext_checkra1n == NULL) {
unlink(checkra1n_path);
free(checkra1n_path);
checkra1n_path = NULL;
}
waitpid(pid, NULL, 0);
if (!external_pongo && pongo_path != NULL) {
unlink(pongo_path);
}
if (pongo_path != NULL) free(pongo_path);
pongo_path = NULL;
#if defined(__APPLE__) && defined(__arm64__) && (TARGET_OS_IPHONE || defined(FORCE_HELPER))
if (libcheckra1nhelper_dylib_path != NULL) {
if (!gOverrideLibcheckra1nHelper) unlink(libcheckra1nhelper_dylib_path);
unsetenv("DYLD_INSERT_LIBRARIES");
unsetenv("DYLD_FORCE_FLAT_NAMESPACE");
if (!gOverrideLibcheckra1nHelper) free(libcheckra1nhelper_dylib_path);
libcheckra1nhelper_dylib_path = NULL;
}
#endif
return 0;
}
-31
View File
@@ -1,31 +0,0 @@
#include <stdlib.h>
#ifdef NO_KPF
unsigned char* checkra1n_kpf_pongo_lzma = NULL;
unsigned int checkra1n_kpf_pongo_lzma_len = 0;
#endif
#ifdef NO_RAMDISK
unsigned char* ramdisk_dmg_lzma = NULL;
unsigned int ramdisk_dmg_lzma_len = 0;
#endif
#ifdef NO_CHECKRAIN
unsigned char* checkra1n = NULL;
unsigned int checkra1n_len = 0;
#endif
#ifdef NO_OVERLAY
unsigned char* binpack_dmg = NULL;
unsigned int binpack_dmg_len = 0;
#endif
#ifdef NO_CUSTOM_PONGO
unsigned char* Pongo_bin = NULL;
unsigned int Pongo_bin_len = 0;
#endif
#ifdef NO_EMBED_HELPER
unsigned char* libcheckra1nhelper_dylib = NULL;
unsigned int libcheckra1nhelper_dylib_len = 0;
#endif
-1
View File
@@ -1 +0,0 @@
*.o
-1
View File
@@ -1 +0,0 @@
.
-85
View File
@@ -1,85 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>
#include <assert.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pthread.h>
#include <inttypes.h>
#include <getopt.h>
#include <errno.h>
#include <spawn.h>
#include <sys/mman.h>
#include <time.h>
#include <libimobiledevice/libimobiledevice.h>
#include <ANSI-color-codes.h>
#include <palerain.h>
#include <xxd-embedded.h>
#include <paleinfo.h>
pthread_mutex_t spin_mutex, found_pongo_mutex, ecid_dfu_wait_mutex;
bool spin, found_pongo = 0;
uint64_t ecid_wait_for_dfu = 0;
static bool get_locked_bool(bool* val, pthread_mutex_t* mutex) {
// fprintf(stderr, "%s: val = %p mutex = %p\n", __func__, (void*)val, (void*)mutex);
pthread_mutex_lock(mutex);
bool ret = *val;
pthread_mutex_unlock(mutex);
return ret;
}
static bool set_locked_bool(bool* val, bool newval, pthread_mutex_t* mutex) {
// fprintf(stderr, "%s: val = %p mutex = %p, newval = %d\n", __func__, (void*)val, (void*)mutex, newval);
pthread_mutex_lock(mutex);
*val = newval;
pthread_mutex_unlock(mutex);
return newval;
}
bool get_spin(void) {
return get_locked_bool(&spin, &spin_mutex);
}
bool set_spin(bool newval) {
return set_locked_bool(&spin, newval, &spin_mutex);
}
bool get_found_pongo(void) {
return get_locked_bool(&found_pongo, &found_pongo_mutex);
}
bool set_found_pongo(bool val) {
return set_locked_bool(&found_pongo, val, &found_pongo_mutex);
}
uint64_t get_ecid_wait_for_dfu(void) {
LOG(LOG_VERBOSE5, "locking ecid wait for dfu mutex for get");
pthread_mutex_lock(&ecid_dfu_wait_mutex);
uint64_t ret = ecid_wait_for_dfu;
LOG(LOG_VERBOSE5, "UN-locking ecid wait for dfu mutex, ecid_wait_for_dfu value is %llu", ret);
pthread_mutex_unlock(&ecid_dfu_wait_mutex);
return ret;
}
uint64_t set_ecid_wait_for_dfu(uint64_t ecid) {
LOG(LOG_VERBOSE5, "locking ecid wait for dfu mutex for set ecid_wait_for_dfu = %llu", ecid);
pthread_mutex_lock(&ecid_dfu_wait_mutex);
ecid_wait_for_dfu = ecid;
LOG(LOG_VERBOSE5, "UN-locking ecid wait for dfu mutex afrer setting ecid_wait_for_dfu");
pthread_mutex_unlock(&ecid_dfu_wait_mutex);
return ecid;
}
-107
View File
@@ -1,107 +0,0 @@
#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <pthread.h>
#include <assert.h>
#include <ANSI-color-codes.h>
#include <palerain.h>
#ifdef TUI
#include <tui.h>
#endif
int p1_log(log_level_t loglevel, const char *fname, int lineno, const char *fxname, const char *__restrict format, ...)
{
#ifdef TUI
if (tui_started) return 0;
#endif
if (verbose >= 5
#ifdef TUI
&& !(palerain_flags & palerain_option_tui)
#endif
) fprintf(stderr, "p1_log: loglevel %d from %s:%d:%s()\n", loglevel, fname, lineno, fxname);
int ret = 0;
char type[0x10];
char colour[0x10];
char colour_bold[0x10];
va_list args;
va_start(args, format);
if (verbose < (loglevel - 3) && loglevel > LOG_INFO) {
if (verbose >= 5
#ifdef TUI
&& !tui_started
#endif
) fprintf(stderr, "p1_log: hid log with high log level (%d < %d)\n", verbose, loglevel - 3);
va_end(args);
return 0;
}
switch (loglevel) {
case LOG_FATAL:
snprintf(type, 0x10, "%s", "!");
snprintf(colour, 0x10, "%s", RED);
snprintf(colour_bold, 0x10, "%s", BRED);
break;
case LOG_ERROR:
snprintf(type, 0x10, "%s", "Error");
snprintf(colour, 0x10, "%s", RED);
snprintf(colour_bold, 0x10, "%s", BRED);
break;
case LOG_WARNING:
snprintf(type, 0x10, "%s", "Warning");
snprintf(colour, 0x10, "%s", YEL);
snprintf(colour_bold, 0x10, "%s", BYEL);
break;
case LOG_INFO:
snprintf(type, 0x10, "%s", "Info");
snprintf(colour, 0x10, "%s", CYN);
snprintf(colour_bold, 0x10, "%s", BCYN);
break;
default:
assert(loglevel >= 0);
snprintf(type, 0x10, "%s", "Verbose");
snprintf(colour, 0x10, "%s", WHT);
snprintf(colour_bold, 0x10, "%s", BWHT);
break;
}
if ((palerain_flags & palerain_option_no_colors)) {
colour[0] = '\0';
colour_bold[0] = '\0';
}
{
pthread_mutex_lock(&log_mutex);
char timestring[0x80];
time_t curtime;
time(&curtime);
struct tm* timeinfo = localtime(&curtime);
if (!(palerain_flags & palerain_option_no_colors))
snprintf(timestring, 0x80, "%s[%s%02d/%02d/%d %02d:%02d:%02d%s]", CRESET, HBLK, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_year - 100, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, CRESET);
else
snprintf(timestring, 0x80, "[%02d/%02d/%d %02d:%02d:%02d]", timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_year - 100, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
if (verbose >= 2 && !(palerain_flags & palerain_option_no_colors)) {
printf("%s| - %s%s <%s> " CRESET "%s" HBLU "%s" CRESET ":" BLU "%d" CRESET ":" BMAG "%s()" CRESET ": \n%s| ----> ", colour_bold, timestring, colour_bold, type, WHT, fname, lineno, fxname, colour_bold);
} else if (!(palerain_flags & palerain_option_no_colors)) {
printf(" - %s %s<%s>%s: ", timestring, colour_bold, type, CRESET);
} else if (verbose >= 2 && (palerain_flags & palerain_option_no_colors)) {
printf("%s| - %s%s <%s> %s:%d:%s(): \n%s| ----> ", colour_bold, timestring, colour_bold, type, fname, lineno, fxname, colour_bold);
} else if ((palerain_flags & palerain_option_no_colors)) {
printf(" - %s %s<%s>: ", timestring, colour_bold, type);
}
printf("%s", colour);
ret = vprintf(format, args);
va_end(args);
if (verbose < 2 && !(palerain_flags & palerain_option_no_colors))
printf(CRESET "\n");
else if (!(palerain_flags & palerain_option_no_colors))
printf("\n%s-%s\n", colour, CRESET);
else if (verbose < 2)
printf("\n");
else
printf("\n%s-\n", colour);
fflush(stdout);
}
pthread_mutex_unlock(&log_mutex);
return ret;
}
-190
View File
@@ -1,190 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include <assert.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pthread.h>
#include <inttypes.h>
#include <errno.h>
#include <spawn.h>
#include <sys/mman.h>
#include <time.h>
#include <libimobiledevice/libimobiledevice.h>
#include <ANSI-color-codes.h>
#include <palerain.h>
#include <xxd-embedded.h>
#include <paleinfo.h>
#define CMD_LEN_MAX 512
#define OVERRIDE_MAGIC 0xd803b376
unsigned int verbose = 0;
/* we want to write to them so don't use string literals */
char xargs_cmd[0x270] = { 'x', 'a', 'r', 'g', 's', '\0' },
palerain_flags_cmd[0x30] = { 'd', 'e', 'a', 'd', 'b', 'e', 'e', 'f', '\0' };
extern char** environ;
niarelap_file_t* kpf_to_upload_1 = &checkra1n_kpf_pongo_lzma;
niarelap_file_t* ramdisk_to_upload_1 = &ramdisk_dmg_lzma;
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;
uint64_t palerain_flags = 0;
pthread_mutex_t log_mutex;
pthread_t dfuhelper_thread, pongo_thread;
void thr_cleanup(void* ptr) {
*(int*)ptr = 0;
}
static int build_checks(void) {
#ifndef NO_CHECKRAIN
#if defined(__APPLE__)
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
if (checkra1n_len <= (UCHAR_MAX + 1)) {
LOG(LOG_FATAL, "checkra1n too small");
}
if (boyermoore_horspool_memmem(&checkra1n[0], checkra1n_len, (const unsigned char *)"[ra1npoc15-part] thanks to", strlen("[ra1npoc15-part] thanks to")) != NULL) {
palerain_flags |= palerain_option_checkrain_is_clone;
}
#endif
return 0;
}
#ifdef TUI
bool tui_started = false;
#endif
#ifdef USE_LIBUSB
void log_cb(libusb_context *ctx, enum libusb_log_level level, const char *str) {
LOG(level + 0, "%s", str);
}
#endif
// save argc, argv, and envp for restarting
int saved_argc;
char** saved_argv;
char** saved_envp;
static int palera1n(int argc, char *argv[], char *envp[]) {
saved_argc = argc;
saved_argv = argv;
saved_envp = envp;
print_credits();
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 (!(palerain_flags & palerain_option_device_info) && (palerain_flags & palerain_option_palerain_version)) goto normal_exit;
#ifdef TUI
if ((palerain_flags & palerain_option_tui) || (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && !(palerain_flags & palerain_option_cli))) {
ret = tui();
if (ret) goto cleanup;
else goto normal_exit;
}
#endif
#ifdef USE_LIBUSB
{
libusb_set_log_cb(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL);
libusb_context* ctx = NULL;
int test_libusb = libusb_init(&ctx);
if (test_libusb) {
LOG(LOG_ERROR, "cannot initialize libusb: %d (%s)\n", test_libusb, libusb_strerror(test_libusb));
libusb_exit(ctx);
goto cleanup;
}
libusb_exit(ctx);
}
#endif
if (!(palerain_flags & palerain_option_device_info))
LOG(LOG_INFO, "Waiting for devices");
if (getenv("USBMUXD_SOCKET_ADDRESS") == NULL && access("/var/run/usbmuxd", F_OK) != 0)
LOG(LOG_WARNING, "/var/run/usbmuxd not found, normal mode device detection will not work.");
pthread_create(&pongo_thread, NULL, pongo_helper, NULL);
pthread_create(&dfuhelper_thread, NULL, dfuhelper, NULL);
pthread_join(dfuhelper_thread, NULL);
set_spin(0);
if ((palerain_flags & (palerain_option_dfuhelper_only |
palerain_option_reboot_device |
palerain_option_exit_recovery |
palerain_option_enter_recovery |
palerain_option_device_info)
) || device_has_booted)
goto normal_exit;
pthread_cancel(pongo_thread);
pthread_join(pongo_thread, NULL);
if (exec_checkra1n()) goto cleanup;
if ((palerain_flags & (palerain_option_pongo_exit | palerain_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:
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[], char* envp[]) {
return palera1n(argc, argv, envp);
}
+165
View File
@@ -0,0 +1,165 @@
#include <unistd.h> // isatty, STDIN_FILENO
#include <cstdlib> // getenv
#include <iostream>
#include <getopt.h>
#include <cstdio>
#include <cstdlib>
#if defined(__APPLE__)
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/usb/IOUSBLib.h>
#endif
#ifdef WITH_GUI
# include <wx/wx.h>
#endif
#include "utils/constants.h"
#include "utils/log.h"
#include "utils/paleinfo.h"
void print_credits() {
printf(
":: ========================== ::\n"
":: palera1n: " PALERAIN_VERSION "\n"
":: ========================== ::\n\n"
);
}
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"
" --cli Use command line interface\n"
#ifdef WITH_GUI
" --gui Use graphical user interface\n"
#endif
" --force-revert Force environment reversion\n"
" -l, --rootless Enable rootless mode (standard)\n"
" -f, --rootful Enable rootful mode\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"
, argv
);
}
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, 3},
#endif
{"force-revert", no_argument, NULL, 0},
{"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'},
{NULL, 0, NULL, 0}
};
#ifdef WITH_GUI
if (isatty(STDIN_FILENO) && getenv("LLVM_PROFILE_FILE") == nullptr) {
palerain_flags &= ~palerain_option_gui;
palerain_flags |= palerain_option_cli;
} else {
palerain_flags &= ~palerain_option_cli;
palerain_flags |= palerain_option_gui;
}
#else
palerain_flags |= palerain_option_cli;
#endif
while ((options = getopt_long(argc, argv, "hvlf:", long_options, &option_index)) != -1) {
switch (options) {
case 'h': // --help
print_usage(argv[0]);
exit(1);
case 'v': // --version
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 3: // --gui
palerain_flags &= ~palerain_option_cli;
palerain_flags &= ~palerain_option_tui;
palerain_flags |= palerain_option_gui;
break;
#endif
case 0: // --force-revert
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 '?':
LOG("Unknown option");
print_usage(argv[0]);
exit(1);
default: break;
}
}
if (!(palerain_flags & palerain_option_gui)) {
if (!(palerain_flags & palerain_option_rootful) && !(palerain_flags & palerain_option_rootless)) {
LOG("You must specify either -l, --rootless or -f, --rootful.\n");
print_usage(argv[0]);
exit(1);
}
}
}
int main(int argc, char* argv[], char* envp[]) {
print_credits();
parse_arguments(argc, argv);
LOG("palera1n_flags: %llu", palerain_flags);
#ifdef WITH_GUI
if (palerain_flags & palerain_option_gui) {
wxEntryStart(argc, argv);
wxTheApp->CallOnInit();
wxTheApp->OnRun();
wxTheApp->OnExit();
wxEntryCleanup();
return 0;
}
#endif
return 0;
}
-1
View File
@@ -1 +0,0 @@
*.o
-1
View File
@@ -1 +0,0 @@
.
-467
View File
@@ -1,467 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>
#include <assert.h>
#include <getopt.h>
#include <limits.h>
#include <errno.h>
#include <palerain.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <sys/stat.h>
#ifdef TUI
#include <tui.h>
#endif
uint64_t* palerain_flags_p = &palerain_flags;
char* gOverrideLibcheckra1nHelper = NULL;
static struct option longopts[] = {
{"setup-partial-fakefs", no_argument, NULL, 'B'},
{"setup-fakefs", no_argument, NULL, 'c'},
{"clean-fakefs", no_argument, NULL, 'C'},
{"dfuhelper", no_argument, NULL, 'D'},
{"help", no_argument, NULL, 'h'},
{"pongo-shell", no_argument, NULL, 'p'},
{"pongo-full", no_argument, NULL, 'P'},
{"debug-logging", no_argument, NULL, 'v'},
{"verbose-boot", no_argument, NULL, 'V'},
{"boot-args", required_argument, NULL, 'e'},
{"fakefs", no_argument, NULL, 'f'},
{"rootless", no_argument, NULL, 'l'},
{"demote", no_argument, NULL, 'd'},
{"force-revert", no_argument, NULL, palerain_option_case_force_revert},
{"no-colors", no_argument, NULL, 'S'},
{"safe-mode", no_argument, NULL, 's'},
{"telnetd", no_argument, NULL, 'T'},
{"version", no_argument, NULL, palerain_option_case_version},
{"override-libcheckra1nhelper", required_argument, NULL, palerain_option_case_libcheckra1nhelper_path},
{"override-pongo", required_argument, NULL, 'k'},
{"override-overlay", required_argument, NULL, 'o'},
{"override-ramdisk", required_argument, NULL, 'r'},
{"override-kpf", required_argument, NULL, 'K'},
{"override-checkra1n", required_argument, NULL, 'i'},
{"reboot-device", no_argument, NULL, 'R'},
{"exit-recovery", no_argument, NULL, 'n'},
{"enter-recovery", no_argument, NULL, 'E'},
{"device-info", no_argument, NULL, 'I'},
#ifdef DEV_BUILD
{"test1", no_argument, NULL, '1'},
{"test2", no_argument, NULL, '2'},
#endif
#ifdef TUI
{"tui", no_argument, NULL, 't'},
#endif
{"cli", no_argument, NULL, palerain_option_case_cli},
{NULL, 0, NULL, 0}
};
static int usage(int e, char* prog_name)
{
fprintf(stderr,
"Usage: %s [-"
"DEhpvVldsSTLRnPI"
#ifdef DEV_BUILD
"12"
#endif
#ifdef ROOTFUL
"cCfB"
#endif
#ifdef TUI
"t"
#endif
"] [-e boot arguments] [-k Pongo image] [-o overlay file] [-r ramdisk file] [-K KPF file] [-i checkra1n file]\n"
"Copyright (C) 2024, palera1n team, All Rights Reserved.\n\n"
"iOS/iPadOS/tvOS 15.0-26.0, bridgeOS 5.0-10.0 arm64 jailbreaking tool\n\n"
"\t--version\t\t\t\tPrint version\n"
"\t--force-revert\t\t\t\tRemove jailbreak\n"
#ifdef DEV_BUILD
"\t-1, --test1\t\t\t\tSet palerain_option_test1\n"
"\t-2, --test2\t\t\t\tSet palerain_option_test2\n"
#endif
#ifdef ROOTFUL
"\t-B, --setup-partial-fakefs\t\tSetup partial fakefs\n"
"\t-c, --setup-fakefs\t\t\tSetup fakefs\n"
"\t-C, --clean-fakefs\t\t\tClean fakefs\n"
#endif
"\t-d, --demote\t\t\t\tDemote\n"
"\t-D, --dfuhelper\t\t\t\tExit after entering DFU\n"
"\t-e, --boot-args <boot arguments>\tXNU boot arguments\n"
"\t-E, --enter-recovery\t\t\tEnter recovery mode\n"
#ifdef ROOTFUL
"\t-f, --fakefs \t\t\t\tBoots fakefs\n"
#endif
"\t-h, --help\t\t\t\tShow this help\n"
"\t-i, --override-checkra1n <file>\t\tOverride checkra1n\n"
"\t-k, --override-pongo <file>\t\tOverride Pongo image\n"
"\t-K, --override-kpf <file>\t\tOverride kernel patchfinder\n"
#ifdef ROOTFUL
"\t-l, --rootless\t\t\t\tBoots rootless. This is the default\n"
#endif
"\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-I, --device-info\t\t\tPrint info about the connected device\n"
"\t-o, --override-overlay <file>\t\tOverride overlay\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 <file>\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-S, --no-colors\t\t\t\tDisable colors on the command line\n"
"\t-T, --telnetd\t\t\t\tEnable TELNET daemon on port 46 (insecure)\n"
"\t-v, --debug-logging\t\t\tEnable debug logging\n"
"\t\tThis option can be repeated for extra verbosity.\n"
"\t-V, --verbose-boot\t\t\tVerbose boot\n"
#ifdef TUI
"\t-t, --tui\t\t\t\tForce interactive TUI\n"
"\t--cli\t\t\t\t\tForce cli mode\n"
#endif
"\nEnvironmental variables:\n"
"\tTMPDIR\t\ttemporary diretory (path the built-in checkra1n will be extracted to)\n"
,
prog_name);
exit(e);
}
int optparse(int argc, char* argv[]) {
int opt;
int index;
while ((opt = getopt_long(argc, argv,
"DEhpvVlLdsSTtRnPIe:o:r:K:k:i:"
#ifdef DEV_BUILD
"12"
#endif
#ifdef ROOTFUL
"fCcB"
#endif
,longopts, NULL)) != -1)
{
switch (opt) {
#ifdef ROOTFUL
case 'B':
palerain_flags |= palerain_option_setup_partial_root;
palerain_flags |= palerain_option_setup_rootful;
break;
case 'c':
palerain_flags |= palerain_option_setup_rootful;
break;
case 'C':
palerain_flags |= palerain_option_clean_fakefs;
break;
#endif
case 'p':
palerain_flags |= palerain_option_pongo_exit;
break;
case 'P':
palerain_flags |= palerain_option_pongo_full;
break;
case 'D':
palerain_flags |= palerain_option_dfuhelper_only;
break;
case 'h':
usage(0, argv[0]);
assert(0);
case 'v':
verbose++;
break;
case 'V':
palerain_flags |= palerain_option_verbose_boot;
#ifdef TUI
tui_options_verbose_boot = true;
#endif
break;
case 'e':
if (strlen(optarg) > (sizeof(xargs_cmd) - 0x20)) {
LOG(LOG_FATAL, "Boot arguments too long");
return -1;
}
snprintf(xargs_cmd, sizeof(xargs_cmd), "xargs %s", optarg);
#ifdef TUI
snprintf(tui_options_boot_args, sizeof(tui_options_boot_args), "%s", optarg);
#endif
break;
#ifdef ROOTFUL
case 'f':
palerain_flags |= palerain_option_rootful;
palerain_flags &= ~palerain_option_rootless;
break;
#endif
case 'l':
palerain_flags &= ~palerain_option_rootful;
palerain_flags |= palerain_option_rootless;
break;
case 'L':
palerain_flags |= palerain_option_jbinit_log_to_file;
break;
case 'd':
palerain_flags |= palerain_option_demote;
break;
case 'E':
palerain_flags |= palerain_option_enter_recovery;
break;
case 's':
palerain_flags |= palerain_option_safemode;
#ifdef TUI
tui_options_safe_mode = true;
#endif
break;
case 'T':
palerain_flags |= palerain_option_telnetd;
break;
case 'k':
if (access(optarg, F_OK) != 0) {
LOG(LOG_FATAL, "Cannot access pongo file at %s: %d (%s)", optarg, errno, strerror(errno));
return -1;
}
pongo_path = malloc(strlen(optarg) + 1);
if (pongo_path == NULL) {
LOG(LOG_FATAL, "memory allocation failed");
return -1;
}
snprintf(pongo_path, strlen(optarg) + 1, "%s", optarg);
break;
case 'o':
if (override_file(&override_overlay, overlay_to_upload, &binpack_dmg_len, optarg))
return 1;
break;
case 'r':
if (override_file(&override_ramdisk, ramdisk_to_upload, &ramdisk_dmg_lzma_len, optarg))
return 1;
break;
case 'K':
if (override_file(&override_kpf, kpf_to_upload, &checkra1n_kpf_pongo_lzma_len, optarg))
return 1;
struct mach_header_64* hdr = (struct mach_header_64*)override_kpf.ptr;
if (hdr->magic != MH_MAGIC_64 && hdr->magic != MH_CIGAM_64) {
LOG(LOG_FATAL, "Invalid kernel patchfinder: Not thin 64-bit Mach-O");
return -1;
} else if (hdr->filetype != MH_KEXT_BUNDLE) {
LOG(LOG_FATAL, "Invalid kernel patchfinder: Not a kext bundle");
return -1;
} else if (hdr->cputype != CPU_TYPE_ARM64) {
LOG(LOG_FATAL, "Invalid kernel patchfinder: CPU type is not arm64");
return -1;
}
break;
case 'i': {};
struct stat st;
if (stat(optarg, &st) != 0) {
LOG(LOG_FATAL, "cannot stat external checkra1n file: %d (%s)", errno, strerror(errno));
return -1;
} else if (!(st.st_mode & S_IXUSR) && !(st.st_mode & S_IXGRP) && !(st.st_mode & S_IXOTH)) {
LOG(LOG_FATAL, "%s is not executable", optarg);
return -1;
} else if (!S_ISREG(st.st_mode)) {
LOG(LOG_FATAL, "%s is not a regular file", optarg);
return -1;
}
if (st.st_size < (UCHAR_MAX+1)) {
LOG(LOG_FATAL, "%s too small", optarg);
return -1;
}
int checkra1n_fd = open(optarg, O_RDONLY);
if (checkra1n_fd == -1) {
LOG(LOG_FATAL, "Cannot open %s: %d (%s)", optarg, errno, strerror(errno));
return -1;
}
void* addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, checkra1n_fd, 0);
if (addr == MAP_FAILED) {
LOG(LOG_ERROR, "Failed to map file %s: %d (%s)", optarg, errno, strerror(errno));
return -1;
}
if (boyermoore_horspool_memmem(addr, st.st_size, (const unsigned char*)"[ra1npoc15-part] thanks to", strlen("[ra1npoc15-part] thanks to")) != NULL)
{
palerain_flags |= palerain_option_checkrain_is_clone;
LOG(LOG_VERBOSE3, "%s is checkra1n clone", optarg);
}
else
{
palerain_flags &= ~palerain_option_checkrain_is_clone;
LOG(LOG_VERBOSE3, "%s is checkra1n", optarg);
}
munmap(addr, st.st_size);
close(checkra1n_fd);
ext_checkra1n = calloc(1, strlen(optarg) + 1);
snprintf(ext_checkra1n, strlen(optarg) + 1, "%s", optarg);
break;
case 'R':
palerain_flags |= palerain_option_reboot_device;
break;
case 'n':
palerain_flags |= palerain_option_exit_recovery;
break;
case 'I':
palerain_flags |= palerain_option_device_info;
break;
case 'S':
palerain_flags |= palerain_option_no_colors;
break;
#ifdef TUI
case 't':
palerain_flags |= palerain_option_tui;
break;
#endif
case palerain_option_case_cli:
palerain_flags |= palerain_option_cli;
break;
#ifdef DEV_BUILD
case '1':
palerain_flags |= palerain_option_test1;
break;
case '2':
palerain_flags |= palerain_option_test2;
break;
#endif
case palerain_option_case_force_revert:
palerain_flags |= palerain_option_force_revert;
#ifdef TUI
tui_options_force_revert = true;
#endif
break;
case palerain_option_case_version:
palerain_flags |= palerain_option_palerain_version;
break;
case palerain_option_case_libcheckra1nhelper_path:
printf("meow\n");
gOverrideLibcheckra1nHelper = calloc(1, strlen(optarg) + 1);
if (!gOverrideLibcheckra1nHelper) {
return -1;
}
snprintf(gOverrideLibcheckra1nHelper, strlen(optarg) + 1, "%s", optarg);
break;
default:
usage(1, argv[0]);
break;
}
}
if ((palerain_flags & palerain_option_palerain_version)) {
printf(
"palera1n " PALERAIN_VERSION "\n"
BUILD_COMMIT " " BUILD_NUMBER " (" BUILD_BRANCH ")\n\n"
"Build style: " BUILD_STYLE "\n"
"Build tag: " BUILD_TAG "\n"
#ifdef USE_LIBUSB
"USB backend: libusb\n"
#else
"USB backend: IOKit\n"
#endif
"Build options: " BUILD_OPTIONS "\n"
);
return 0;
}
if (palerain_flags & palerain_option_telnetd) {
LOG(LOG_WARNING, "telnetd is enabled, this is a security hole");
}
if ((palerain_flags & (palerain_option_tui)) && (palerain_flags & (palerain_option_cli))) {
LOG(LOG_FATAL, "cannot specify both --tui and --cli");
return -1;
}
if ((palerain_flags & (palerain_option_exit_recovery | palerain_option_enter_recovery | palerain_option_reboot_device | palerain_option_device_info | palerain_option_dfuhelper_only | palerain_option_pongo_exit | palerain_option_pongo_full)) > 0) {
palerain_flags &= ~palerain_option_tui;
palerain_flags |= palerain_option_cli;
} else {
#ifdef ROOTFUL
if ((palerain_flags & (palerain_option_rootless | palerain_option_rootful)) == 0) {
LOG(LOG_FATAL, "Please specify rootful (-f) or rootless (-l)");
return -1;
}
#else
palerain_flags |= palerain_option_rootless;
#endif
}
snprintf(palerain_flags_cmd, 0x30, "palera1n_flags 0x%" PRIx64, palerain_flags);
LOG(LOG_VERBOSE3, "palerain_flags: %s", palerain_flags_cmd);
if (override_kpf.magic == OVERRIDE_MAGIC) {
LOG(LOG_VERBOSE4, "kpf override length %" PRIu32 " -> %" PRIu32, override_kpf.orig_len, checkra1n_kpf_pongo_lzma_len);
LOG(LOG_VERBOSE4, "kpf override ptr %p -> %p", override_kpf.orig_ptr, **kpf_to_upload);
}
if (override_ramdisk.magic == OVERRIDE_MAGIC) {
LOG(LOG_VERBOSE4, "ramdisk override length %" PRIu32 " -> %" PRIu32, override_ramdisk.orig_len, ramdisk_dmg_lzma_len);
LOG(LOG_VERBOSE4, "ramdisk override ptr %p -> %p", override_ramdisk.orig_ptr, **ramdisk_to_upload);
}
if (override_overlay.magic == OVERRIDE_MAGIC) {
LOG(LOG_VERBOSE4, "overlay override length %" PRIu32 " -> %" PRIu32, override_overlay.orig_len, binpack_dmg_len);
LOG(LOG_VERBOSE4, "overlay override ptr %p -> %p", override_overlay.orig_ptr, **overlay_to_upload);
}
#ifdef ROOTFUL
if (!(palerain_flags & palerain_option_rootful)) {
if ((palerain_flags & palerain_option_setup_rootful)) {
LOG(LOG_FATAL, "Cannot setup rootful when rootless is requested. Use -f to enable rootful mode.");
return -1;
}
}
#endif
if (!(
(palerain_flags & palerain_option_dfuhelper_only) ||
(palerain_flags & palerain_option_enter_recovery) ||
(palerain_flags & palerain_option_exit_recovery) ||
(palerain_flags & palerain_option_reboot_device)))
{
#ifdef NO_CHECKRAIN
if (checkra1n_len == 0 && ext_checkra1n == NULL)
{
LOG(LOG_FATAL, "checkra1n omitted in build but no override specified");
return -1;
}
if (!((palerain_flags & palerain_option_pongo_exit) || (palerain_flags & palerain_option_pongo_exit)))
{
#ifdef NO_KPF
if (checkra1n_kpf_pongo_lzma_len == 0)
{
LOG(LOG_FATAL, "kernel patchfinder omitted in build but no override specified");
return -1;
}
#endif
}
#endif
#ifdef NO_EMBED_HELPER
if (libcheckra1nhelper_dylib_len == 0 && gOverrideLibcheckra1nHelper == NULL) {
LOG(LOG_FATAL, "checkra1n helper omitted in build but no override specified");
return -1;
}
#endif
}
for (index = optind; index < argc; index++)
{
if (!strcmp("windows", argv[index]))
{
fprintf(stderr,
"Windows not really using for manipulating OSX images,\n"
"compiled in mingw tool for this working unstable and incorrectly\n");
return -2;
}
else
{
fprintf(stderr, "%s: unknown argument: %s\n", argv[0], argv[index]);
usage(1, argv[0]);
}
}
if (verbose >= 2) setenv("LIBUSB_DEBUG", "1", 1);
if (verbose >= 3)
{
libusbmuxd_set_debug_level(verbose - 2);
irecv_set_debug_level(1);
setenv("LIBUSB_DEBUG", "2", 1);
}
if (verbose >= 4) {
idevice_set_debug_level(1);
setenv("LIBUSB_DEBUG", "3", 1);
}
if (verbose >= 5)
setenv("LIBUSB_DEBUG", "4", 1);
return 0;
}
-50
View File
@@ -1,50 +0,0 @@
#include <palerain.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>
#include <assert.h>
#include <getopt.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/stat.h>
int override_file(override_file_t *finfo, niarelap_file_t** orig, unsigned int *orig_len, char *filename) {
int ret = 0;
int fd = open(filename, O_RDONLY);
LOG(LOG_VERBOSE5, "override_file() called!");
if (fd == -1) {
LOG(LOG_ERROR, "Cannot open file %s: %d (%s)", filename, errno, strerror(errno));
return errno;
}
LOG(LOG_VERBOSE5, "override_file: opened %s!", filename);
struct stat st;
ret = fstat(fd, &st);
if (ret) {
LOG(LOG_ERROR, "Cannot fstat fd from file %s: %d (%s)", filename, errno, strerror(errno));
return errno;
}
LOG(LOG_VERBOSE5, "override_file: fstat fd %d succeeded!", fd);
void *addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) {
LOG(LOG_ERROR, "Failed to map file %s: %d (%s)", filename, errno, strerror(errno));
return errno;
}
LOG(LOG_VERBOSE5, "override_file: Override file mapped successfully");
finfo->magic = OVERRIDE_MAGIC;
finfo->fd = fd;
finfo->len = (unsigned int)st.st_size;;
finfo->ptr = *(niarelap_file_t*)addr;
finfo->orig_len = *orig_len;
finfo->orig_ptr = **orig;
*orig = (niarelap_file_t*)addr;
*orig_len = (unsigned int)st.st_size;
LOG(LOG_VERBOSE5, "override_file() finished!");
return 0;
}
-283
View File
@@ -1,283 +0,0 @@
#include <errno.h>
#include <fcntl.h> // open
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> // exit, strtoull
#include <string.h> // strlen, strerror, memcpy, memmove
#include <unistd.h> // close
#include <sys/mman.h> // mmap, munmap
#include <sys/stat.h> // fstst
#include <palerain.h>
#ifdef TUI
#include <tui.h>
#endif
#include <ANSI-color-codes.h>
bool device_has_booted = 0;
int pongo_thr_running = 0;
#define ERR(...) LOG(LOG_VERBOSE, __VA_ARGS__)
static int issue_pongo_command(usb_device_handle_t, char*);
static int upload_pongo_file(usb_device_handle_t, unsigned char*, unsigned int);
static void write_stdout(char *buf, uint32_t len);
void* pongo_helper(void* ptr) {
pongo_thr_running = 1;
pthread_cleanup_push(thr_cleanup, &pongo_thr_running);
wait_for_pongo();
while (get_spin()) {
sleep(1);
}
pthread_cleanup_pop(1);
return NULL;
}
static void *pongo_usb_callback(stuff_t *arg) {
if (get_found_pongo())
return NULL;
set_found_pongo(1);
#ifdef ROOTFUL
if ((palerain_flags & palerain_option_setup_rootful)) {
strncat(xargs_cmd, " wdt=-1", 0x270 - strlen(xargs_cmd) - 1);
}
#endif
LOG(LOG_INFO, "Found PongoOS USB Device");
if (palerain_flags & palerain_option_pongo_exit)
goto done;
usb_device_handle_t handle = arg->handle;
#ifdef TUI
if (tui_is_jailbreaking) {
tui_jailbreak_stage = 4;
tui_jailbreak_status = "Sending PongoOS commands";
tui_jailbreak_status_changed();
}
#endif
issue_pongo_command(handle, NULL);
issue_pongo_command(handle, "fuse lock");
issue_pongo_command(handle, "sep auto");
#ifdef TUI
if (tui_is_jailbreaking) {
tui_jailbreak_stage = 5;
tui_jailbreak_status = "Sending KPF";
tui_jailbreak_status_changed();
}
#endif
upload_pongo_file(handle, **kpf_to_upload, checkra1n_kpf_pongo_lzma_len);
if (*kpf_to_upload == &checkra1n_kpf_pongo_lzma) {
issue_pongo_command(handle, "modload " KPF_UNCOMPRESSED_SIZE);
} else {
issue_pongo_command(handle, "modload");
}
issue_pongo_command(handle, palerain_flags_cmd);
#ifdef NO_RAMDISK
if (ramdisk_dmg_lzma_len != 0)
#endif
{
#ifdef TUI
if (tui_is_jailbreaking) {
tui_jailbreak_stage = 6;
tui_jailbreak_status = "Sending ramdisk";
tui_jailbreak_status_changed();
}
#endif
upload_pongo_file(handle, **ramdisk_to_upload, ramdisk_dmg_lzma_len);
if ((*ramdisk_to_upload) == &ramdisk_dmg_lzma)
issue_pongo_command(handle, "ramdisk " RAMDISK_UNCOMPRESSED_SIZE);
else {
issue_pongo_command(handle, "ramdisk");
}
}
#ifdef NO_OVERLAY
if (binpack_dmg_len != 0)
#endif
{
#ifdef TUI
if (tui_is_jailbreaking) {
tui_jailbreak_stage = 7;
tui_jailbreak_status = "Sending binpack";
tui_jailbreak_status_changed();
}
#endif
upload_pongo_file(handle, **overlay_to_upload, binpack_dmg_len);
issue_pongo_command(handle, "overlay");
}
issue_pongo_command(handle, xargs_cmd);
if ((palerain_flags & palerain_option_pongo_full)) goto done;
#ifdef TUI
if (tui_is_jailbreaking) {
tui_jailbreak_stage = 8;
tui_jailbreak_status = "Booting";
tui_jailbreak_status_changed();
}
#endif
issue_pongo_command(handle, "bootx");
LOG(LOG_INFO, "Booting Kernel...");
#ifdef ROOTFUL
if ((palerain_flags & palerain_option_setup_partial_root)) {
LOG(LOG_INFO, "Please wait up to 5 minutes for the bindfs to be created.");
LOG(LOG_INFO, "Once the device reboots into recovery mode, run again without the -B (Create BindFS) option to jailbreak.");
} else if ((palerain_flags & palerain_option_setup_rootful)) {
LOG(LOG_INFO, "Please wait up to 10 minutes for the fakefs to be created.");
LOG(LOG_INFO, "Once the device reboots into recovery mode, run again without the -c (Create FakeFS) option to jailbreak.");
}
#endif
if (dfuhelper_thr_running) {
pthread_cancel(dfuhelper_thread);
dfuhelper_thr_running = false;
}
done:
device_has_booted = true;
#ifdef TUI
if (tui_is_jailbreaking) {
tui_jailbreak_stage = 9;
tui_jailbreak_status = "All Done";
tui_is_jailbreaking = false;
tui_jailbreak_status_changed();
}
#endif
#ifdef USE_LIBUSB
libusb_unref_device(arg->dev);
#endif
set_spin(0);
return NULL;
}
static int issue_pongo_command(usb_device_handle_t handle, char *command)
{
uint32_t outpos = 0;
uint32_t outlen = 0;
int ret = USB_RET_SUCCESS;
uint8_t in_progress = 1;
if (command == NULL) goto fetch_output;
size_t len = strlen(command);
char command_buf[512];
char stdout_buf[0x2000];
if (len > (CMD_LEN_MAX - 2))
{
LOG(LOG_ERROR, "Pongo command %s too long (max %d)", command, CMD_LEN_MAX - 2);
return EINVAL;
}
if (verbose < 3 || verbose > 4) {
LOG(LOG_VERBOSE, "Executing PongoOS command: '%s'", command);
} else {
printf("%s\n", command);
}
snprintf(command_buf, 512, "%s\n", command);
len = strlen(command_buf);
ret = USBControlTransfer(handle, 0x21, 4, 1, 0, 0, NULL, NULL);
if (ret)
goto bad;
ret = USBControlTransfer(handle, 0x21, 3, 0, 0, (uint32_t)len, command_buf, NULL);
fetch_output:
while (in_progress) {
ret = USBControlTransfer(handle, 0xa1, 2, 0, 0, (uint32_t)sizeof(in_progress), &in_progress, NULL);
if (ret == USB_RET_SUCCESS)
{
ret = USBControlTransfer(handle, 0xa1, 1, 0, 0, 0x1000, stdout_buf + outpos, &outlen);
if (ret == USB_RET_SUCCESS)
{
write_stdout(stdout_buf + outpos, outlen);
outpos += outlen;
if (outpos > 0x1000)
{
memmove(stdout_buf, stdout_buf + outpos - 0x1000, 0x1000);
outpos = 0x1000;
}
}
}
if (ret != USB_RET_SUCCESS)
{
goto bad;
}
}
bad:
if (ret != USB_RET_SUCCESS)
{
if (command != NULL && (!strncmp("boot", command, 4))) {
if (ret == USB_RET_IO || ret == USB_RET_NO_DEVICE || ret == USB_RET_NOT_RESPONDING)
return 0;
}
LOG(LOG_ERROR, "USB error: %s", usb_strerror(ret));
return ret;
}
else
return ret;
}
static int upload_pongo_file(usb_device_handle_t handle, unsigned char *buf, unsigned int buf_len)
{
int ret = 0;
ret = USBControlTransfer(handle, 0x21, 1, 0, 0, 4, &buf_len, NULL);
if (ret == USB_RET_SUCCESS)
{
ret = USBBulkUpload(handle, buf, buf_len);
if (ret == USB_RET_SUCCESS)
{
if (verbose < 3 || verbose > 4) {
LOG(LOG_VERBOSE, "Uploaded %llu bytes to PongoOS", (unsigned long long)buf_len);
} else {
if ((palerain_flags & palerain_option_no_colors))
printf("/send mem:%p:%p\n[Uploaded %llu bytes]\n", (void*)buf, (void*)(buf + buf_len), (unsigned long long)buf_len);
else
printf("/send mem:%p:%p\n" BCYN "[Uploaded %llu bytes]\n" CRESET, (void*)buf, (void*)(buf + buf_len), (unsigned long long)buf_len);
}
}
}
if (verbose >= 3) printf("pongoOS> ");
return ret;
}
void io_start(stuff_t *stuff)
{
int r = pthread_create(&stuff->th, NULL, (pthread_start_t)pongo_usb_callback, stuff);
if(r != 0)
{
ERR("pthread_create: %s", strerror(r));
set_spin(0);
return;
}
pthread_join(stuff->th, NULL);
}
void io_stop(stuff_t *stuff)
{
int r = pthread_cancel(stuff->th);
if(r != 0)
{
ERR("pthread_cancel: %s", strerror(r));
set_spin(0);
return;
}
r = pthread_join(stuff->th, NULL);
if(r != 0)
{
ERR("pthread_join: %s", strerror(r));
set_spin(0);
return;
}
#ifdef USE_LIBUSB
libusb_unref_device(stuff->dev);
#endif
}
static void write_stdout(char *buf, uint32_t len)
{
while(len > 0) {
if (verbose >= 3) {
ssize_t s = write(1, buf, len);
if(s < 0) {
LOG(LOG_ERROR, "write: %s", strerror(errno));
pthread_exit(NULL);
}
buf += s;
len -= s;
} else break;
}
}
-2
View File
@@ -1,2 +0,0 @@
*
!.gitignore
-220
View File
@@ -1,220 +0,0 @@
#ifdef TUI
#include <palerain.h>
#include <tui.h>
static irecv_device_t tui_get_recovery_device(uint64_t ecid) {
irecv_client_t client = NULL;
for (int i = 0; i <= 5; i++) {
irecv_error_t err = irecv_open_with_ecid(&client, ecid);
if (err == IRECV_E_UNSUPPORTED) {
return NULL;
}
else if (err != IRECV_E_SUCCESS)
sleep(1);
else
break;
if (i == 5) {
return NULL;
}
}
irecv_device_t device = NULL;
irecv_devices_get_device_by_client(client, &device);
irecv_close(client);
return device;
}
struct tui_connected_device *tui_connected_devices = NULL;
static void* tui_connected_recovery_mode(struct irecv_device_info* info) {
//printf("Recovery mode device %" PRIu64 " connected\n", info->ecid);
tui_last_event = TUI_EVENT_CONNECTED_DEVICES_CHANGED;
sem_post(tui_event_semaphore);
pthread_exit(NULL);
return NULL;
}
static void* tui_disconnected_recovery_mode(struct irecv_device_info* info) {
//printf("Recovery mode device %" PRIu64 " disconnected\n", info->ecid);
tui_last_event = TUI_EVENT_CONNECTED_DEVICES_CHANGED;
sem_post(tui_event_semaphore);
pthread_exit(NULL);
return NULL;
}
static void* tui_connected_dfu_mode(struct irecv_device_info* info) {
//printf("DFU mode device %" PRIu64 " connected\n", info->ecid);
tui_last_event = TUI_EVENT_CONNECTED_DEVICES_CHANGED;
sem_post(tui_event_semaphore);
pthread_exit(NULL);
return NULL;
}
static void* tui_disconnected_dfu_mode(struct irecv_device_info* info) {
//printf("DFU mode device %" PRIu64 " disconnected\n", info->ecid);
tui_last_event = TUI_EVENT_CONNECTED_DEVICES_CHANGED;
sem_post(tui_event_semaphore);
pthread_exit(NULL);
return NULL;
}
static int tui_connected_normal_mode(const usbmuxd_device_info_t *usbmuxd_device) {
struct tui_connected_device *tui_dev = malloc(sizeof(struct tui_connected_device));
snprintf(tui_dev->udid, sizeof(tui_dev->udid), "%s", usbmuxd_device->udid);
tui_dev->next = tui_connected_devices;
tui_dev->mode = TUI_DEVICE_MODE_NORMAL;
tui_connected_devices = tui_dev;
devinfo_t dev;
int ret;
ret = devinfo_cmd(&dev, usbmuxd_device->udid);
if (ret != 0) {
LOG(LOG_ERROR, "Unable to get device information");
free(tui_dev);
return 0;
}
snprintf(tui_dev->product_type, sizeof(tui_dev->product_type), "%s", dev.productType);
snprintf(tui_dev->display_name, sizeof(tui_dev->display_name), "%s", dev.displayName);
tui_dev->ecid = dev.ecid;
if (strncmp(dev.CPUArchitecture, "arm64", strlen("arm64"))) {
tui_dev->arm64 = false;
} else {
tui_dev->arm64 = true;
}
snprintf(tui_dev->version, sizeof(tui_dev->version), "%s", dev.productVersion);
if (!strncmp(dev.productType, "iPhone10,", strlen("iPhone10,"))) {
tui_dev->requires_passcode_disabled = true;
unsigned char passcode_state = 0;
ret = passstat_cmd(&passcode_state, usbmuxd_device->udid);
if (ret != 0) {
LOG(LOG_ERROR, "Failed to get passcode state");
devinfo_free(&dev);
free(tui_dev);
return -1;
}
tui_dev->passcode_state = passcode_state;
}
//enter_recovery_cmd(usbmuxd_device->udid);
devinfo_free(&dev);
tui_last_event = TUI_EVENT_CONNECTED_DEVICES_CHANGED;
sem_post(tui_event_semaphore);
return 0;
}
static void tui_disconnected_normal_mode(const usbmuxd_device_info_t *usbmuxd_device) {
struct tui_connected_device *cur = tui_connected_devices;
struct tui_connected_device *prev = NULL;
while (cur) {
if (!strcmp(cur->udid, usbmuxd_device->udid)) {
if (prev) {
prev->next = cur->next;
} else {
tui_connected_devices = cur->next;
}
free(cur);
break;
}
prev = cur;
cur = cur->next;
}
tui_last_event = TUI_EVENT_CONNECTED_DEVICES_CHANGED;
sem_post(tui_event_semaphore);
}
static void tui_device_event_cb(const usbmuxd_event_t *event, void* userdata) {
if (event->device.conn_type != CONNECTION_TYPE_USB) return;
switch (event->event) {
case UE_DEVICE_ADD:
LOG(LOG_VERBOSE, "Normal mode device connected");
tui_connected_normal_mode(&event->device);
break;
case UE_DEVICE_REMOVE:
LOG(LOG_VERBOSE, "Normal mode device disconnected");
tui_disconnected_normal_mode(&event->device);
break;
}
}
static void tui_irecv_device_event_cb(const irecv_device_event_t *event, void* userdata) {
pthread_t recovery_thread, dfu_thread;
int ret;
switch(event->type) {
case IRECV_DEVICE_ADD: {
struct tui_connected_device *dev = malloc(sizeof(struct tui_connected_device));
dev->ecid = event->device_info->ecid;
dev->next = tui_connected_devices;
dev->arm64 = cpid_is_arm64(event->device_info->cpid);
/*recvinfo_t info;
ret = recvinfo_cmd(&info, event->device_info->ecid);
if (ret) {
LOG(LOG_WARNING, "Could not get info from device");
} else {
snprintf(dev->product_type, sizeof(dev->product_type), "%s", info.product_type);
snprintf(dev->display_name, sizeof(dev->display_name), "%s", info.display_name);
}*/
irecv_device_t device = tui_get_recovery_device(event->device_info->ecid);
if (!device) {
LOG(LOG_WARNING, "Could not get info from device");
free(dev);
return;
}
snprintf(dev->product_type, sizeof(dev->product_type), "%s", device->product_type);
snprintf(dev->display_name, sizeof(dev->display_name), "%s", device->display_name);
dev->cpid = device->chip_id;
tui_connected_devices = dev;
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) {
dev->mode = TUI_DEVICE_MODE_RECOVERY;
pthread_create(&recovery_thread, NULL, (pthread_start_t)tui_connected_recovery_mode, event->device_info);
} else if (event->mode == IRECV_K_DFU_MODE) {
dev->mode = TUI_DEVICE_MODE_DFU;
pthread_create(&dfu_thread, NULL, (pthread_start_t)tui_connected_dfu_mode, event->device_info);
}
break;
}
case IRECV_DEVICE_REMOVE: {
struct tui_connected_device *cur = tui_connected_devices;
struct tui_connected_device *prev = NULL;
while (cur) {
if (cur->ecid == event->device_info->ecid) {
if (prev) {
prev->next = cur->next;
} else {
tui_connected_devices = cur->next;
}
if (cur->mode == TUI_DEVICE_MODE_RECOVERY) {
LOG(LOG_VERBOSE, "Recovery mode device %" PRIu64 " disconnected", event->device_info->ecid);
pthread_create(&recovery_thread, NULL, (pthread_start_t)tui_disconnected_recovery_mode, event->device_info);
} else if (cur->mode == TUI_DEVICE_MODE_DFU) {
LOG(LOG_VERBOSE, "DFU mode device %" PRIu64 " disconnected", event->device_info->ecid);
pthread_create(&dfu_thread, NULL, (pthread_start_t)tui_disconnected_dfu_mode, event->device_info);
}
free(cur);
break;
}
prev = cur;
cur = cur->next;
}
break;
}
}
}
void tui_devhelper(void) {
subscribe_cmd(tui_device_event_cb, tui_irecv_device_event_cb);
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
-166
View File
@@ -1,166 +0,0 @@
#ifdef TUI
#include <tui.h>
#ifdef __linux__
#include <gpm.h>
#endif
int tui_mouse_x = 0;
int tui_mouse_y = 0;
int tui_mouse_button = -1;
int tui_last_event = -1;
int tui_last_input = -1;
sem_t *tui_event_semaphore;
char tui_last_key = 0;
#ifdef __linux__
bool using_gpm = false;
#endif
int tui_get_input(void) {
char c = getc(stdin);
if (c == '\x1b' && getc(stdin) == '[') {
char c3 = getc(stdin);
switch (c3) {
case 'D':
return TUI_INPUT_LEFT;
case 'C':
return TUI_INPUT_RIGHT;
case 'A':
return TUI_INPUT_UP;
case 'B':
return TUI_INPUT_DOWN;
case 'Z':
return TUI_INPUT_TAB_BACK;
case 'M': {
char c4 = getc(stdin);
char c5 = getc(stdin);
char c6 = getc(stdin);
int new_mouse_x = c5 - 33;
if (new_mouse_x < 0) new_mouse_x += 256;
int new_mouse_y = c6 - 33;
if (new_mouse_y < 0) new_mouse_y += 256;
int mouse_button = c4 & 3;
if (tui_mouse_x != new_mouse_x || tui_mouse_y != new_mouse_y) {
tui_mouse_x = new_mouse_x;
tui_mouse_y = new_mouse_y;
return TUI_INPUT_MOUSE_MOVE;
}
if (tui_mouse_button != (c4 & 1)) {
tui_mouse_button = c4 & 1;
if (tui_mouse_button == 0) {
return TUI_INPUT_MOUSE_DOWN;
} else {
return TUI_INPUT_MOUSE_UP;
}
}
break;
}
}
}
tui_last_key = c;
if (c == '\x0d' || c == ' ') {
return TUI_INPUT_SELECT;
}
if (c == '\t') {
return TUI_INPUT_TAB;
}
if (c == '\x7f') {
return TUI_INPUT_BACKSPACE;
}
if (c == '\x1b') {
return TUI_INPUT_ESCAPE;
}
return TUI_INPUT_NONE;
}
#ifdef __linux__
void *tui_gpm_thread(void *arg) {
Gpm_Event event;
while (1) {
if (Gpm_GetEvent(&event) == -1) {
exit(1);
}
tui_mouse_x = event.x - 1;
tui_mouse_y = event.y - 1;
if (event.type & GPM_MOVE) {
tui_last_event = TUI_EVENT_INPUT;
tui_last_input = TUI_INPUT_MOUSE_MOVE;
sem_post(tui_event_semaphore);
}
if (event.buttons & 4) {
if (event.type & GPM_DOWN) {
tui_mouse_button = 1;
tui_last_event = TUI_EVENT_INPUT;
tui_last_input = TUI_INPUT_MOUSE_DOWN;
sem_post(tui_event_semaphore);
} else if (event.type & GPM_UP) {
tui_mouse_button = 0;
tui_last_event = TUI_EVENT_INPUT;
tui_last_input = TUI_INPUT_MOUSE_UP;
sem_post(tui_event_semaphore);
}
continue;
}
}
}
#endif
void *tui_input_thread(void *arg) {
#ifdef __linux__
if (strncmp(getenv("TERM"), "linux", 5) == 0) {
Gpm_Connect conn;
Gpm_Event event;
conn.eventMask = GPM_UP | GPM_DOWN;
conn.defaultMask = ~0;
conn.minMod = 0;
conn.maxMod = 0xffff;
if (Gpm_Open(&conn, 0) != -1) {
using_gpm = true;
pthread_t gpm_thread;
pthread_create(&gpm_thread, NULL, tui_gpm_thread, NULL);
}
}
#endif
while (1) {
int input = tui_get_input();
tui_last_event = TUI_EVENT_INPUT;
tui_last_input = input;
sem_post(tui_event_semaphore);
}
return 0;
}
int tui_get_event(void) {
sem_wait(tui_event_semaphore);
int last_event = tui_last_event;
tui_last_event = -1;
return last_event;
}
int tui_try_get_event(void) {
int ret = sem_trywait(tui_event_semaphore);
if (ret == 0) {
int last_event = tui_last_event;
tui_last_event = -1;
return last_event;
}
return -1;
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
-256
View File
@@ -1,256 +0,0 @@
#ifdef TUI
#ifdef __APPLE__
#define _DARWIN_C_SOURCE
#else
#define _DEFAULT_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#include <time.h>
#include <palerain.h>
#include <tui.h>
#ifdef __APPLE__
int proc_pidpath(int pid, void * buffer, uint32_t buffersize);
char random_sem_name[sizeof("palera1n.tui_event_semaphore") + 16 + 1];
#endif
static int tui_state = 0;
int tui_x_offset = 0;
int tui_y_offset = 0;
bool supports_bright_colors = true;
static struct termios saved_termios;
int redraw_screen(void) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
CLEAR_SCREEN;
MOVETO(0, 0);
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
if (w.ws_col < 80 || w.ws_row < 24) {
LOG(LOG_FATAL, "Terminal size must be at least 80x24");
printf("\033[37;41mERROR: Terminal size must be at least 80x24!");
fflush(stdout);
return -1;
}
tui_y_offset = (w.ws_row - 24) / 2;
for (int i = 0; i < tui_y_offset; i++) {
printf("\n");
}
tui_x_offset = (w.ws_col - 80) / 2;
const char* tui_version = TUI_VERSION;
if (tui_version[0] == 'v') tui_version++;
tui_draw_rectangle(0, 0, 79, 23);
MOVETOT((int)(80 - (strlen("[palera1n - Version ]") + strlen(tui_version) ) - 1), 1);
printf("[palera1n - Version %s]", tui_version);
SETCOLOR(FG_WHITE, BG_BLACK);
switch(tui_state) {
case MAIN_SCREEN:
tui_screen_main_redraw();
break;
case OPTIONS_SCREEN:
tui_screen_options_redraw();
break;
case ENTER_RECOVERY_SCREEN:
tui_screen_enter_recovery_redraw();
break;
case ENTER_DFU_SCREEN:
tui_screen_enter_dfu_redraw();
break;
case JAILBREAK_SCREEN:
tui_screen_jailbreak_redraw();
break;
}
fflush(stdout);
return 0;
}
static int destroy_window(void) {
if (!tui_started) return 0;
tui_started = false;
tcsetattr(STDIN_FILENO, 0, &saved_termios);
MOUSEOFF;
CLEAR_SCREEN;
MOVETO(0, 0);
RMCUP;
CNORM;
return 0;
}
static int init_window(void) {
setlocale(LC_ALL, NULL);
tui_started = true;
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
if (w.ws_col < 80 || w.ws_row < 24) {
tui_started = false;
LOG(LOG_FATAL, "Terminal size must be at least 80x24");
return -1;
}
LOG(LOG_VERBOSE3, "cols: %d, rows: %d\n", w.ws_col, w.ws_row);
SMCUP;
CIVIS;
fflush(stdout);
struct termios term;
tcgetattr(STDIN_FILENO, &term);
tcgetattr(STDIN_FILENO, &saved_termios);
cfmakeraw(&term);
term.c_lflag |= ISIG;
tcsetattr(STDIN_FILENO, 0, &term);
MOUSEON;
return 0;
}
bool tui_is_restarting = false;
extern int saved_argc;
extern char** saved_argv;
extern char** saved_envp;
void tui_terminate(int sig) {
destroy_window();
if (tui_is_restarting) {
#ifdef __APPLE__
sem_close(tui_event_semaphore);
sem_unlink(random_sem_name);
char pathbuf[4096];
if (proc_pidpath(getpid(), pathbuf, sizeof(pathbuf)) <= 0) {
LOG(LOG_FATAL, "Failed to get path of running executable");
exit(1);
}
execve(pathbuf, saved_argv, saved_envp);
#elif defined(__linux__)
execve("/proc/self/exe", saved_argv, saved_envp);
#endif
} else {
exit(0);
}
}
static void resize_handler(int sig) {
redraw_screen();
}
int tui(void) {
if (strncmp(getenv("TERM"), "xterm", 5) != 0) {
supports_bright_colors = false;
}
srand(time(NULL));
int ret = 0;
if ((ret = init_window())) return ret;
signal(SIGINT, tui_terminate);
signal(SIGTERM, tui_terminate);
signal(SIGQUIT, tui_terminate);
signal(SIGWINCH, resize_handler);
#ifdef __APPLE__
// generate a 16 character random hex string from urandom
int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) {
LOG(LOG_FATAL, "Failed to open /dev/urandom");
return -1;
}
uint8_t random[8];
if (read(fd, random, 8) != 8) {
LOG(LOG_FATAL, "Failed to read from /dev/urandom");
return -1;
}
close(fd);
for (int i = 0; i < 8; i++) {
sprintf(&random_sem_name[i * 2], "%02x", random[i]);
}
sem_unlink(random_sem_name);
tui_event_semaphore = sem_open(random_sem_name, O_CREAT, 0644, 0);
#else
tui_event_semaphore = malloc(sizeof(sem_t));
sem_init(tui_event_semaphore, 0, 0);
#endif
pthread_t input_thread;
pthread_create(&input_thread, NULL, tui_input_thread, NULL);
tui_devhelper();
tui_state = MAIN_SCREEN;
while (1) {
switch (tui_state) {
case ERROR_SCREEN:
case EXIT_SCREEN:
goto out;
break;
case MAIN_SCREEN:
tui_state = tui_screen_main();
break;
case OPTIONS_SCREEN:
tui_state = tui_screen_options();
break;
case ENTER_RECOVERY_SCREEN:
tui_state = tui_screen_enter_recovery();
break;
case ENTER_DFU_SCREEN:
tui_state = tui_screen_enter_dfu();
break;
case JAILBREAK_SCREEN:
tui_state = tui_screen_jailbreak();
break;
default:
assert(0);
goto out;
}
}
out:
destroy_window();
return 0;
}
void tui_draw_rectangle(int x1, int y1, int x2, int y2) {
if (x1 == x2 || y1 == y2) return;
DSGON;
MOVETOT(x1 + 1, y1 + 1);
printf("%c", 0x6C);
for (int x = x1 + 1; x < x2; x++) {
putchar(0x71);
}
putchar(0x6B);
MOVETOT(x1 + 1, y2 + 1);
putchar(0x6D);
for (int x = x1 + 1; x < x2; x++) {
putchar(0x71);
}
putchar(0x6A);
for (int y = y1 + 1; y < y2; y++) {
PRINTATT(x1 + 1, y + 1, "\x78");
PRINTATT(x2 + 1, y + 1, "\x78");
}
DSGOFF;
fflush(stdout);
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
-473
View File
@@ -1,473 +0,0 @@
#ifdef TUI
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <assert.h>
#include <palerain.h>
#include <tui.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <palerain.h>
#include <tui.h>
static int tui_enter_dfu_nav_selection = 1;
static bool tui_device_is_entering_dfu = false;
static int tui_enter_dfu_status = 0;
enum {
DEVICE_TYPE_IPHONE_SE,
DEVICE_TYPE_IPHONE_6S,
DEVICE_TYPE_IPHONE_7_8,
DEVICE_TYPE_IPHONE_X,
DEVICE_TYPE_IPAD,
DEVICE_TYPE_IPOD_TOUCH
} device_type;
static int tui_product_type_to_device_type(char *product_type) {
if (strcmp(product_type, "iPhone8,1") == 0 || strcmp(product_type, "iPhone8,2") == 0) {
return DEVICE_TYPE_IPHONE_6S;
}
if (strcmp(product_type, "iPhone8,4") == 0) return DEVICE_TYPE_IPHONE_SE;
if (strcmp(product_type, "iPhone9,1") == 0 || strcmp(product_type, "iPhone9,2") == 0
|| strcmp(product_type, "iPhone9,3") == 0 || strcmp(product_type, "iPhone9,4") == 0) {
return DEVICE_TYPE_IPHONE_7_8;
}
if (strcmp(product_type, "iPhone10,1") == 0 || strcmp(product_type, "iPhone10,2") == 0
|| strcmp(product_type, "iPhone10,4") == 0 || strcmp(product_type, "iPhone10,5") == 0) {
return DEVICE_TYPE_IPHONE_7_8;
}
if (strcmp(product_type, "iPhone10,3") == 0 || strcmp(product_type, "iPhone10,6") == 0) {
return DEVICE_TYPE_IPHONE_X;
}
if (strncmp(product_type, "iPad", strlen("iPad")) == 0) {
return DEVICE_TYPE_IPAD;
}
if (strcmp(product_type, "iPod9,1") == 0) {
return DEVICE_TYPE_IPOD_TOUCH;
}
// Not found
return DEVICE_TYPE_IPHONE_SE;
}
static int tui_enter_dfu_device_type = DEVICE_TYPE_IPHONE_SE;
static int tui_enter_dfu_loading_progress = 1;
static void tui_screen_enter_dfu_nav(void) {
MOVETOT(80 - 22, 23);
printf("%s[ Cancel ]" COLOR(FG_WHITE, BG_BLACK) " %s[ %s ]" COLOR(FG_WHITE, BG_BLACK),
tui_device_is_entering_dfu || tui_enter_dfu_status == 1 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : tui_enter_dfu_nav_selection == 0 ? "\033[30;107m" : (
(
tui_mouse_x >= tui_x_offset + 80 - 23 && tui_mouse_x <= tui_x_offset + 80 - 23 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
),
tui_device_is_entering_dfu || tui_enter_dfu_status == 1 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : tui_enter_dfu_nav_selection == 1 ? "\033[30;107m" : (
(
tui_mouse_x >= tui_x_offset + 80 - 12 && tui_mouse_x <= tui_x_offset + 80 - 12 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
),
tui_enter_dfu_status == 2 ? "Retry" : "Start"
);
}
void tui_screen_enter_dfu_redraw(void) {
SETCOLOR(FG_WHITE, BG_BLACK);
switch(tui_enter_dfu_status) {
case 0:
PRINTATT(3, 3, "Time to put the device into DFU mode. Locate the buttons as marked below on");
PRINTATT(3, 4, "your device and check the instructions on the right *before* clicking Start.");
break;
case 1:
PRINTATT(3, 3, "Device entered DFU mode successfully.");
break;
case 2:
PRINTATT(3, 3, "Whoops, the device didn't enter DFU mode. Click Retry to try again.");
break;
}
tui_screen_enter_dfu_nav();
switch(tui_enter_dfu_device_type) {
case DEVICE_TYPE_IPHONE_SE:
case DEVICE_TYPE_IPAD:
if (tui_enter_dfu_loading_progress > 0 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 6, "1. Click Start");
if (tui_enter_dfu_loading_progress > 0) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
if (!tui_device_is_entering_dfu || tui_enter_dfu_loading_progress > 4 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 7, "2. Press and hold the Top and");
MOVETOT(54, 8);
printf("Home buttons together (%d)", tui_enter_dfu_loading_progress > 4 ? 0 : tui_enter_dfu_loading_progress < 1 ? 4 : 5 - tui_enter_dfu_loading_progress);
if (!tui_device_is_entering_dfu || tui_enter_dfu_loading_progress > 4) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
if (tui_enter_dfu_loading_progress < 5 || tui_enter_dfu_loading_progress > 14 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 9, "3. Release the Top button BUT");
PRINTATT(54, 10, "KEEP HOLDING the Home");
MOVETOT(54, 11);
printf("button (%d)", tui_enter_dfu_loading_progress > 14 ? 0 : tui_enter_dfu_loading_progress < 5 ? 10 : 15 - tui_enter_dfu_loading_progress);
if (tui_enter_dfu_loading_progress < 5 || tui_enter_dfu_loading_progress > 14) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
break;
case DEVICE_TYPE_IPHONE_6S:
if (tui_enter_dfu_loading_progress > 0 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 6, "1. Click Start");
if (tui_enter_dfu_loading_progress > 0) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
if (!tui_device_is_entering_dfu || tui_enter_dfu_loading_progress > 4 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 7, "2. Press and hold the Side");
PRINTATT(54, 8, "and Home buttons together");
MOVETOT(54, 9);
printf("(%d)", tui_enter_dfu_loading_progress > 4 ? 0 : tui_enter_dfu_loading_progress < 1 ? 4 : 5 - tui_enter_dfu_loading_progress);
if (!tui_device_is_entering_dfu || tui_enter_dfu_loading_progress > 4) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
if (tui_enter_dfu_loading_progress < 5 || tui_enter_dfu_loading_progress > 14 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 10, "3. Release the Side button");
PRINTATT(54, 11, "BUT KEEP HOLDING the Home");
MOVETOT(54, 12);
printf("button (%d)", tui_enter_dfu_loading_progress > 14 ? 0 : tui_enter_dfu_loading_progress < 5 ? 10 : 15 - tui_enter_dfu_loading_progress);
if (tui_enter_dfu_loading_progress < 5 || tui_enter_dfu_loading_progress > 14) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
break;
case DEVICE_TYPE_IPHONE_7_8:
case DEVICE_TYPE_IPHONE_X:
tui_draw_rectangle(17, 5, 33, 21);
PRINTATT(17, 10, "|");
MOVETOT(5, 11);
printf("%sVolume down-", tui_enter_dfu_loading_progress > 14 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : COLOR(FG_YELLOW, BG_BLACK));
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
putchar('|');
DSGON;
MOVETOT(35, 10);
putchar(0x78);
DSGOFF;
printf("%s-Side button", tui_enter_dfu_loading_progress > 4 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : COLOR(FG_YELLOW, BG_BLACK));
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
if (tui_enter_dfu_loading_progress > 0 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 6, "1. Click Start");
if (tui_enter_dfu_loading_progress > 0) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
if (!tui_device_is_entering_dfu || tui_enter_dfu_loading_progress > 4 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 7, "2. Press and hold the Side");
PRINTATT(54, 8, "and Volume down buttons");
MOVETOT(54, 9);
printf("together (%d)", tui_enter_dfu_loading_progress > 4 ? 0 : tui_enter_dfu_loading_progress < 1 ? 4 : 5 - tui_enter_dfu_loading_progress);
if (!tui_device_is_entering_dfu || tui_enter_dfu_loading_progress > 4) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
if (tui_enter_dfu_loading_progress < 5 || tui_enter_dfu_loading_progress > 14 || tui_enter_dfu_status == 2) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
}
PRINTATT(51, 10, "3. Release the Side button");
PRINTATT(54, 11, "BUT KEEP HOLDING the");
MOVETOT(54, 12);
printf("Volume down button (%d)", tui_enter_dfu_loading_progress > 14 ? 0 : tui_enter_dfu_loading_progress < 5 ? 10 : 15 - tui_enter_dfu_loading_progress);
if (tui_enter_dfu_loading_progress < 5 || tui_enter_dfu_loading_progress > 14) {
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
break;
}
switch(tui_enter_dfu_device_type) {
case DEVICE_TYPE_IPHONE_SE:
tui_draw_rectangle(18, 6, 32, 21);
tui_draw_rectangle(24, 19, 26, 20);
for (int y = 9; y < 20; y++) {
SETCOLOR(FG_BLACK, BG_BRIGHT_BLACK);
PRINTATT(20, y, " ");
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
PRINTATT(23, 8, "o ===");
PRINTATT(18, 11, "|");
PRINTATT(18, 12, "|");
MOVETOT(30, 6);
printf("__ %s-Top button", tui_enter_dfu_loading_progress > 4 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : COLOR(FG_YELLOW, BG_BLACK));
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
MOVETOT(31, 20);
printf("%s-Home button", tui_enter_dfu_loading_progress > 14 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : COLOR(FG_YELLOW, BG_BLACK));
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
break;
case DEVICE_TYPE_IPHONE_6S:
tui_draw_rectangle(17, 5, 33, 21);
tui_draw_rectangle(24, 19, 26, 20);
for (int y = 8; y < 20; y++) {
SETCOLOR(FG_BLACK, BG_BRIGHT_BLACK);
PRINTATT(19, y, " ");
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
PRINTATT(23, 7, "o ===");
PRINTATT(17, 10, "|");
PRINTATT(17, 11, "|");
MOVETOT(35, 10);
printf("|%s-Side button", tui_enter_dfu_loading_progress > 4 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : COLOR(FG_YELLOW, BG_BLACK));
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
MOVETOT(30, 20);
printf("%s-Home button", tui_enter_dfu_loading_progress > 14 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : COLOR(FG_YELLOW, BG_BLACK));
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
break;
case DEVICE_TYPE_IPHONE_7_8:
tui_draw_rectangle(24, 19, 26, 20);
for (int y = 8; y < 20; y++) {
SETCOLOR(FG_BLACK, BG_BRIGHT_BLACK);
PRINTATT(19, y, " ");
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
PRINTATT(23, 7, "o ===");
break;
case DEVICE_TYPE_IPHONE_X:
SETCOLOR(FG_BLACK, BG_BRIGHT_BLACK);
PRINTATT(19, 7, " ");
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
printf(" ");
SETCOLOR(FG_BLACK, BG_BRIGHT_BLACK);
printf(" ");
SETCOLOR(FG_BLACK, BG_BRIGHT_BLACK);
for (int y = 8; y < 22; y++) {
PRINTATT(19, y, " ");
}
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
DSGON;
MOVETOT(35, 11);
putchar(0x78);
DSGOFF;
break;
case DEVICE_TYPE_IPAD:
tui_draw_rectangle(14, 6, 36, 21);
tui_draw_rectangle(24, 19, 26, 20);
for (int y = 9; y < 20; y++) {
SETCOLOR(FG_BLACK, BG_BRIGHT_BLACK);
PRINTATT(16, y, " ");
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
}
PRINTATT(23, 8, "o ===");
PRINTATT(14, 11, "|");
PRINTATT(14, 12, "|");
MOVETOT(33, 6);
printf("__ %s-Top button", tui_enter_dfu_loading_progress > 4 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : COLOR(FG_YELLOW, BG_BLACK));
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
MOVETOT(29, 21);
printf("%s-Home button", tui_enter_dfu_loading_progress > 14 ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : COLOR(FG_YELLOW, BG_BLACK));
SETCOLOR(FG_BRIGHT_WHITE, BG_BLACK);
break;
}
fflush(stdout);
}
// TODO: IMPLEMENT REAL ENTER RECOVERY
static int dfu_time = 0;
static tui_screen_t tui_enter_dfu(void) {
if (tui_connected_devices && !tui_connected_devices->next) {
if (tui_connected_devices->mode == TUI_DEVICE_MODE_NORMAL) {
tui_enter_dfu_status = 0;
return ENTER_RECOVERY_SCREEN;
}
}
int i = 0;
tui_enter_dfu_loading_progress = 1;
while(1) {
if (++i % 10 == 0) {
tui_enter_dfu_loading_progress++;
}
redraw_screen();
usleep(100000);
int event = tui_try_get_event();
if (event == TUI_EVENT_CONNECTED_DEVICES_CHANGED) {
if (tui_connected_devices && !tui_connected_devices->next) {
if (tui_connected_devices->mode == TUI_DEVICE_MODE_RECOVERY || tui_connected_devices->mode == TUI_DEVICE_MODE_NORMAL) {
tui_enter_dfu_status = 2;
tui_device_is_entering_dfu = false;
return ENTER_DFU_SCREEN;
} else {
tui_enter_dfu_status = 1;
tui_device_is_entering_dfu = false;
tui_enter_dfu_loading_progress = 15;
redraw_screen();
sleep(3);
tui_jailbreak();
return JAILBREAK_SCREEN;
}
}
}
if (i > 10 * (60 + 15)) {
return MAIN_SCREEN;
}
if (i == 10 * 2) {
exitrecv_cmd(tui_connected_devices->ecid);
}
}
redraw_screen();
fflush(stdout);
sleep(3);
return JAILBREAK_SCREEN;
}
static int tui_enter_dfu_nav_mouse_select = -1;
tui_screen_t tui_screen_enter_dfu(void) {
if (tui_connected_devices && !tui_connected_devices->next) {
tui_enter_dfu_device_type = tui_product_type_to_device_type(tui_connected_devices->product_type);
}
tui_device_is_entering_dfu = false;
tui_enter_dfu_loading_progress = 0;
tui_enter_dfu_nav_selection = 1;
redraw_screen();
tui_device_is_entering_dfu = false;
tui_enter_dfu_loading_progress = 0;
while(1) {
int event = tui_get_event();
switch (event) {
case TUI_EVENT_CONNECTED_DEVICES_CHANGED:
break;
case TUI_EVENT_INPUT: {
int input = tui_last_input;
if (input == TUI_INPUT_NONE) continue;
if (tui_device_is_entering_dfu) continue;
switch (input) {
case TUI_INPUT_LEFT:
case TUI_INPUT_RIGHT:
tui_enter_dfu_nav_selection = !tui_enter_dfu_nav_selection;
redraw_screen();
break;
case TUI_INPUT_SELECT:
switch(tui_enter_dfu_nav_selection) {
case 0:
return MAIN_SCREEN;
case 1:
tui_device_is_entering_dfu = true;
redraw_screen();
return tui_enter_dfu();
}
case TUI_INPUT_MOUSE_MOVE:
tui_screen_enter_dfu_nav();
fflush(stdout);
break;
case TUI_INPUT_MOUSE_DOWN:
if (tui_mouse_y == tui_y_offset + 22) {
if (tui_mouse_x >= tui_x_offset + 80 - 23 && tui_mouse_x <= tui_x_offset + 80 - 23 + 10) {
tui_enter_dfu_nav_selection = 0;
tui_enter_dfu_nav_mouse_select = 0;
redraw_screen();
} else if (tui_mouse_x >= tui_x_offset + 80 - 12 && tui_mouse_x <= tui_x_offset + 80 - 12 + 10) {
tui_enter_dfu_nav_selection = 1;
tui_enter_dfu_nav_mouse_select = 1;
redraw_screen();
}
}
break;
case TUI_INPUT_MOUSE_UP:
if (tui_mouse_y == tui_y_offset + 22) {
if (tui_mouse_x >= tui_x_offset + 80 - 23 && tui_mouse_x <= tui_x_offset + 80 - 23 + 10) {
return MAIN_SCREEN;
} else if (tui_mouse_x >= tui_x_offset + 80 - 12 && tui_mouse_x <= tui_x_offset + 80 - 12 + 10) {
tui_device_is_entering_dfu = true;
redraw_screen();
return tui_enter_dfu();
}
}
tui_enter_dfu_nav_mouse_select = -1;
break;
}
break;
}
}
}
return MAIN_SCREEN;
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
-209
View File
@@ -1,209 +0,0 @@
#ifdef TUI
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <poll.h>
#include <palerain.h>
#include <tui.h>
int tui_enter_recovery_nav_selection = 1;
bool tui_device_is_entering_recovery = false;
bool tui_enter_recovery_mode_failed = false;
static void tui_screen_enter_recovery_nav(void) {
MOVETOT(80 - 22, 23);
printf("%s[ Back ]" COLOR(FG_WHITE, BG_BLACK) " %s[ Next ]" COLOR(FG_WHITE, BG_BLACK),
tui_device_is_entering_recovery ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : tui_enter_recovery_nav_selection == 0 ? "\033[30;107m" : (
(
tui_mouse_x >= tui_x_offset + 80 - 23 && tui_mouse_x <= tui_x_offset + 80 - 23 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
),
tui_device_is_entering_recovery ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : tui_enter_recovery_nav_selection == 1 ? "\033[30;107m" : (
(
tui_mouse_x >= tui_x_offset + 80 - 12 && tui_mouse_x <= tui_x_offset + 80 - 12 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
)
);
}
static char enter_recovery_loading[9][8] = {
"........",
"|.......",
".|......",
"..|.....",
"...|....",
"....|...",
".....|..",
"......|.",
".......|"
};
static char enter_recovery_loading_troll[9][8] = {
".......",
"t......",
".r.....",
"..o....",
"...l...",
"....l..",
".....e.",
"......d",
};
static bool is_troll;
static int tui_enter_recovery_loading_progress = 0;
static void tui_screen_enter_recovery_loading(void) {
SETCOLOR(FG_YELLOW, BG_BLACK);
PRINTATT(3, 8, "Entering recovery mode ");
printf("%.8s", is_troll ? enter_recovery_loading_troll[tui_enter_recovery_loading_progress] : enter_recovery_loading[tui_enter_recovery_loading_progress]);
SETCOLOR(FG_WHITE, BG_BLACK);
fflush(stdout);
}
void tui_screen_enter_recovery_redraw(void) {
PRINTATT(3, 3, "The device needs to be put into DFU mode to apply the jailbreak. This is a");
PRINTATT(3, 4, "manual process and we will guide you through it.");
PRINTATT(3, 5, "In order to prevent filesystem corruption through hard reset, the device");
PRINTATT(3, 6, "will be put into recovery mode first. Click Next when you are ready.");
if (tui_enter_recovery_mode_failed) {
SETCOLOR(FG_YELLOW, BG_BLACK);
PRINTATT(3, 8, "Hmm... device did not enter recovery mode!? Click Next to try again...");
SETCOLOR(FG_WHITE, BG_BLACK);
}
tui_screen_enter_recovery_nav();
if (tui_device_is_entering_recovery) {
tui_screen_enter_recovery_loading();
}
fflush(stdout);
}
static int recovery_time = 0;
static tui_screen_t tui_enter_recovery(void) {
enter_recovery_cmd(tui_connected_devices->udid);
is_troll = false;
if (rand() % 1000 == 0) {
is_troll = true;
}
int i = 0;
recovery_time = 0;
while(1) {
redraw_screen();
tui_enter_recovery_loading_progress++;
tui_enter_recovery_loading_progress %= 9;
// 100ms sleep
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 100000000;
nanosleep(&ts, NULL);
int event = tui_try_get_event();
if (event == TUI_EVENT_CONNECTED_DEVICES_CHANGED) {
if (tui_connected_devices && !tui_connected_devices->next && tui_connected_devices->mode == TUI_DEVICE_MODE_RECOVERY) {
SETCOLOR(FG_YELLOW, BG_BLACK);
PRINTATT(3, 8, "Device is now in recovery mode.");
SETCOLOR(FG_WHITE, BG_BLACK);
fflush(stdout);
sleep(3);
return ENTER_DFU_SCREEN;
}
}
if (i > 60 * 10) {
tui_enter_recovery_mode_failed = true;
return ENTER_RECOVERY_SCREEN;
}
}
}
static int tui_enter_recovery_nav_mouse_select = -1;
tui_screen_t tui_screen_enter_recovery(void) {
tui_device_is_entering_recovery = false;
tui_enter_recovery_loading_progress = 0;
tui_enter_recovery_nav_selection = 1;
redraw_screen();
while(1) {
int event = tui_get_event();
switch (event) {
case TUI_EVENT_CONNECTED_DEVICES_CHANGED:
tui_enter_recovery_mode_failed = false;
return MAIN_SCREEN;
case TUI_EVENT_INPUT: {
int input = tui_last_input;
if (input == TUI_INPUT_NONE) continue;
if (tui_device_is_entering_recovery) continue;
switch (input) {
case TUI_INPUT_LEFT:
case TUI_INPUT_RIGHT:
tui_enter_recovery_nav_selection = !tui_enter_recovery_nav_selection;
redraw_screen();
break;
case TUI_INPUT_SELECT:
switch(tui_enter_recovery_nav_selection) {
case 0:
tui_enter_recovery_mode_failed = false;
return MAIN_SCREEN;
case 1:
tui_device_is_entering_recovery = true;
redraw_screen();
return tui_enter_recovery();
}
break;
case TUI_INPUT_MOUSE_MOVE:
tui_screen_enter_recovery_nav();
fflush(stdout);
break;
case TUI_INPUT_MOUSE_DOWN:
if (tui_mouse_y == tui_y_offset + 22) {
if (tui_mouse_x >= tui_x_offset + 80 - 23 && tui_mouse_x <= tui_x_offset + 80 - 23 + 10) {
tui_enter_recovery_nav_selection = 0;
tui_enter_recovery_nav_mouse_select = 0;
tui_screen_enter_recovery_nav();
fflush(stdout);
} else if (tui_mouse_x >= tui_x_offset + 80 - 12 && tui_mouse_x <= tui_x_offset + 80 - 12 + 10) {
tui_enter_recovery_nav_selection = 1;
tui_enter_recovery_nav_mouse_select = 1;
tui_screen_enter_recovery_nav();
fflush(stdout);
}
}
break;
case TUI_INPUT_MOUSE_UP:
if (tui_mouse_y == tui_y_offset + 22) {
if (tui_mouse_x >= tui_x_offset + 80 - 23 && tui_mouse_x <= tui_x_offset + 80 - 23 + 10) {
return MAIN_SCREEN;
} else if (tui_mouse_x >= tui_x_offset + 80 - 12 && tui_mouse_x <= tui_x_offset + 80 - 12 + 10) {
tui_device_is_entering_recovery = true;
redraw_screen();
return tui_enter_recovery();
}
}
tui_enter_recovery_nav_mouse_select = -1;
break;
}
break;
}
}
}
tui_enter_recovery_mode_failed = false;
return MAIN_SCREEN;
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
-176
View File
@@ -1,176 +0,0 @@
#ifdef TUI
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <assert.h>
#include <palerain.h>
#include <tui.h>
bool tui_is_jailbreaking = false;
static void tui_screen_jailbreak_nav(void) {
if (tui_is_jailbreaking) {
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
} else {
SETCOLOR(FG_BLACK, BG_BRIGHT_WHITE);
}
PRINTATT(80 - 11, 23, "[ Done ]");
SETCOLOR(FG_WHITE, BG_BLACK);
}
static pthread_t tui_jailbreak_thread_id;
int tui_jailbreak_stage = 0;
char *tui_jailbreak_status = NULL;
void tui_jailbreak_status_changed(void) {
tui_last_event = TUI_EVENT_JAILBREAK_STATUS_CHANGED;
sem_post(tui_event_semaphore);
}
static void *tui_jailbreak_thread(void *arg) {
tui_jailbreak_stage = 1;
tui_jailbreak_status = "About to execute checkra1n";
tui_jailbreak_status_changed();
if (!tui_connected_devices || tui_connected_devices->next || tui_connected_devices->mode != TUI_DEVICE_MODE_DFU) {
tui_jailbreak_status = "ERROR: No single device in DFU mode found";
tui_jailbreak_status_changed();
pthread_exit(NULL);
return NULL;
}
tui_jailbreak_stage = 2;
tui_jailbreak_status = "Running exploit";
tui_jailbreak_status_changed();
if (exec_checkra1n() != 0) {
tui_jailbreak_status = "ERROR: Failed to run exploit";
tui_jailbreak_status_changed();
pthread_exit(NULL);
return NULL;
}
tui_jailbreak_stage = 3;
tui_jailbreak_status = "Waiting for PongoOS";
tui_jailbreak_status_changed();
sleep(2);
pthread_create(&pongo_thread, NULL, pongo_helper, NULL);
// pongo helper will take care of the rest
pthread_exit(NULL);
}
void tui_jailbreak(void) {
tui_is_jailbreaking = true;
if (tui_options_verbose_boot) {
palerain_flags |= palerain_option_verbose_boot;
} else {
palerain_flags &= ~palerain_option_verbose_boot;
}
if (tui_options_safe_mode) {
palerain_flags |= palerain_option_safemode;
} else {
palerain_flags &= ~palerain_option_safemode;
}
if (tui_options_force_revert) {
palerain_flags |= palerain_option_force_revert;
} else {
palerain_flags &= ~palerain_option_force_revert;
}
snprintf(palerain_flags_cmd, 0x30, "palera1n_flags 0x%" PRIx64, palerain_flags);
snprintf(xargs_cmd, sizeof(xargs_cmd), "xargs %s", tui_options_boot_args);
pthread_create(&tui_jailbreak_thread_id, NULL, tui_jailbreak_thread, NULL);
}
void tui_screen_jailbreak_redraw(void) {
PRINTATT(3, 3, "Installing jailbreak, this will take a moment. If the device asks for a");
PRINTATT(3, 4, "passcode please enter it. Do not disconnect the device until finished.");
if (tui_jailbreak_status) {
SETCOLOR(FG_YELLOW, BG_BLACK);
PRINTATT(3, 6, tui_jailbreak_status);
SETCOLOR(FG_WHITE, BG_BLACK);
}
tui_draw_rectangle(5, 9, 80 - 6, 9 + 2);
MOVETOT(6 + 1, 10 + 1);
SETCOLOR(FG_BLACK, BG_WHITE);
for (int i = 0; i < ((80 - 12) * ((float)tui_jailbreak_stage / 9)); i++) {
putchar(' ');
}
SETCOLOR(FG_WHITE, BG_BLACK);
tui_screen_jailbreak_nav();
}
static int tui_jailbreak_nav_mouse_select = -1;
tui_screen_t tui_screen_jailbreak(void) {
redraw_screen();
while(1) {
int event = tui_get_event();
switch (event) {
case TUI_EVENT_INPUT: {
int input = tui_last_input;
if (input == TUI_INPUT_NONE) continue;
switch (input) {
case TUI_INPUT_SELECT:
if (!tui_is_jailbreaking) {
tui_is_restarting = true;
tui_terminate(0);
}
break;
case TUI_INPUT_MOUSE_DOWN:
if (tui_mouse_y == tui_y_offset + 24 - 2 &&
tui_mouse_x >= tui_x_offset + 80 - 12 &&
tui_mouse_x <= tui_x_offset + 80 - 12 + 10) {
tui_jailbreak_nav_mouse_select = 0;
redraw_screen();
}
break;
case TUI_INPUT_MOUSE_UP:
if (tui_jailbreak_nav_mouse_select == 0) {
tui_jailbreak_nav_mouse_select = -1;
if (!tui_is_jailbreaking) {
tui_is_restarting = true;
tui_terminate(0);
}
}
break;
}
break;
}
case TUI_EVENT_JAILBREAK_STATUS_CHANGED:
redraw_screen();
break;
}
}
return EXIT_SCREEN;
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
-380
View File
@@ -1,380 +0,0 @@
#ifdef TUI
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <assert.h>
#include <palerain.h>
#include <tui.h>
static int tui_compare_versions(const char *firstVersion, const char *secondVersion);
static bool showing_ecid = false;
static char palera1n_logo[17][16] = {
" ++ ",
" #@@# ",
" +@@@@+ ",
" :@@@@@@: ",
" #@@@@@@# ",
" +@@@@@@@@+ ",
" :#*@@@@@@*#: ",
" %###@@@@###% ",
" .####%@@%####. ",
" @############@ ",
"=@@*########*@@=",
"+@@@@%####%@@@@+",
":@@@@%%**%%@@@@:",
" +@@%%*@@*%%@@+ ",
" ++%@@@@%++ ",
" :++: "
};
static char random_quotes[][150] = {
"panic(cpu 1 caller 0xfffffff0232bd958): SEP Panic",
"Now with Apple TV support!",
"checkra1n will open source in 2020",
"Try running palera1n on a Intel 80486!",
"\"iOS 15 with SSV is unhackable\", but here we are.",
"initproc exited -- exit reason namespace 1 subcode0x7 description: none",
"totally not checkra1n",
"Because the command line wasn't easy enough",
"Checkra1n wrapper?",
""
};
#define PALERA1N_URL "https://palera.in"
static int tui_main_nav_selection = 1;
static bool quick_mode_enabled = false;
static bool tui_can_start = false;
static int random_quote;
bool easter_egg = false;
void tui_screen_main_nav(void) {
MOVETOT(80 - 52, 23);
printf("[%c] %sQuick Mode " COLOR(FG_WHITE, BG_BLACK) " %s[ Options ]" COLOR(FG_WHITE, BG_BLACK) " %s[ Start ]" COLOR(FG_WHITE, BG_BLACK) " %s[ Quit ]" COLOR(FG_WHITE, BG_BLACK), quick_mode_enabled ? 'x' : ' ',
tui_main_nav_selection == 0 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 80 - 49 && tui_mouse_x <= tui_x_offset + 80 - 49 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
),
tui_main_nav_selection == 1 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 80 - 37 && tui_mouse_x <= tui_x_offset + 80 - 37 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
),
tui_main_nav_selection == 2 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : !tui_can_start ? (supports_bright_colors ? COLOR(FG_BRIGHT_BLACK, BG_BLACK) : COLOR(FG_BLUE, BG_BLACK)) : (
(
tui_mouse_x >= tui_x_offset + 80 - 25 && tui_mouse_x <= tui_x_offset + 80 - 25 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
),
tui_main_nav_selection == 3 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 80 - 13 && tui_mouse_x <= tui_x_offset + 80 - 13 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
)
);
}
void tui_screen_main_redraw(void) {
PRINTATT(3, 2, "Welcome to palera1n!");
SETCOLOR(FG_WHITE, BG_BLACK);
PRINTATT(3, 9, "Made by: Nick Chan, Ploosh, Khcrysalis, Mineek");
PRINTATT(3, 10, "staturnz, kok3shidoll, ");
if ((tui_mouse_y == tui_y_offset + 9 && tui_mouse_x >= tui_x_offset + 25 && tui_mouse_x <= tui_x_offset + 25 + 8) || easter_egg) {
SETCOLORA(FG_BRIGHT_WHITE, BG_BLACK, BOLD);
}
printf("HAHALOSAH");
RESETFONT;
SETCOLOR(FG_WHITE, BG_BLACK);
PRINTATT(3, 12, "Thanks to: llsc12, nebula,");
PRINTATT(3, 13, "nikias (libimobiledevice), checkra1n");
PRINTATT(3, 14, "(Siguza, axi0mx, littlelailo et al.), Procursus");
PRINTATT(3, 15, "Team (Hayden Seay, Cameron Katri, Keto et.al),");
PRINTATT(80 - (int)sizeof(PALERA1N_URL), 21, PALERA1N_URL);
PRINTATT(80 - (int)sizeof("@palera1n"), 20, "@palera1n");
PRINTATT(3, 20, "With <3 from HAHALOSAH");
PRINTATT(3, 21, "Note: Backup your stuff. Use at your own risk.");
DRAWLINET(2, 22, 78);
DRAWLINET(2, 3, 50);
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
DRAWLINET(2, 11, 50);
DRAWLINET(2, 16, 50);
for (int y = 0; y < 16; y++) {
PRINTATLENT(80 - 22, y + 4, palera1n_logo[y], 16);
}
SETCOLOR(FG_YELLOW, BG_BLACK);
if (tui_connected_devices == NULL) {
PRINTATT(3, 5, "Connect your iPhone, iPad, iPod Touch, or Apple");
PRINTATT(3, 6, "TV to begin.");
tui_can_start = false;
} else if (tui_connected_devices->next != NULL) {
PRINTATT(3, 5, "Please attach only one device.");
tui_can_start = false;
} else {
if (strlen(tui_connected_devices->display_name) == 0) {
PRINTATT(3, 5, "ERROR: Failed to open device in recovery/DFU mode");
PRINTATT(3, 6, "Please reopen palera1n and try again.");
} else if (tui_connected_devices->mode == TUI_DEVICE_MODE_NORMAL) {
MOVETOT(3, 5);
int ecid_y;
if (!tui_connected_devices->arm64) {
printf("Sorry, %s (iOS %s) is not supported.", tui_connected_devices->display_name, tui_connected_devices->version);
ecid_y = 6;
tui_can_start = false;
} else if (tui_compare_versions(tui_connected_devices->version, "15.0") < 0) {
printf("Sorry, %s is supported, but iOS", tui_connected_devices->display_name);
MOVETOT(3, 6);
printf("%s is not.", tui_connected_devices->version);
PRINTATT(3, 7, "Supported versions are 15.0+");
ecid_y = 8;
tui_can_start = false;
} else if (tui_connected_devices->requires_passcode_disabled) {
printf("Sorry, this devices passcode must be disabled on %s.", tui_connected_devices->version);
MOVETOT(3, 6);
printf("On 16.0+, you must reset the phone to factory settings");
MOVETOT(3, 7);
printf("and not have a passcode enabled ever since last restore.");
ecid_y = 8;
tui_can_start = false;
} else {
printf("%s (%s) connected in Normal mode.", tui_connected_devices->display_name, tui_connected_devices->version);
ecid_y = 6;
tui_can_start = true;
}
if (showing_ecid) {
MOVETOT(3, ecid_y);
printf("ECID: 0x%" PRIx64 " ", tui_connected_devices->ecid);
} else {
PRINTATT(3, ecid_y, "Press (E) to show ECID.");
}
} else if (tui_connected_devices->mode == TUI_DEVICE_MODE_RECOVERY) {
MOVETOT(3, 5);
printf("%s connected in Recovery mode.", tui_connected_devices->display_name);
if (showing_ecid) {
MOVETOT(3, 6);
printf("ECID: 0x%" PRIx64 " ", tui_connected_devices->ecid);
} else {
PRINTATT(3, 6, "Press (E) to show ECID.");
}
PRINTATT(3, 7, "NOTE: Ensure installed iOS is in range 15.0+");
tui_can_start = true;
} else if (tui_connected_devices->mode == TUI_DEVICE_MODE_DFU) {
MOVETOT(3, 5);
printf("%s connected in DFU mode.", tui_connected_devices->display_name);
if (showing_ecid) {
MOVETOT(3, 6);
printf("ECID: 0x%" PRIx64 " ", tui_connected_devices->ecid);
} else {
PRINTATT(3, 6, "Press (E) to show ECID.");
}
#ifdef DEV_BUILD
tui_can_start = true;
#else
PRINTATT(3, 7, "Please connect device in Normal/Recovery mode");
PRINTATT(3, 8, "or run palera1n in CLI mode");
tui_can_start = false;
#endif
}
}
if (!tui_can_start && tui_main_nav_selection == 2) {
tui_main_nav_selection = 1;
}
SETCOLOR(FG_WHITE, BG_BLACK);
for (int y = 0; y < 3; y++) {
PRINTATLEN(tui_x_offset + 3, tui_y_offset + 17 + y, random_quotes[random_quote] + y * 50, 50);
}
tui_screen_main_nav();
fflush(stdout);
}
static int tui_main_nav_mouse_select = -1;
tui_screen_t tui_screen_main(void) {
random_quote = ((unsigned int)((rand()+rand())/2)) % 8;
redraw_screen();
while(1) {
int event = tui_get_event();
switch (event) {
case TUI_EVENT_CONNECTED_DEVICES_CHANGED:
redraw_screen();
break;
case TUI_EVENT_INPUT: {
int input = tui_last_input;
switch (input) {
case TUI_INPUT_NONE:
if (tui_last_key == 'E' || tui_last_key == 'e') {
showing_ecid = !showing_ecid;
tui_screen_main_redraw();
}
break;
case TUI_INPUT_LEFT:
case TUI_INPUT_TAB_BACK:
if (--tui_main_nav_selection == -1) tui_main_nav_selection = 3;
if (tui_main_nav_selection == 2 && !tui_can_start) tui_main_nav_selection = 1;
tui_screen_main_nav();
fflush(stdout);
break;
case TUI_INPUT_RIGHT:
case TUI_INPUT_TAB:
if (++tui_main_nav_selection == 4) tui_main_nav_selection = 0;
if (tui_main_nav_selection == 2 && !tui_can_start) tui_main_nav_selection = 3;
tui_screen_main_nav();
fflush(stdout);
break;
case TUI_INPUT_SELECT:
switch(tui_main_nav_selection) {
case 0:
quick_mode_enabled = !quick_mode_enabled;
tui_screen_main_nav();
fflush(stdout);
break;
case 1:
return OPTIONS_SCREEN;
case 2:
if (tui_can_start) {
if (tui_connected_devices->mode == TUI_DEVICE_MODE_NORMAL) {
return ENTER_RECOVERY_SCREEN;
} else if (tui_connected_devices->mode == TUI_DEVICE_MODE_RECOVERY) {
return ENTER_DFU_SCREEN;
} else if (tui_connected_devices->mode == TUI_DEVICE_MODE_DFU) {
tui_jailbreak();
return JAILBREAK_SCREEN;
}
}
break;
case 3:
return EXIT_SCREEN;
}
break;
case TUI_INPUT_MOUSE_MOVE:
tui_screen_main_redraw();
break;
case TUI_INPUT_MOUSE_DOWN:
if ((tui_mouse_y == tui_y_offset + 9 && tui_mouse_x >= tui_x_offset + 25 && tui_mouse_x <= tui_x_offset + 25 + 8)) {
easter_egg = true;
break;
}
if (tui_mouse_y == tui_y_offset + 22) {
if (tui_mouse_x >= tui_x_offset + 80 - 49 && tui_mouse_x <= tui_x_offset + 80 - 49 + 10) {
tui_main_nav_selection = 0;
tui_main_nav_mouse_select = 0;
} else if (tui_mouse_x >= tui_x_offset + 80 - 37 && tui_mouse_x <= tui_x_offset + 80 - 37 + 10) {
tui_main_nav_selection = 1;
tui_main_nav_mouse_select = 1;
} else if (tui_mouse_x >= tui_x_offset + 80 - 25 && tui_mouse_x <= tui_x_offset + 80 - 25 + 10) {
if (tui_can_start) {
tui_main_nav_selection = 2;
tui_main_nav_mouse_select = 2;
}
} else if (tui_mouse_x >= tui_x_offset + 80 - 13 && tui_mouse_x <= tui_x_offset + 80 - 13 + 10) {
tui_main_nav_selection = 3;
tui_main_nav_mouse_select = 3;
}
tui_screen_main_nav();
fflush(stdout);
}
break;
case TUI_INPUT_MOUSE_UP:
if (tui_mouse_y == tui_y_offset + 22) {
if (tui_mouse_x >= tui_x_offset + 80 - 49 && tui_mouse_x <= tui_x_offset + 80 - 49 + 10 && tui_main_nav_mouse_select == 0) {
quick_mode_enabled = !quick_mode_enabled;
redraw_screen();
} else if (tui_mouse_x >= tui_x_offset + 80 - 37 && tui_mouse_x <= tui_x_offset + 80 - 37 + 10 && tui_main_nav_mouse_select == 1) {
return OPTIONS_SCREEN;
} else if (tui_mouse_x >= tui_x_offset + 80 - 25 && tui_mouse_x <= tui_x_offset + 80 - 25 + 10 && tui_main_nav_mouse_select == 2) {
if (tui_can_start) {
if (tui_connected_devices->mode == TUI_DEVICE_MODE_NORMAL) {
return ENTER_RECOVERY_SCREEN;
} else if (tui_connected_devices->mode == TUI_DEVICE_MODE_RECOVERY) {
return ENTER_DFU_SCREEN;
} else if (tui_connected_devices->mode == TUI_DEVICE_MODE_DFU) {
tui_jailbreak();
return JAILBREAK_SCREEN;
}
}
} else if (tui_mouse_x >= tui_x_offset + 80 - 13 && tui_mouse_x <= tui_x_offset + 80 - 13 + 10 && tui_main_nav_mouse_select == 3) {
return EXIT_SCREEN;
}
}
tui_main_nav_mouse_select = -1;
break;
}
break;
}
}
}
return MAIN_SCREEN;
}
static int tui_version_extract_component(const char *version, int index) {
int component = 0;
int componentIndex = 0;
for (int i = 0; version[i] != '\0'; i++) {
if (version[i] == '.') {
componentIndex++;
if (componentIndex > index) {
break;
}
continue;
}
if (componentIndex == index) {
component *= 10;
component += version[i] - '0';
}
}
return component;
}
static int tui_compare_versions(const char *firstVersion, const char *secondVersion) {
if (strcmp(firstVersion, secondVersion) == 0) {
return 0;
}
int firstVersionMajor = tui_version_extract_component(firstVersion, 0);
int firstVersionMinor = tui_version_extract_component(firstVersion, 1);
int firstVersionPatch = tui_version_extract_component(firstVersion, 2);
int secondVersionMajor = tui_version_extract_component(secondVersion, 0);
int secondVersionMinor = tui_version_extract_component(secondVersion, 1);
int secondVersionPatch = tui_version_extract_component(secondVersion, 2);
if (firstVersionMajor != secondVersionMajor) {
return firstVersionMajor - secondVersionMajor;
}
if (firstVersionMinor != secondVersionMinor) {
return firstVersionMinor - secondVersionMinor;
}
return firstVersionPatch - secondVersionPatch;
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
-349
View File
@@ -1,349 +0,0 @@
#ifdef TUI
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <assert.h>
#include <palerain.h>
#include <tui.h>
static int tui_options_nav_selection = 0;
static int tui_options_nav_mouse_select = 0;
static bool tui_options_allow_untested = false;
bool tui_options_safe_mode = false;
bool tui_options_verbose_boot = false;
bool tui_options_force_revert = false;
bool tui_options_flower_chain = true;
bool tui_options_is_editing_boot_args = false;
char tui_options_boot_args[0x1e0 + 1] = {0};
int tui_options_boot_args_cursor = 0;
int tui_options_boot_args_offset = 0;
void tui_screen_options_nav(void) {
SETCOLOR(FG_WHITE, BG_BLACK);
MOVETOT(80 - 11, 23);
printf("%s[ Back ]" COLOR(FG_WHITE, BG_BLACK),
tui_options_nav_selection == 0 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 80 - 12 && tui_mouse_x <= tui_x_offset + 80 - 12 + 10
) && (tui_mouse_y == tui_y_offset + 22) ? COLOR(FG_BLACK, BG_WHITE) : ""
)
);
#ifdef DEV_BUILD
PRINTATT(3, 23, "DEV_BUILD");
#endif
}
extern bool easter_egg;
void tui_screen_options_options(void) {
SETCOLOR( FG_BRIGHT_BLACK, BG_BLACK);
MOVETOT(3, 8);
printf("[%c] %sAllow untested iOS/iPadOS versions" COLOR(FG_WHITE, BG_BLACK),
tui_options_allow_untested ? ' ' : ' ',
COLOR(FG_BLACK, FG_BRIGHT_BLACK));
SETCOLOR(FG_WHITE, BG_BLACK);
MOVETOT(3, 9);
printf("[%c] %sSafe Mode " COLOR(FG_WHITE, BG_BLACK),
tui_options_safe_mode ? 'x' : ' ',
tui_options_nav_selection == 1 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 5 && tui_mouse_x <= tui_x_offset + 5 + 34
) && (tui_mouse_y == tui_y_offset + 8) ? COLOR(FG_BLACK, BG_WHITE) : ""
));
MOVETOT(3, 10);
printf("[%c] %sVerbose Boot " COLOR(FG_WHITE, BG_BLACK),
tui_options_verbose_boot ? 'x' : ' ',
tui_options_nav_selection == 2 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 5 && tui_mouse_x <= tui_x_offset + 5 + 34
) && (tui_mouse_y == tui_y_offset + 9) ? COLOR(FG_BLACK, BG_WHITE) : ""
));
MOVETOT(3, 11);
printf("[%c] %sForce Revert " COLOR(FG_WHITE, BG_BLACK),
tui_options_force_revert ? 'x' : ' ',
tui_options_nav_selection == 3 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 5 && tui_mouse_x <= tui_x_offset + 5 + 34
) && (tui_mouse_y == tui_y_offset + 10) ? COLOR(FG_BLACK, BG_WHITE) : ""
));
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
DRAWLINET(3, 13, 76);
SETCOLOR(FG_WHITE, BG_BLACK);
MOVETOT(7, 15);
printf("%sBoot Arguments: " COLOR(FG_WHITE, BG_BLACK),
tui_options_nav_selection == 4 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 5 && tui_mouse_x <= tui_x_offset + 5 + 34
) && (
tui_mouse_y == tui_y_offset + 14 || tui_mouse_y == tui_y_offset + 15
) ? COLOR(FG_BLACK, BG_WHITE) : ""
));
const char* boot_args_hint = tui_options_is_editing_boot_args ? "(press ENTER when done)" : " (press ENTER to edit)";
MOVETOT((int)(80 - 5 - strlen(boot_args_hint)), 15);
printf("%s", boot_args_hint);
MOVETOT(3, 17);
printf("[%c] %s%s " COLOR(FG_WHITE, BG_BLACK),
tui_options_flower_chain ? 'x' : ' ',
tui_options_nav_selection == 5 ? COLOR(FG_BLACK, BG_BRIGHT_WHITE) : (
(
tui_mouse_x >= tui_x_offset + 5 && tui_mouse_x <= tui_x_offset + 5 + 34
) && (tui_mouse_y == tui_y_offset + 16) ? COLOR(FG_BLACK, BG_WHITE) : ""
), easter_egg ? "Neko Chain " : "Flower Chain");
MOVETOT(7, 16);
if (supports_bright_colors) {
SETCOLOR(tui_options_is_editing_boot_args ? FG_YELLOW : FG_WHITE, BG_BRIGHT_BLACK);
} else {
SETCOLOR(tui_options_is_editing_boot_args ? FG_YELLOW : FG_WHITE, BG_BLUE);
}
int boot_args_len = strlen(tui_options_boot_args);
if ((tui_options_boot_args_cursor - tui_options_boot_args_offset) > (68 - 1)) {
tui_options_boot_args_offset += (tui_options_boot_args_cursor - tui_options_boot_args_offset) - (68 - 1);
}
if ((tui_options_boot_args_cursor - tui_options_boot_args_offset) < 0) {
tui_options_boot_args_offset = tui_options_boot_args_cursor;
}
if ((tui_options_boot_args_offset + 68 - 1) > boot_args_len && boot_args_len >= 68 - 1) {
tui_options_boot_args_offset = boot_args_len - 68 + 1;
}
for (int i = 0; i < 68; i++) {
putchar(((i + tui_options_boot_args_offset) < boot_args_len) ? tui_options_boot_args[i + tui_options_boot_args_offset] : ' ');
}
if (tui_options_is_editing_boot_args) {
MOVETOT((int)(7 + tui_options_boot_args_cursor - tui_options_boot_args_offset), 16);
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_YELLOW);
} else {
SETCOLOR(FG_BLUE, BG_YELLOW);
}
putchar(tui_options_boot_args_cursor < boot_args_len ? tui_options_boot_args[tui_options_boot_args_cursor] : ' ');
}
SETCOLOR(FG_WHITE, BG_BLACK);
MOVETOT(5, 16);
printf(tui_options_boot_args_offset > 0 ? "<<" : " ");
MOVETOT(75, 16);
printf((strlen(tui_options_boot_args) - tui_options_boot_args_offset) > 68 ? ">>" : " ");
}
void tui_screen_options_redraw(void) {
SETCOLOR(FG_WHITE, BG_BLACK);
PRINTATT(3, 3, "You may set the following options. If you don't know what they mean you'll");
PRINTATT(3, 4, "probably have no reason to set them.");
if (supports_bright_colors) {
SETCOLOR(FG_BRIGHT_BLACK, BG_BLACK);
} else {
SETCOLOR(FG_BLUE, BG_BLACK);
}
DRAWLINET(3, 6, 76);
tui_screen_options_nav();
tui_screen_options_options();
fflush(stdout);
}
tui_screen_t tui_screen_options(void) {
redraw_screen();
while(1) {
int event = tui_get_event();
if (event != TUI_EVENT_INPUT) continue;
int input = tui_last_input;
switch (input) {
case TUI_INPUT_DOWN:
case TUI_INPUT_TAB:
if (tui_options_is_editing_boot_args) break;
if (++tui_options_nav_selection > 5) tui_options_nav_selection = 0;
tui_screen_options_nav();
tui_screen_options_options();
fflush(stdout);
break;
case TUI_INPUT_UP:
case TUI_INPUT_TAB_BACK:
if (tui_options_is_editing_boot_args) break;
if (--tui_options_nav_selection < 0) tui_options_nav_selection = 5;
tui_screen_options_nav();
tui_screen_options_options();
fflush(stdout);
break;
case TUI_INPUT_SELECT:
if (tui_options_is_editing_boot_args && tui_last_key == ' ' && tui_options_boot_args[strlen(tui_options_boot_args)] == '\x00') {
size_t max_len = sizeof(tui_options_boot_args) - 1;
size_t len = strlen(tui_options_boot_args);
if (len >= max_len) {
break;
}
tui_options_boot_args[len] = ' ';
tui_options_boot_args[len + 1] = '\x00';
tui_options_boot_args_cursor++;
tui_screen_options_options();
fflush(stdout);
break;
}
switch(tui_options_nav_selection) {
case 0:
return MAIN_SCREEN;
// case 1:
// tui_options_allow_untested = !tui_options_allow_untested;
// break;
case 1:
tui_options_safe_mode = !tui_options_safe_mode;
break;
case 2:
tui_options_verbose_boot = !tui_options_verbose_boot;
break;
case 3:
tui_options_force_revert = !tui_options_force_revert;
break;
case 4:
tui_options_is_editing_boot_args = !tui_options_is_editing_boot_args;
tui_options_boot_args_cursor = tui_options_is_editing_boot_args ? strlen(tui_options_boot_args) : 0;
break;
case 5:
tui_options_flower_chain = !tui_options_flower_chain;
break;
}
tui_screen_options_nav();
tui_screen_options_options();
fflush(stdout);
break;
case TUI_INPUT_MOUSE_MOVE:
tui_screen_options_nav();
tui_screen_options_options();
fflush(stdout);
break;
case TUI_INPUT_MOUSE_DOWN:
if (tui_mouse_y == tui_y_offset + 24 - 2 &&
tui_mouse_x >= tui_x_offset + 80 - 12 &&
tui_mouse_x <= tui_x_offset + 80 - 12 + 10) {
tui_options_nav_selection = 0;
tui_options_nav_mouse_select = 0;
redraw_screen();
}
#define MOUSEDOWN_HANDLER(y, val) \
if (tui_mouse_y == tui_y_offset + y && \
tui_mouse_x >= tui_x_offset + 5 - 4 && \
tui_mouse_x <= tui_x_offset + 5 + 34) { \
tui_options_nav_selection = val; \
tui_options_nav_mouse_select = val; \
tui_screen_options_nav(); \
tui_screen_options_options(); \
fflush(stdout); \
}
if (!tui_options_is_editing_boot_args) {
MOUSEDOWN_HANDLER(8, 1);
MOUSEDOWN_HANDLER(9, 2);
MOUSEDOWN_HANDLER(10, 3);
MOUSEDOWN_HANDLER(16, 5);
}
MOUSEDOWN_HANDLER(14, 4);
MOUSEDOWN_HANDLER(15, 4);
#undef MOUSEDOWN_HANDLER
break;
case TUI_INPUT_MOUSE_UP:
if (tui_mouse_y == tui_y_offset + 24 - 2 &&
tui_mouse_x >= tui_x_offset + 80 - 12 &&
tui_mouse_x <= tui_x_offset + 80 - 12 + 10 &&
tui_options_nav_mouse_select == 0) {
return MAIN_SCREEN;
}
#define MOUSEUP_HANDLER(y, val, option, e) \
if (tui_mouse_y == tui_y_offset + y && \
tui_mouse_x >= tui_x_offset + 5 - 4 && \
tui_mouse_x <= tui_x_offset + 5 + 34 && \
tui_options_nav_mouse_select == val) { \
tui_options_##option = !tui_options_##option; \
e \
tui_screen_options_nav(); \
tui_screen_options_options(); \
fflush(stdout); \
}
if (!tui_options_is_editing_boot_args) {
MOUSEUP_HANDLER(8, 1, safe_mode, );
MOUSEUP_HANDLER(9, 2, verbose_boot, );
MOUSEUP_HANDLER(10, 3, force_revert, );
MOUSEUP_HANDLER(16, 5, flower_chain, );
}
#define BOOTARGS_HANDLER \
tui_options_boot_args_cursor = tui_options_is_editing_boot_args ? strlen(tui_options_boot_args) : 0;
MOUSEUP_HANDLER(14, 4, is_editing_boot_args, BOOTARGS_HANDLER);
MOUSEUP_HANDLER(15, 4, is_editing_boot_args, BOOTARGS_HANDLER);
#undef MOUSEUP_HANDLER
tui_options_nav_mouse_select = -1;
break;
case TUI_INPUT_BACKSPACE:
if (tui_options_is_editing_boot_args && tui_options_boot_args_cursor > 0) {
memmove(tui_options_boot_args + tui_options_boot_args_cursor - 1, tui_options_boot_args + tui_options_boot_args_cursor, strlen(tui_options_boot_args) - tui_options_boot_args_cursor);
tui_options_boot_args[strlen(tui_options_boot_args) - 1] = '\x00';
tui_options_boot_args_cursor--;
tui_screen_options_options();
fflush(stdout);
}
break;
case TUI_INPUT_NONE:
if (tui_options_is_editing_boot_args && tui_options_boot_args[strlen(tui_options_boot_args)] == '\x00') {
size_t max_len = sizeof(tui_options_boot_args) - 1;
size_t len = strlen(tui_options_boot_args);
if (len >= max_len) {
break;
}
memmove(tui_options_boot_args + tui_options_boot_args_cursor + 1, tui_options_boot_args + tui_options_boot_args_cursor, strlen(tui_options_boot_args) - tui_options_boot_args_cursor);
tui_options_boot_args[tui_options_boot_args_cursor] = tui_last_key;
tui_options_boot_args[len + 1] = '\x00';
tui_options_boot_args_cursor++;
tui_screen_options_options();
fflush(stdout);
}
break;
case TUI_INPUT_LEFT:
if (tui_options_is_editing_boot_args) {
if (tui_options_boot_args_cursor > 0) {
tui_options_boot_args_cursor--;
tui_screen_options_options();
fflush(stdout);
}
}
break;
case TUI_INPUT_RIGHT:
if (tui_options_is_editing_boot_args) {
if (tui_options_boot_args_cursor < (int)strlen(tui_options_boot_args)) {
tui_options_boot_args_cursor++;
tui_screen_options_options();
fflush(stdout);
}
}
break;
}
}
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifdef WITH_GUI
#include "app.hpp"
#include <string>
#include "../utils/constants.h"
bool PalerainApp::OnInit() {
auto* frame = new wxFrame(
nullptr,
wxID_ANY,
"palera1n - Version " + wxString(PALERAIN_VERSION),
wxDefaultPosition,
wxSize(480, 360),
wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER)
);
new wxStaticText(frame, wxID_ANY, "my cute ui", wxPoint(10, 10));
frame->Show(true);
return true;
}
wxIMPLEMENT_APP_NO_MAIN(PalerainApp);
#endif // WITH_GUI
+10
View File
@@ -0,0 +1,10 @@
#ifdef WITH_GUI
#pragma once
#include <wx/wx.h>
class PalerainApp : public wxApp {
public:
bool OnInit() override;
};
#endif // WITH_GUI
-13
View File
@@ -1,13 +0,0 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>platform-application</key>
<true/>
<key>com.apple.private.security.no-container</key>
<true/>
<key>com.apple.security.iokit-user-client-class</key>
<array>
<string>IOUserClient</string>
</array>
</dict>
</plist>
-257
View File
@@ -1,257 +0,0 @@
/*
* pongoOS - https://checkra.in
*
* Copyright (C) 2019-2022 checkra1n team
*
* This file is part of pongoOS.
*
* 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.
*
*/
#ifndef USE_LIBUSB
#include <errno.h>
#include <fcntl.h> // open
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> // exit, strtoull
#include <string.h> // strlen, strerror, memcpy, memmove
#include <unistd.h> // close
#include <wordexp.h>
#include <sys/mman.h> // mmap, munmap
#include <sys/stat.h> // fstst
#include <mach/mach.h>
#include <palerain.h>
#include <CoreFoundation/CoreFoundation.h>
#define ERR(...) LOG(LOG_VERBOSE, __VA_ARGS__)
const char *usb_strerror(usb_ret_t err)
{
return mach_error_string(err);
}
usb_ret_t USBControlTransfer(usb_device_handle_t handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint32_t wLength, void *data, uint32_t *wLenDone)
{
IOUSBDevRequest request =
{
.bmRequestType = bmRequestType,
.bRequest = bRequest,
.wValue = wValue,
.wIndex = wIndex,
.wLength = wLength,
.pData = data,
};
usb_ret_t ret = (*handle)->ControlRequest(handle, 0, &request);
if(wLenDone) *wLenDone = request.wLenDone;
return ret;
}
usb_ret_t USBBulkUpload(usb_device_handle_t handle, void *data, uint32_t len)
{
return (*handle)->WritePipe(handle, 2, data, len);
}
static void FoundDevice(void *refCon, io_iterator_t it)
{
stuff_t *stuff = refCon;
if(stuff->regID)
{
return;
}
io_service_t usbDev = MACH_PORT_NULL;
while((usbDev = IOIteratorNext(it)))
{
uint64_t regID;
kern_return_t ret = IORegistryEntryGetRegistryEntryID(usbDev, &regID);
if(ret != KERN_SUCCESS)
{
ERR("IORegistryEntryGetRegistryEntryID: %s", mach_error_string(ret));
goto next;
}
SInt32 score = 0;
IOCFPlugInInterface **plugin = NULL;
ret = IOCreatePlugInInterfaceForService(usbDev, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score);
if(ret != KERN_SUCCESS)
{
ERR("IOCreatePlugInInterfaceForService(usbDev): %s", mach_error_string(ret));
goto next;
}
HRESULT result = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*)&stuff->dev);
(*plugin)->Release(plugin);
if(result != 0)
{
ERR("QueryInterface(dev): 0x%x", result);
goto next;
}
ret = (*stuff->dev)->USBDeviceOpenSeize(stuff->dev);
if(ret != KERN_SUCCESS)
{
ERR("USBDeviceOpenSeize: %s", mach_error_string(ret));
}
else
{
ret = (*stuff->dev)->SetConfiguration(stuff->dev, 1);
if(ret != KERN_SUCCESS)
{
ERR("SetConfiguration: %s", mach_error_string(ret));
}
else
{
IOUSBFindInterfaceRequest request =
{
.bInterfaceClass = kIOUSBFindInterfaceDontCare,
.bInterfaceSubClass = kIOUSBFindInterfaceDontCare,
.bInterfaceProtocol = kIOUSBFindInterfaceDontCare,
.bAlternateSetting = kIOUSBFindInterfaceDontCare,
};
io_iterator_t iter = MACH_PORT_NULL;
ret = (*stuff->dev)->CreateInterfaceIterator(stuff->dev, &request, &iter);
if(ret != KERN_SUCCESS)
{
ERR("CreateInterfaceIterator: %s", mach_error_string(ret));
}
else
{
io_service_t usbIntf = MACH_PORT_NULL;
while((usbIntf = IOIteratorNext(iter)))
{
ret = IOCreatePlugInInterfaceForService(usbIntf, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score);
IOObjectRelease(usbIntf);
if(ret != KERN_SUCCESS)
{
ERR("IOCreatePlugInInterfaceForService(usbIntf): %s", mach_error_string(ret));
continue;
}
result = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID*)&stuff->handle);
(*plugin)->Release(plugin);
if(result != 0)
{
ERR("QueryInterface(intf): 0x%x", result);
continue;
}
ret = (*stuff->handle)->USBInterfaceOpen(stuff->handle);
if(ret != KERN_SUCCESS)
{
ERR("USBInterfaceOpen: %s", mach_error_string(ret));
}
else
{
io_start(stuff);
stuff->regID = regID;
while((usbIntf = IOIteratorNext(iter))) IOObjectRelease(usbIntf);
IOObjectRelease(iter);
while((usbDev = IOIteratorNext(it))) IOObjectRelease(usbDev);
IOObjectRelease(usbDev);
return;
}
(*stuff->handle)->Release(stuff->handle);
stuff->handle = NULL;
}
IOObjectRelease(iter);
}
}
}
next:;
if(stuff->dev)
{
(*stuff->dev)->USBDeviceClose(stuff->dev);
(*stuff->dev)->Release(stuff->dev);
stuff->dev = NULL;
}
IOObjectRelease(usbDev);
}
}
static void LostDevice(void *refCon, io_iterator_t it)
{
stuff_t *stuff = refCon;
io_service_t usbDev = MACH_PORT_NULL;
while((usbDev = IOIteratorNext(it)))
{
uint64_t regID;
kern_return_t ret = IORegistryEntryGetRegistryEntryID(usbDev, &regID);
IOObjectRelease(usbDev);
if(ret == KERN_SUCCESS && stuff->regID == regID)
{
io_stop(stuff);
stuff->regID = 0;
(*stuff->handle)->USBInterfaceClose(stuff->handle);
(*stuff->handle)->Release(stuff->handle);
(*stuff->dev)->USBDeviceClose(stuff->dev);
(*stuff->dev)->Release(stuff->dev);
}
}
}
static const int pongo_usb_vendor = PONGO_USB_VENDOR;
static const int pongo_usb_product = PONGO_USB_PRODUCT;
int wait_for_pongo(void) {
kern_return_t ret;
stuff_t stuff = {0};
io_iterator_t found, lost;
void* cfdict_keys[3];
void* cfdict_values[3];
cfdict_keys[0] = (void*)CFSTR("IOProviderClass");
cfdict_keys[1] = (void*)CFSTR("idVendor");
cfdict_keys[2] = (void*)CFSTR("idProduct");
cfdict_values[0] = (void*)CFSTR("IOUSBDevice");
cfdict_values[1] = (void*)CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pongo_usb_vendor);
cfdict_values[2] = (void*)CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pongo_usb_product);
CFDictionaryRef cfdict = CFDictionaryCreate(kCFAllocatorDefault, (const void**)cfdict_keys, (const void**)cfdict_values, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
IONotificationPortRef notifyPort = IONotificationPortCreate(kIOMasterPortDefault);
CFRetain(cfdict);
// CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPort), kCFRunLoopDefaultMode);
ret = IOServiceAddMatchingNotification(notifyPort, kIOFirstMatchNotification, cfdict, &FoundDevice, &stuff, &found);
if(ret != KERN_SUCCESS)
{
ERR("IOServiceAddMatchingNotification: %s", mach_error_string(ret));
return -1;
}
FoundDevice(&stuff, found);
CFRetain(cfdict);
ret = IOServiceAddMatchingNotification(notifyPort, kIOTerminatedNotification, cfdict, &LostDevice, &stuff, &lost);
if(ret != KERN_SUCCESS)
{
ERR("IOServiceAddMatchingNotification: %s", mach_error_string(ret));
return -1;
}
LostDevice(&stuff, lost);
// CFRunLoopRun();
while (get_spin()) {
sleep(1);
}
CFRelease(cfdict);
return 0;
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
-269
View File
@@ -1,269 +0,0 @@
/*
* pongoOS - https://checkra.in
*
* Copyright (C) 2019-2023 checkra1n team
*
* This file is part of pongoOS.
*
* 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.
*
*/
#ifdef USE_LIBUSB
#include <errno.h>
#include <fcntl.h> // open
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> // exit, strtoull
#include <string.h> // strlen, strerror, memcpy, memmove
#include <unistd.h> // close
#include <sys/mman.h> // mmap, munmap
#include <sys/stat.h> // fstst
#include <palerain.h>
#define ERR(...) LOG(LOG_ERROR, __VA_ARGS__)
void io_start(stuff_t *stuff);
void io_stop(stuff_t *stuff);
const char *usb_strerror(usb_ret_t err)
{
return libusb_error_name(err);
}
usb_ret_t USBControlTransfer(usb_device_handle_t handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint32_t wLength, void *data, uint32_t *wLenDone)
{
usb_ret_t r = libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, 0);
if(r < 0) return r;
if(wLenDone) *wLenDone = r;
return USB_RET_SUCCESS;
}
usb_ret_t USBBulkUpload(usb_device_handle_t handle, void *data, int len)
{
static uint32_t maxLen = 0;
int transferred = 0;
usb_ret_t r;
if(maxLen == 0)
{
r = libusb_bulk_transfer(handle, 2, data, len, &transferred, 0);
if(r == LIBUSB_SUCCESS)
{
return transferred == len ? USB_RET_SUCCESS : LIBUSB_ERROR_INTERRUPTED;
}
else if(r != LIBUSB_ERROR_NO_MEM)
{
return r;
}
#if defined(__linux__)
// We only get here on ENOMEM
FILE *f = fopen("/sys/module/usbcore/parameters/usbfs_memory_mb", "r");
if(f)
{
char str[32]; // More than enough to hold a uint64 in decimal
size_t s = fread(str, 1, sizeof(str), f);
fclose(f);
if(s == 0 || s >= sizeof(str)) return r;
str[s] = '\0';
char *end = NULL;
unsigned long long max = strtoull(str, &end, 0);
// Using the limit as-is will lead to ENOMEM, so we multiply
// by half a MB and impose an appropriate max value.
if(*end == '\n') ++end;
if(*end != '\0' || max == 0 || max >= 0x2000) return r;
maxLen = (uint32_t)(max << 19);
}
else
#endif
{
// Just 1MB by default?
maxLen = 0x100000;
}
}
// If we get here, we have to chunk our data
for(int done = transferred; done < len; )
{
uint32_t chunk = len - done;
if(chunk > maxLen) chunk = maxLen;
transferred = 0;
r = libusb_bulk_transfer(handle, 2, (unsigned char*)data + done, chunk, &transferred, 0);
done += transferred;
if(r == LIBUSB_SUCCESS) continue;
if(r != LIBUSB_ERROR_NO_MEM || maxLen <= 0x40) return r;
maxLen /= 2;
}
return LIBUSB_SUCCESS;
}
static int FoundDevice(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *arg)
{
stuff_t *stuff = arg;
if(stuff->handle)
{
return LIBUSB_SUCCESS;
}
LOG(LOG_VERBOSE, "PongoOS USB Device connected");
libusb_device_handle *handle;
int r = libusb_open(dev, &handle);
if(r != LIBUSB_SUCCESS)
{
ERR("libusb_open: %s", libusb_error_name(r));
return r;
}
/* nah there would not be a kernel driver for pongoOS in Darwin */
#if !defined(__APPLE__)
r = libusb_detach_kernel_driver(handle, 0);
if(r != LIBUSB_SUCCESS && r != LIBUSB_ERROR_NOT_FOUND)
{
ERR("libusb_detach_kernel_driver: %s", libusb_error_name(r));
return r;
}
#endif
r = libusb_set_configuration(handle, 1);
if(r != LIBUSB_SUCCESS)
{
ERR("libusb_set_configuration: %s", libusb_error_name(r));
return r;
}
r = libusb_claim_interface(handle, 0);
if(r != LIBUSB_SUCCESS)
{
ERR("libusb_claim_interface: %s", libusb_error_name(r));
return r;
}
stuff->dev = dev;
stuff->handle = handle;
io_start(stuff);
return LIBUSB_SUCCESS;
}
static int LostDevice(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *arg)
{
stuff_t *stuff = arg;
if(stuff->dev != dev)
{
return LIBUSB_SUCCESS;
}
LOG(LOG_VERBOSE, "PongoOS USB Device disconnected");
io_stop(stuff);
libusb_close(stuff->handle);
libusb_unref_device(dev);
stuff->handle = NULL;
stuff->dev = NULL;
return LIBUSB_SUCCESS;
}
int wait_for_pongo(void)
{
stuff_t stuff = {0};
libusb_hotplug_callback_handle hp[2];
libusb_context* ctx = NULL;
int r = libusb_init(&ctx);
if(r != LIBUSB_SUCCESS)
{
ERR("libusb_init: %s", libusb_error_name(r));
return -1;
}
if(!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
{
ERR("libusb: no hotplug capability");
libusb_exit(ctx);
return -1;
}
r = libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, PONGO_USB_VENDOR, PONGO_USB_PRODUCT, LIBUSB_HOTPLUG_MATCH_ANY, LostDevice, &stuff, &hp[1]);
if(r != LIBUSB_SUCCESS)
{
ERR("libusb_hotplug: %s", libusb_error_name(r));
libusb_exit(ctx);
return -1;
}
while (1) {
r = libusb_handle_events(ctx);
if(r != LIBUSB_SUCCESS)
{
ERR("libusb_handle_events: %s", libusb_error_name(r));
break;
}
libusb_device **list;
ssize_t sz = libusb_get_device_list(ctx, &list);
bool done = false;
if(sz < 0)
{
ERR("libusb_get_device_list: %s", libusb_error_name((int)sz));
libusb_exit(ctx);
return -1;
}
for(ssize_t i = 0; i < sz; ++i)
{
struct libusb_device_descriptor desc;
r = libusb_get_device_descriptor(list[i], &desc);
if(r != LIBUSB_SUCCESS)
{
ERR("libusb_get_device_descriptor: %s", libusb_error_name(r));
// continue anyway
}
if(desc.idVendor != PONGO_USB_VENDOR || desc.idProduct != PONGO_USB_PRODUCT)
{
libusb_unref_device(list[i]);
continue;
}
r = FoundDevice(ctx, list[i], LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, &stuff);
for (ssize_t j = i; j < sz; ++j) {
libusb_unref_device(list[j]);
}
if(r != LIBUSB_SUCCESS)
{
libusb_free_device_list(list, 0);
libusb_exit(ctx);
return -1;
} else {
done = true;
}
break;
}
libusb_free_device_list(list, 0);
if (done) goto end;
}
end:
libusb_exit(ctx);
return 0;
}
#else
/* ISO C forbids an empty translation unit */
extern char** environ;
#endif
+3
View File
@@ -0,0 +1,3 @@
#include "constants.h"
uint64_t palerain_flags = 0;
+10
View File
@@ -0,0 +1,10 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H
#define PALERAIN_VERSION "3.0.0"
#include <cstdint>
extern uint64_t palerain_flags;
#endif // CONSTANTS_H
+17
View File
@@ -0,0 +1,17 @@
#ifndef LOG_H
#define LOG_H
#define RESET_COLOR "\033[0m"
#define RED_COLOR "\033[31m"
#define GREEN_COLOR "\033[32m"
#define YELLOW_COLOR "\033[33m"
#define BLUE_COLOR "\033[34m"
#define MAGENTA_COLOR "\033[35m"
#define CYAN_COLOR "\033[36m"
#define WHITE_COLOR "\033[37m"
#define GRAY_COLOR "\033[90m"
#define LOG(fmt, ...) \
printf("(%s:%d) => " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif // LOG_H
+73
View File
@@ -0,0 +1,73 @@
/*
* jbinit - https://github.com/palera1n/jbinit
*
* This file is part of jbinit
*
* SPDX-License-Identifier: MIT
*/
#ifndef PALEINFO_H
#define PALEINFO_H
#include <stdint.h>
#define PALEINFO_VERSION 2U
typedef uint64_t palerain_option_t;
// unified palera1n options
#define palerain_option_rootful (UINT64_C(1) << 0) /* rootful jailbreak */
#define palerain_option_rootless (UINT64_C(1) << 1) /* rootless jailbreak */
#define palerain_option_setup_rootful (UINT64_C(1) << 2) /* create fakefs */
// (UINT64_C(1) << 3) /* Deprecated and removed */
#define palerain_option_setup_partial_root (UINT64_C(1) << 4) /* fakefs creating should be partial */
#define palerain_option_checkrain_is_clone (UINT64_C(1) << 5) /* supplied checkra1n is checkra1n clone */
#define palerain_option_rootless_livefs (UINT64_C(1) << 6) /* mount root livefs on rootless */
#define palerain_option_ssv (UINT64_C(1) << 7) /* has signed system volume */
// (UINT64_C(1) << 8) /* reserved */
#define palerain_option_clean_fakefs (UINT64_C(1) << 9) /* clean fakefs, but does not delete it */
#define palerain_option_tui (UINT64_C(1) << 10) /* terminal user interface */
#define palerain_option_gui (UINT64_C(1) << 11) /* graphical user interface*/
#define palerain_option_dfuhelper_only (UINT64_C(1) << 12) /* dfuhelper only */
#define palerain_option_pongo_exit (UINT64_C(1) << 13) /* boot to clean pongo shell */
#define palerain_option_demote (UINT64_C(1) << 14) /* Demote effective production fuse status */
#define palerain_option_pongo_full (UINT64_C(1) << 15) /* Boot to pongo with default images and options */
#define palerain_option_palerain_version (UINT64_C(1) << 16) /* Print version */
#define palerain_option_exit_recovery (UINT64_C(1) << 17) /* Exit recovery mode */
#define palerain_option_reboot_device (UINT64_C(1) << 18) /* Reboot device in normal mode */
#define palerain_option_enter_recovery (UINT64_C(1) << 19) /* Enter recovery mode */
#define palerain_option_device_info (UINT64_C(1) << 20) /* Print device info */
#define palerain_option_no_colors (UINT64_C(1) << 21) /* no colors */
#define palerain_option_bind_mount (UINT64_C(1) << 22) /* bind mounts should be used (always true iOS 15+)*/
#define palerain_option_overlay (UINT64_C(1) << 23) /* there is an overlay (should always be true) */
#define palerain_option_force_revert (UINT64_C(1) << 24) /* Unjailbreak */
#define palerain_option_safemode (UINT64_C(1) << 25) /* Enter safe mode */
#define palerain_option_verbose_boot (UINT64_C(1) << 26) /* verbose boot */
// #define palerain_option_sf_ssh (UINT64_C(1) << 27) /* safe mode with bootstrap ssh */
// #define palerain_option_sf_launchdaemons (UINT64_C(1) << 28) /* safe mode with launchdaemons */
// #define palerain_option_emerg_mode (UINT64_C(1) << 29) /* emergency mode (early boot usb shell) */
#define palerain_option_jbinit_log_to_file (UINT64_C(1) << 30) /* deprecated (kept for compatibility) */
#define palerain_option_cli (UINT64_C(1) << 31) /* CLI mode */
#define palerain_option_telnetd (UINT64_C(1) << 32) /* Enable TELNET daemon */
#define palerain_option_flower_chain (UINT64_C(1) << 61) /* Flower chain */
#define palerain_option_test1 (UINT64_C(1) << 62) /* Developer test option 1 */
#define palerain_option_test2 (UINT64_C(1) << 63) /* Developer test option 2 */
#define PALEINFO_MAGIC 'PLSH'
#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wpadded"
/* paleinfo version 2, appended to ramdisk */
struct paleinfo {
uint32_t magic; /* 'PLSH' */
uint32_t version; /* 2 */
uint64_t kbase; /* kernel base */
uint64_t kslide; /* kernel slide */
uint64_t flags; /* unified palera1n flags */
char rootdev[0x10]; /* ex. disk0s1s8 */
};
#pragma clang diagnostic pop
#endif