feat: wxWidgets gui

This commit is contained in:
CLARATION committed 2026-06-19 17:51:51 -07:00
1 parent 7ee6976c7d
commit fa05fd34e1
53 files changed
+2494 -296

No files matched your search

+1 -3
View File
@@ -1,5 +1,3 @@
build/
.DS_Store
src/exploit/payloads/
src/exploit/userland/
src/exploit/logo.h
src/gen/
+6
View File
@@ -0,0 +1,6 @@
{
"cmake.loadCompileCommands": true,
"cmake.configureOnOpen": true,
"cmake.buildDirectory": "${workspaceFolder}/build",
"cmake.copyCompileCommands": "${workspaceFolder}/build/compile_commands.json",
}
+330 -33
View File
@@ -1,62 +1,359 @@
# Project
cmake_minimum_required(VERSION 3.10)
project(palera1n VERSION 3.0)
include(FetchContent)
include(ExternalProject)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra -DWX_PRECOMP")
# Option for GUI (wxWidgets)
option(WITH_GUI "Build with wxWidgets GUI" OFF)
option(WITH_STATIC "Build with static wxWidgets" OFF)
option(WITH_STATIC "Build with static wxWidgets / deps" OFF)
# Architectures
set(CMAKE_OSX_ARCHITECTURES "arm64")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Deps
set(DEPS_PREFIX ${CMAKE_BINARY_DIR}/deps)
# =========================
# wxWidgets
# =========================
if(WITH_GUI)
if(WITH_STATIC)
set(wxBUILD_SHARED OFF)
FetchContent_Declare(
wxWidgets
GIT_REPOSITORY https://github.com/wxWidgets/wxWidgets.git
GIT_SHALLOW ON
)
FetchContent_MakeAvailable(wxWidgets)
set(WX_LIBRARIES wxWidgets::core wxWidgets::base wxWidgets::net)
else()
find_package(wxWidgets REQUIRED COMPONENTS core base net)
include(${wxWidgets_USE_FILE})
set(WX_LIBRARIES ${wxWidgets_LIBRARIES})
endif()
if(WITH_STATIC)
set(wxBUILD_SHARED OFF CACHE BOOL "" FORCE)
FetchContent_Declare(
wxWidgets
GIT_REPOSITORY https://github.com/wxWidgets/wxWidgets.git
GIT_SHALLOW ON
)
FetchContent_MakeAvailable(wxWidgets)
set(WX_LIBRARIES wxcore wxbase wxnet)
else()
find_package(wxWidgets REQUIRED COMPONENTS core base net)
include(${wxWidgets_USE_FILE})
set(WX_LIBRARIES ${wxWidgets_LIBRARIES})
endif()
endif()
# Files
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS "src/*.cpp" "src/*.c" "src/*.h" "src/*.hpp")
# =========================
# JSON
# =========================
include(FetchContent)
FetchContent_Declare(
nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.3
)
FetchContent_MakeAvailable(nlohmann_json)
# =========================
# SOURCES
# =========================
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
"src/*.cpp"
"src/*.c"
"src/*.h"
"src/*.hpp"
)
# =========================
# TARGET
# =========================
if(APPLE AND WITH_GUI)
set(APP_ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/palera1n.icns)
add_executable(palera1n MACOSX_BUNDLE ${SOURCES})
set_target_properties(palera1n PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/resources/Info.plist)
elseif(APPLE)
add_executable(palera1n ${SOURCES})
target_sources(palera1n PRIVATE ${APP_ICON})
set_source_files_properties(${APP_ICON} PROPERTIES
MACOSX_PACKAGE_LOCATION "Resources"
)
set_target_properties(palera1n PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/resources/Info.plist
MACOSX_BUNDLE_ICON_FILE palera1n.icns
)
else()
add_executable(palera1n WIN32 ${SOURCES} resources/main.exe.manifest)
add_executable(palera1n ${SOURCES})
endif()
include_directories(${DEPS_PREFIX}/include)
link_directories(${DEPS_PREFIX}/lib)
# =========================
# APPLE FRAMEWORKS
# =========================
if(APPLE)
find_library(IOKIT IOKit)
find_library(COREFOUNDATION CoreFoundation)
target_link_libraries(palera1n PRIVATE ${IOKIT} ${COREFOUNDATION})
target_link_libraries(palera1n PRIVATE
${IOKIT}
${COREFOUNDATION}
)
endif()
# =========================
# wxWidgets
# =========================
if(WITH_GUI)
if(WITH_STATIC)
target_link_libraries(palera1n PRIVATE wxcore wxnet)
else()
target_link_libraries(palera1n PRIVATE ${wxWidgets_LIBRARIES})
target_link_libraries(palera1n PRIVATE ${WX_LIBRARIES})
target_compile_definitions(palera1n PRIVATE WITH_GUI)
endif()
target_compile_definitions(palera1n PRIVATE WITH_GUI)
target_link_libraries(palera1n PRIVATE nlohmann_json::nlohmann_json)
# =========================
# libimobiledevice
# =========================
if(WITH_GUI)
if(WITH_STATIC)
include(ExternalProject)
find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config REQUIRED)
set(PKG_ENV
env
PKG_CONFIG=${PKG_CONFIG_EXECUTABLE}
PKG_CONFIG_PATH=${DEPS_PREFIX}/lib/pkgconfig:${DEPS_PREFIX}/share/pkgconfig
PKG_CONFIG_LIBDIR=${DEPS_PREFIX}/lib/pkgconfig:${DEPS_PREFIX}/share/pkgconfig
CPPFLAGS=-I${DEPS_PREFIX}/include
LDFLAGS=-L${DEPS_PREFIX}/lib
C_INCLUDE_PATH=${DEPS_PREFIX}/include
CPLUS_INCLUDE_PATH=${DEPS_PREFIX}/include
libcurl_CFLAGS=-I/Applications/Xcode-26.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/usr/include
libcurl_LIBS=-lcurl
mbedtls_INCLUDES=${DEPS_PREFIX}/include
mbedtls_LIBDIR=${DEPS_PREFIX}/lib
mbedtls_LIBS=-lmbedtls\ -lmbedx509\ -lmbedcrypto
)
# =========================
# mbedTLS
# =========================
ExternalProject_Add(mbedtls_ep
GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git
GIT_TAG mbedtls-3.5.2
UPDATE_COMMAND ""
PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/patches/0001-Allow-empty-x509-cert-issuer.patch
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${DEPS_PREFIX}
-DENABLE_TESTING=OFF
-DENABLE_PROGRAMS=OFF
-DBUILD_SHARED_LIBS=OFF
INSTALL_DIR ${DEPS_PREFIX}
)
# =========================
# libplist
# =========================
ExternalProject_Add(libplist_ep
GIT_REPOSITORY https://github.com/libimobiledevice/libplist.git
GIT_TAG 2117b8fdb6b4096455bd2041a63e59a028120136
UPDATE_COMMAND ""
CONFIGURE_COMMAND
${PKG_ENV}
./autogen.sh
--prefix=${DEPS_PREFIX}
--enable-static
--disable-shared
BUILD_COMMAND make -j
INSTALL_COMMAND make install
BUILD_IN_SOURCE 1
)
# =========================
# libimobiledevice-glue
# =========================
ExternalProject_Add(limd_glue_ep
GIT_REPOSITORY https://github.com/libimobiledevice/libimobiledevice-glue.git
GIT_TAG 362f7848ac89b74d9dd113b38b51ecb601f76094
UPDATE_COMMAND ""
CONFIGURE_COMMAND
${PKG_ENV}
./autogen.sh
--prefix=${DEPS_PREFIX}
--enable-static
--disable-shared
BUILD_COMMAND make -j
INSTALL_COMMAND make install
BUILD_IN_SOURCE 1
DEPENDS libplist_ep
)
# =========================
# libusbmuxd
# =========================
ExternalProject_Add(libusbmuxd_ep
GIT_REPOSITORY https://github.com/libimobiledevice/libusbmuxd.git
GIT_TAG a7f0543fb1ecb20ac7121c0fd77297200e0e43fc
UPDATE_COMMAND ""
CONFIGURE_COMMAND
${PKG_ENV}
./autogen.sh
--prefix=${DEPS_PREFIX}
--enable-static
--disable-shared
BUILD_COMMAND make -j
INSTALL_COMMAND make install
BUILD_IN_SOURCE 1
DEPENDS libplist_ep limd_glue_ep
)
# =========================
# libtatsu
# =========================
ExternalProject_Add(libtatsu_ep
GIT_REPOSITORY https://github.com/libimobiledevice/libtatsu.git
GIT_SHALLOW 1
UPDATE_COMMAND ""
CONFIGURE_COMMAND
${PKG_ENV}
./autogen.sh
--prefix=${DEPS_PREFIX}
--enable-static
--disable-shared
BUILD_COMMAND make -j
INSTALL_COMMAND make install
BUILD_IN_SOURCE 1
DEPENDS libplist_ep
)
# =========================
# libimobiledevice
# =========================
ExternalProject_Add(libimobiledevice_ep
GIT_REPOSITORY https://github.com/libimobiledevice/libimobiledevice.git
GIT_TAG ed0d66d0341562731bb19928dfe48155509fa7a7
UPDATE_COMMAND ""
CONFIGURE_COMMAND
${PKG_ENV}
./autogen.sh
--prefix=${DEPS_PREFIX}
--with-mbedtls
--enable-static
--disable-shared
BUILD_COMMAND make -j
INSTALL_COMMAND make install
BUILD_IN_SOURCE 1
DEPENDS mbedtls_ep libplist_ep libusbmuxd_ep limd_glue_ep libtatsu_ep
)
# =========================
# libirecovery
# =========================
ExternalProject_Add(libirecovery_ep
GIT_REPOSITORY https://github.com/libimobiledevice/libirecovery.git
GIT_TAG 7ce02c347b7c26e59498e6af31c9da51018d0fa1
UPDATE_COMMAND ""
CONFIGURE_COMMAND
${PKG_ENV}
./autogen.sh
--prefix=${DEPS_PREFIX}
--enable-static
--disable-shared
BUILD_COMMAND make -j
INSTALL_COMMAND make install
BUILD_IN_SOURCE 1
DEPENDS libplist_ep libusbmuxd_ep limd_glue_ep libtatsu_ep
)
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")
target_include_directories(palera1n PRIVATE
${DEPS_PREFIX}/include
)
if(APPLE)
find_library(IOKIT IOKit)
find_library(COREFOUNDATION CoreFoundation)
find_library(SECURITY Security)
target_link_libraries(palera1n PRIVATE
${IOKIT}
${COREFOUNDATION}
${SECURITY}
)
endif()
target_link_libraries(palera1n PRIVATE
${DEPS_PREFIX}/lib/libimobiledevice-1.0.a
${DEPS_PREFIX}/lib/libirecovery-1.0.a
${DEPS_PREFIX}/lib/libusbmuxd-2.0.a
${DEPS_PREFIX}/lib/libplist-2.0.a
${DEPS_PREFIX}/lib/libimobiledevice-glue-1.0.a
${DEPS_PREFIX}/lib/libtatsu.a
)
target_link_libraries(palera1n PRIVATE
${DEPS_PREFIX}/lib/libmbedtls.a
${DEPS_PREFIX}/lib/libmbedx509.a
${DEPS_PREFIX}/lib/libmbedcrypto.a
)
target_link_libraries(palera1n PRIVATE
curl
)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(IMD REQUIRED libimobiledevice-1.0)
pkg_check_modules(IRECOVERY REQUIRED libirecovery-1.0)
pkg_check_modules(PLIST REQUIRED libplist-2.0)
pkg_check_modules(USBMUXD REQUIRED libusbmuxd-2.0)
target_include_directories(palera1n PRIVATE
${IMD_INCLUDE_DIRS}
${IRECOVERY_INCLUDE_DIRS}
${PLIST_INCLUDE_DIRS}
${USBMUXD_INCLUDE_DIRS}
)
target_link_libraries(palera1n PRIVATE
${IMD_LIBRARIES}
${IRECOVERY_LIBRARIES}
${PLIST_LIBRARIES}
${USBMUXD_LIBRARIES}
)
target_compile_options(palera1n PRIVATE
${IMD_CFLAGS_OTHER}
${IRECOVERY_INCLUDE_DIRS}
${PLIST_CFLAGS_OTHER}
${USBMUXD_CFLAGS_OTHER}
)
endif()
endif()
+7 -5
View File
@@ -5,19 +5,21 @@ WITH_STATIC ?= 0
BUILD_TYPE ?= Debug
payloads:
@mkdir -p src/exploit/payloads
@for file in payloads/*; do \
@for file in images/*; do \
name=$$(basename "$$file"); \
name=$${name%.*}; \
echo " XXD $$file"; \
xxd -i $$file > src/exploit/$$file.h; \
xxd -i -n "$$name" "$$file" > "src/gen/images/$$name.h"; \
done
xxd -i resources/logo.png > src/exploit/logo.h
xxd -i -n "DFUHelperDeviceInfo" resources/DFUHelperDeviceInfo.json > src/gen/DFUHelperDeviceInfo.h
palera1n: payloads
@cmake -S . -B build \
-DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \
-DWITH_GUI=$(WITH_GUI) \
-DWITH_STATIC=$(WITH_STATIC) && \
cmake --build build -- -j$(sysctl -n hw.ncpu)
cmake --build build -- -j4
palera1n_xcode: payloads
@cmake -S . -B build \
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,33 @@
From a2d012f3ba459f6debe636b576ad9aeab7b3c2aa Mon Sep 17 00:00:00 2001
From: Nick Chan <[email protected]>
Date: Sat, 27 May 2023 23:50:23 +0800
Subject: [PATCH] Allow empty x509 cert issuer
---
library/x509_crt.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/library/x509_crt.c b/library/x509_crt.c
index cf62532f2..ef25b3d77 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1061,13 +1061,13 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt,
if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- mbedtls_x509_crt_free(crt);
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
+ /*mbedtls_x509_crt_free(crt);
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);*/
}
if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) {
- mbedtls_x509_crt_free(crt);
- return ret;
+ /*mbedtls_x509_crt_free(crt);
+ return ret;*/
}
crt->issuer_raw.len = p - crt->issuer_raw.p;
--
2.39.1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+452
View File
@@ -0,0 +1,452 @@
{
"devicemap":{
"iPhone6,1":"iphonese",
"iPhone6,2":"iphonese",
"iPhone7,1":"iphone6s",
"iPhone7,2":"iphone6s",
"iPhone8,1":"iphone6s",
"iPhone8,2":"iphone6s",
"iPhone8,4":"iphonese",
"iPhone9,1":"iphone7",
"iPhone9,2":"iphone7",
"iPhone9,3":"iphone7",
"iPhone9,4":"iphone7",
"iPhone10,1":"iphone8",
"iPhone10,2":"iphone8",
"iPhone10,4":"iphone8",
"iPhone10,5":"iphone8",
"iPhone10,3":"iphonex",
"iPhone10,6":"iphonex",
"iPhone11,2":"iphonex",
"iPhone11,4":"iphonex",
"iPhone11,6":"iphonex",
"iPhone11,8":"iphonex",
"iPhone12,1":"iphonex",
"iPhone12,3":"iphonex",
"iPhone12,5":"iphonex",
"iPhone12,8":"iphone8",
"iPad4,1":"ipad",
"iPad4,2":"ipad",
"iPad4,3":"ipad",
"iPad5,3":"ipad",
"iPad5,4":"ipad",
"iPad6,3":"ipad",
"iPad6,4":"ipad",
"iPad6,7":"ipad",
"iPad6,8":"ipad",
"iPad6,11":"ipad",
"iPad6,12":"ipad",
"iPad7,1":"ipad",
"iPad7,2":"ipad",
"iPad7,3":"ipad",
"iPad7,4":"ipad",
"iPad7,5":"ipad",
"iPad7,6":"ipad",
"iPad7,11":"ipad",
"iPad7,12":"ipad",
"iPad8,1":"ipad",
"iPad8,2":"ipad",
"iPad8,3":"ipad",
"iPad8,4":"ipad",
"iPad8,5":"ipad",
"iPad8,6":"ipad",
"iPad8,7":"ipad",
"iPad8,8":"ipad",
"iPad8,9":"ipad",
"iPad8,10":"ipad",
"iPad8,11":"ipad",
"iPad8,12":"ipad",
"iPad11,3":"ipad",
"iPad11,4":"ipad",
"iPad11,6":"ipad",
"iPad11,7":"ipad",
"iPad4,4":"ipadmini",
"iPad4,5":"ipadmini",
"iPad4,6":"ipadmini",
"iPad4,7":"ipadmini",
"iPad4,8":"ipadmini",
"iPad4,9":"ipadmini",
"iPad5,1":"ipadmini",
"iPad5,2":"ipadmini",
"iPod7,1":"ipodtouch",
"iPod9,1":"ipodtouch7",
"AppleTV5,3":"appletv4",
"AppleTV6,2":"appletv4k"
},
"devicelayout":{
"ipodtouch7":{
"image_name":"ipodtouch",
"image_width":116,
"image_height":240,
"image_offset_x":100,
"buttons":{
"top":{
"name":"– Top button",
"x":192,
"y":-4
},
"vol_down":{
"name":"Volume down –",
"x":8,
"y":62
}
},
"sequence":"ipodtouch7"
},
"ipodtouch":{
"image_name":"ipodtouch",
"image_width":116,
"image_height":240,
"image_offset_x":100,
"buttons":{
"top":{
"name":"– Top button",
"x":196,
"y":-4
},
"home":{
"name":"Home button –",
"x":50,
"y":210
}
},
"sequence":"iphone-old"
},
"iphonese":{
"image_name":"iphonese",
"image_width":119,
"image_height":240,
"image_offset_x":100,
"buttons":{
"top":{
"name":"– Top button",
"x":200,
"y":-4
},
"home":{
"name":"Home button –",
"x":56,
"y":210
}
},
"sequence":"iphone-old"
},
"iphone6s":{
"image_name":"iphone6s",
"image_width":123,
"image_height":240,
"image_offset_x":100,
"buttons":{
"side":{
"name":"– Side button",
"x":224,
"y":58
},
"home":{
"name":"Home button –",
"x":60,
"y":210
}
},
"sequence":"iphone6"
},
"iphone7":{
"image_name":"iphone7",
"image_width":123,
"image_height":240,
"image_offset_x":100,
"buttons":{
"side":{
"name":"– Side button",
"x":224,
"y":58
},
"vol_down":{
"name":"Volume down –",
"x":14,
"y":78
}
},
"sequence":"iphone7"
},
"iphone8":{
"image_name":"iphone8",
"image_width":120,
"image_height":240,
"image_offset_x":100,
"buttons":{
"side":{
"name":"– Side button",
"x":220,
"y":58
},
"vol_down":{
"name":"Volume down –",
"x":10,
"y":78
}
},
"sequence":"iphone8"
},
"iphonex":{
"image_name":"iphonex",
"image_width":121,
"image_height":240,
"image_offset_x":100,
"buttons":{
"side":{
"name":"– Side button",
"x":220,
"y":68
},
"vol_down":{
"name":"Volume down –",
"x":10,
"y":75
}
},
"sequence":"iphone8"
},
"ipad":{
"image_name":"ipad",
"image_width":170,
"image_height":240,
"buttons":{
"top":{
"name":"Top button",
"x":149,
"y":5
},
"home":{
"name":"Home button",
"x":89,
"y":225
}
},
"sequence":"iphone-old"
},
"ipadmini":{
"image_name":"ipadmini",
"image_width":163,
"image_height":240,
"buttons":{
"top":{
"name":"Top button",
"x":140,
"y":4
},
"home":{
"name":"Home button",
"x":86,
"y":224
}
},
"sequence":"iphone-old"
},
"appletv4":{
"image_name":"siriremote",
"image_width":79,
"image_height":240,
"image_offset_x":120,
"buttons":{
"menu":{
"name":"Menu –",
"x":84,
"y":84
},
"playpause":{
"name":"Play/Pause –",
"x":52,
"y":146
}
},
"sequence":"appletv4"
},
"appletv4k":{
"image_name":"atv_std_brd",
"image_width":300,
"image_height":240,
"image_offset_x":0,
"buttons":{
"dfu":{
"name":"-- DFU button",
"x":120,
"y":48
}
},
"sequence":"atv_standard_breakout"
}
},
"sequences":{
"ipodtouch7":[
{
"buttons":[
],
"description":"Click Start",
"duration":0
},
{
"buttons":[
"top",
"vol_down"
],
"description":"Press and hold the Top and Volume down buttons together",
"duration":4,
"action":"reboot"
},
{
"buttons":[
"vol_down"
],
"description":"Release the Top button BUT KEEP HOLDING the Volume down button",
"duration":10
}
],
"iphone-old":[
{
"buttons":[
],
"description":"Click Start",
"duration":0
},
{
"buttons":[
"top",
"home"
],
"description":"Press and hold the Top\n and Home buttons\n together",
"duration":4,
"action":"reboot"
},
{
"buttons":[
"home"
],
"description":"Release the Top button\n BUT KEEP HOLDING the\n Home button",
"duration":10
}
],
"iphone6":[
{
"buttons":[
],
"description":"Click Start",
"duration":0
},
{
"buttons":[
"side",
"home"
],
"description":"Press and hold the Side\n and Home buttons\n together",
"duration":4,
"action":"reboot"
},
{
"buttons":[
"home"
],
"description":"Release the Side button\n BUT KEEP HOLDING the\n Home button",
"duration":10
}
],
"iphone7":[
{
"buttons":[
],
"description":"Click Start",
"duration":0
},
{
"buttons":[
"side",
"vol_down"
],
"description":"Press and hold the Side\n and Volume down\n buttons together",
"duration":4,
"action":"reboot"
},
{
"buttons":[
"vol_down"
],
"description":"Release the Side button\n BUT KEEP HOLDING the\n Volume down button",
"duration":10
}
],
"iphone8":[
{
"buttons":[
],
"description":"Click Start",
"duration":0
},
{
"buttons":[
"side",
"vol_down"
],
"description":"Press and hold the Side\n and Volume down\n buttons together",
"duration":4,
"action":"reboot"
},
{
"buttons":[
"vol_down"
],
"description":"Release the Side button\n BUT KEEP HOLDING the\n Volume down button",
"duration":10
}
],
"appletv4":[
{
"buttons":[
],
"description":"Get Ready",
"duration":3
},
{
"buttons":[
"menu",
"playpause"
],
"description":"Press and hold Menu\n and Play/Pause together\n ",
"duration":7
},
{
"buttons":[
],
"description":"Release the buttons",
"duration":2
}
],
"atv_standard_breakout":[
{
"buttons":[
],
"description":"Get Ready",
"duration":3
},
{
"buttons":[
"dfu"
],
"description":"Press and hold the DFU\n button",
"duration":10,
"action":"reboot"
}
]
}
}
+20 -12
View File
@@ -1,16 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>palera.in.palera1n</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>palera1n</string>
<key>CFBundleIconFile</key>
<string>palera1n.icns</string>
<key>CFBundleIdentifier</key>
<string>palera1n</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>palera1n</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>NSHumanReadableCopyright</key>
<string>(c) 2026 palera1n</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.
+186
View File
@@ -0,0 +1,186 @@
#ifdef WITH_GUI
#include "event.hpp"
#include "wx/AppFrame.hpp"
#include "state.hpp"
#include "sequence.hpp"
#include "utils/log.h"
#include <wx/wx.h>
#include <thread>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libirecovery.h>
static inline DeviceState make_fresh_state()
{
return DeviceState{};
}
void normal_device_event_cb(
const idevice_event_t* event,
void* user_data)
{
#ifdef WITH_GUI
auto* frame = static_cast<MainFrame*>(user_data);
if (!frame || !event)
return;
#endif
DeviceState state = make_fresh_state();
if (event->event == IDEVICE_DEVICE_REMOVE)
{
#ifdef WITH_GUI
send_device_state(frame, state);
#endif
return;
}
if (event->event != IDEVICE_DEVICE_ADD)
return;
idevice_t device = nullptr;
if (idevice_new(&device, event->udid) != IDEVICE_E_SUCCESS)
return;
state.connected = true;
state.mode = DeviceMode::Normal;
state.udid = event->udid ? event->udid : "";
lockdownd_client_t client = nullptr;
if (lockdownd_client_new_with_handshake(device, &client, "palera1n") == LOCKDOWN_E_SUCCESS)
{
plist_t product = nullptr;
plist_t version = nullptr;
plist_t ecid = nullptr;
char *p = nullptr, *v = nullptr;
uint64_t ecid_val = 0;
lockdownd_get_value(client, nullptr, "ProductType", &product);
lockdownd_get_value(client, nullptr, "ProductVersion", &version);
lockdownd_get_value(client, nullptr, "UniqueChipID", &ecid);
if (product) plist_get_string_val(product, &p);
if (version) plist_get_string_val(version, &v);
if (ecid) plist_get_uint_val(ecid, &ecid_val);
state.productType = p ? p : "";
state.productVersion = v ? v : "";
state.ecid = ecid_val;
free(p);
free(v);
if (product) plist_free(product);
if (version) plist_free(version);
if (ecid) plist_free(ecid);
lockdownd_client_free(client);
}
idevice_free(device);
state.isSupported = SequenceIsSupported(state.productType);
#ifdef WITH_GUI
send_device_state(frame, state);
#endif
}
void recovery_device_event_cb(
const irecv_device_event_t* event,
void* user_data)
{
#ifdef WITH_GUI
auto* frame = static_cast<MainFrame*>(user_data);
if (!frame || !event)
return;
#endif
DeviceState state = make_fresh_state();
if (event->type == IRECV_DEVICE_REMOVE)
{
#ifdef WITH_GUI
send_device_state(frame, state);
#endif
return;
}
if (event->type != IRECV_DEVICE_ADD)
return;
state.connected = true;
if (event->mode == IRECV_K_DFU_MODE)
{
state.mode = DeviceMode::DFU;
#ifdef WITH_GUI
send_device_state(frame, state);
#endif
return;
}
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))
{
return;
}
state.mode = DeviceMode::Recovery;
uint64_t ecid_val = 0;
if (event->device_info && event->device_info->ecid)
ecid_val = event->device_info->ecid;
state.ecid = ecid_val;
irecv_client_t client = nullptr;
int attempts = 0;
const int max_attempts = 10;
while (attempts < max_attempts)
{
if (irecv_open_with_ecid(&client, state.ecid) == IRECV_E_SUCCESS)
break;
attempts++;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
if (client)
{
LOG("Opened client after %d attempts", attempts);
irecv_device_t device = nullptr;
if (irecv_devices_get_device_by_client(client, &device) == IRECV_E_SUCCESS && device)
{
LOG("device product type: %s", device->product_type);
LOG("device display name: %s", device->display_name);
state.productType = device->product_type ? device->product_type : "";
state.displayName = device->display_name ? device->display_name : "";
}
irecv_close(client);
}
else
{
LOG("Failed to open irecv client after retries");
}
state.isSupported = SequenceIsSupported(state.productType);
#ifdef WITH_GUI
send_device_state(frame, state);
#endif
}
#endif // WITH_GUI
+21
View File
@@ -0,0 +1,21 @@
#ifdef WITH_GUI
#ifndef EVENT_H
#define EVENT_H
#include "state.hpp"
#include <wx/wx.h>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libirecovery.h>
class MainFrame;
void normal_device_event_cb(const idevice_event_t* event, void* user_data);
void recovery_device_event_cb(const irecv_device_event_t* event, void* user_data);
#endif // EVENT_H
#endif // WITH_GUI
+10 -9
View File
@@ -5,12 +5,6 @@
#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
@@ -21,9 +15,16 @@
void print_credits() {
printf(
":: ========================== ::\n"
":: palera1n: " PALERAIN_VERSION "\n"
":: ========================== ::\n\n"
"#\n"
"# palera1n: " PALERAIN_VERSION "\n"
"#\n"
"# ======== Made by =======\n"
"# Made by: asdfugil, kok3shidoll, claration, mineek, staturnz\n"
"# ======== Thanks to =======\n"
"# Thanks to: llsc12, Nebula, Lrdsnow, nikias (libimobiledevice),\n"
"# checkra1n team (Siguza, axi0mx, littlelailo et al.),\n"
"# Procursus Team (Hayden Seay, Cameron Katri, Keto et.al)\n"
"# ==========================\n\n"
);
}
+88
View File
@@ -0,0 +1,88 @@
#ifdef WITH_GUI
#include <nlohmann/json.hpp>
#include "gen/DFUHelperDeviceInfo.h"
#include "sequence.hpp"
DfuSequence ParseSequence(const std::string& deviceKey)
{
DfuSequence seq;
static nlohmann::json j = nlohmann::json::parse(
DFUHelperDeviceInfo,
DFUHelperDeviceInfo + DFUHelperDeviceInfo_len
);
auto itMap = j["devicemap"].find(deviceKey);
if (itMap == j["devicemap"].end())
return seq;
const std::string deviceType = itMap.value();
auto itLayout = j["devicelayout"].find(deviceType);
if (itLayout == j["devicelayout"].end())
return seq;
const auto& layout = itLayout.value();
seq.imageName = layout.value("image_name", "");
seq.imageWidth = layout.value("image_width", 0);
seq.imageHeight = layout.value("image_height", 0);
seq.imageOffsetX = layout.value("image_offset_x", 0);
if (layout.contains("buttons"))
{
for (auto it = layout["buttons"].begin();
it != layout["buttons"].end();
++it)
{
DfuButton btn;
btn.id = it.key();
const auto& b = it.value();
btn.name = b.value("name", "");
btn.x = b.value("x", 0);
btn.y = b.value("y", 0);
seq.buttons.push_back(std::move(btn));
}
}
const std::string sequenceKey =
layout.value("sequence", "");
auto itSeq = j["sequences"].find(sequenceKey);
if (itSeq == j["sequences"].end())
return seq;
for (const auto& s : itSeq.value())
{
DfuStep step;
step.description = s.value("description", "");
step.duration = s.value("duration", 0);
step.action = s.value("action", "");
if (s.contains("buttons"))
{
for (const auto& b : s["buttons"])
step.activeButtons.push_back(
b.get<std::string>()
);
}
seq.steps.push_back(std::move(step));
}
return seq;
}
bool SequenceIsSupported(const std::string& deviceKey)
{
DfuSequence seq = ParseSequence(deviceKey);
return !seq.steps.empty();
}
#endif // WITH_GUI
+40
View File
@@ -0,0 +1,40 @@
#ifdef WITH_GUI
#ifndef SEQUENCE_H
#define SEQUENCE_H
#include <string>
struct DfuButton
{
std::string id;
std::string name;
int x = 0;
int y = 0;
};
struct DfuStep
{
std::string description;
int duration = 0;
std::vector<std::string> activeButtons;
std::string action;
};
struct DfuSequence
{
std::string imageName;
int imageWidth = 0;
int imageHeight = 0;
int imageOffsetX = 0;
std::vector<DfuButton> buttons;
std::vector<DfuStep> steps;
};
DfuSequence ParseSequence(const std::string& deviceKey);
bool SequenceIsSupported(const std::string& deviceKey);
#endif // SEQUENCE_H
#endif // WITH_GUI
+26
View File
@@ -0,0 +1,26 @@
#ifndef STATE_H
#define STATE_H
#include <string>
enum class DeviceMode
{
None,
Normal,
Recovery,
DFU
};
struct DeviceState
{
bool connected = false;
bool isSupported = false;
DeviceMode mode = DeviceMode::None;
std::string productVersion;
std::string productType;
std::string displayName;
std::string udid;
uint64_t ecid;
};
#endif // STATE_H
-209
View File
@@ -1,209 +0,0 @@
#ifdef WITH_GUI
#include "app.hpp"
#include <wx/wx.h>
#include <wx/mstream.h>
#include <wx/image.h>
#include <wx/bitmap.h>
#include <wx/statline.h>
#include <string>
#include "../utils/constants.h"
#include "../utils/paleinfo.h"
#include "../utils/log.h"
#include "../exploit/logo.h"
class MainFrame;
class MainPanel : public wxPanel
{
public:
explicit MainPanel(MainFrame* frame, wxWindow* parent);
};
class SettingsPanel : public wxPanel
{
public:
explicit SettingsPanel(MainFrame* frame, wxWindow* parent);
};
class MainFrame : public wxFrame
{
public:
MainFrame()
: wxFrame(
nullptr,
wxID_ANY,
"palera1n – Version beta " + wxString(PALERAIN_VERSION),
wxDefaultPosition,
wxSize(480, 360),
wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER))
{
auto* root = new wxBoxSizer(wxVERTICAL);
m_main = new MainPanel(this, this);
m_settings = new SettingsPanel(this, this);
root->Add(m_main, 1, wxEXPAND);
root->Add(m_settings, 1, wxEXPAND);
SetSizer(root);
ShowMain();
}
void ShowMain()
{
m_main->Show();
m_settings->Hide();
Layout();
}
void ShowSettings()
{
m_main->Hide();
m_settings->Show();
Layout();
}
private:
MainPanel* m_main;
SettingsPanel* m_settings;
};
MainPanel::MainPanel(MainFrame* frame, wxWindow* parent)
: wxPanel(parent)
{
auto* root = new wxBoxSizer(wxVERTICAL);
wxInitAllImageHandlers();
wxMemoryInputStream stream(resources_logo_png, resources_logo_png_len);
wxImage img(stream, wxBITMAP_TYPE_PNG);
wxBitmap bmp(img);
auto* logo = new wxStaticBitmap(this, wxID_ANY, bmp);
auto* titletext = new wxStaticText(this, wxID_ANY, "Welcome to palera1n!");
wxFont titlefont = titletext->GetFont();
titlefont.SetWeight(wxFONTWEIGHT_BOLD);
titletext->SetFont(titlefont);
auto* left = new wxBoxSizer(wxVERTICAL);
left->Add(titletext, 0, wxTOP | wxLEFT, 10);
auto* row = new wxBoxSizer(wxHORIZONTAL);
row->Add(left, 0, wxALIGN_TOP);
row->AddStretchSpacer();
row->Add(logo, 0, wxTOP | wxRIGHT, 10);
root->Add(row, 0, wxEXPAND);
root->Add(new wxStaticLine(this), 0, wxEXPAND | wxALL, 10);
auto* credtext = new wxStaticText(this, wxID_ANY, "Made by: asdfugil, kok3shidoll, claration, mineek, staturnz\n\nThanks to: itsnebulalol, llsc12, lrdsnow, nikias (libimobiledevice), Checkra1n\n(Siguza, axi0mx, littlelailo et al.), Procursus (Hayden Seay, Cameron Katri,\nKeto et al.)\n\nWith 💖 from C (claration)");
root->Add(credtext, 0, wxLEFT | wxRIGHT, 10);
root->Add(new wxStaticLine(this), 0, wxEXPAND | wxALL, 10);
auto* notetext = new wxStaticText(this, wxID_ANY, "NOTE: Please ensure you have a backup of your device before applying the\njailbreak. While data loss is unlikely, we won't be responsible if something goes\nwrong. Use at your own risk.");
wxFont notefont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
notefont.SetPointSize(12);
notefont.SetStyle(wxFONTSTYLE_ITALIC);
notetext->SetFont(notefont);
root->Add(notetext, 0, wxLEFT | wxRIGHT, 10);
root->AddStretchSpacer();
auto* btn = new wxButton(this, wxID_ANY, "Options");
auto* sbtn = new wxButton(this, wxID_ANY, "Start");
sbtn->Disable();
btn->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowSettings();
});
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
bottomRow->AddStretchSpacer();
bottomRow->Add(btn, 0, wxALL, 10);
bottomRow->Add(sbtn, 0, wxALL, 10);
root->Add(bottomRow, 0, wxEXPAND);
SetSizer(root);
}
SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent)
: wxPanel(parent)
{
auto* root = new wxBoxSizer(wxVERTICAL);
root->Add(new wxStaticText(this, wxID_ANY,
"You may set the following options. If you don't know what they mean you'll\n"
"probably have no reason to set them."), 0, wxALL, 10);
auto* option_safemode = new wxCheckBox(this, wxID_ANY, "Safe Mode");
auto* option_verbose = new wxCheckBox(this, wxID_ANY, "Verbose Boot");
auto* option_revert = new wxCheckBox(this, wxID_ANY, "Restore System");
auto* option_dark_blockchain = new wxCheckBox(this, wxID_ANY, "Dark Blockchain");
option_safemode->SetValue(palerain_flags & palerain_option_safemode);
option_verbose->SetValue(palerain_flags & palerain_option_verbose_boot);
option_revert->SetValue(palerain_flags & palerain_option_force_revert);
option_dark_blockchain->SetValue(true);
option_safemode->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
palerain_flags |= palerain_option_safemode;
else
palerain_flags &= ~palerain_option_safemode;
});
option_verbose->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
palerain_flags |= palerain_option_verbose_boot;
else
palerain_flags &= ~palerain_option_verbose_boot;
});
option_revert->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
palerain_flags |= palerain_option_force_revert;
else
palerain_flags &= ~palerain_option_force_revert;
});
root->Add(option_safemode, 0, wxLEFT | wxRIGHT, 10);
root->Add(option_verbose, 0, wxLEFT | wxRIGHT | wxTOP, 10);
root->Add(new wxStaticText(this, wxID_ANY, "Boot Arguments:"), 0, wxALL, 10);
auto* bootArgs = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize);
root->Add(bootArgs, 0, wxLEFT | wxRIGHT | wxEXPAND, 30);
root->Add(option_revert, 0, wxLEFT | wxRIGHT | wxTOP, 10);
root->Add(option_dark_blockchain, 0, wxLEFT | wxRIGHT | wxTOP, 10);
root->AddStretchSpacer();
auto* back = new wxButton(this, wxID_ANY, "Back");
back->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowMain();
});
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
bottomRow->AddStretchSpacer();
bottomRow->Add(back, 0, wxALL, 10);
root->Add(bottomRow, 0, wxEXPAND);
SetSizer(root);
}
bool PalerainApp::OnInit()
{
auto* frame = new MainFrame();
frame->Show(true);
return true;
}
wxIMPLEMENT_APP_NO_MAIN(PalerainApp);
#endif // WITH_GUI
-10
View File
@@ -1,10 +0,0 @@
#ifdef WITH_GUI
#pragma once
#include <wx/wx.h>
class PalerainApp : public wxApp {
public:
bool OnInit() override;
};
#endif // WITH_GUI
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H
#define PALERAIN_VERSION "2.4.0"
#define PALERAIN_VERSION "3.0.0"
#include <cstdint>
+165
View File
@@ -0,0 +1,165 @@
#ifdef WITH_GUI
#include "AppFrame.hpp"
#include <wx/wx.h>
#include "../utils/constants.h"
#include "../event.hpp"
#include <thread>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libirecovery.h>
wxDEFINE_EVENT(EVT_DEVICE_STATE_UPDATE, wxCommandEvent);
void send_device_state(MainFrame* frame, const DeviceState& state)
{
wxTheApp->CallAfter([frame, state]() {
auto* evt = new wxCommandEvent(EVT_DEVICE_STATE_UPDATE);
evt->SetClientData(new DeviceState(state));
wxPostEvent(frame, *evt);
});
}
MainFrame::MainFrame()
: wxFrame(nullptr,
wxID_ANY,
"palera1n – Version beta " + wxString(PALERAIN_VERSION),
wxDefaultPosition,
wxSize(480, 360),
wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER))
{
auto* root = new wxBoxSizer(wxVERTICAL);
m_main = new MainPanel(this, this);
m_settings = new SettingsPanel(this, this);
m_recovery = new RecoveryPanel(this, this);
m_dfu = new DfuPanel(this, this);
m_exploit = new ExploitPanel(this, this);
root->Add(m_main, 1, wxEXPAND);
root->Add(m_settings, 1, wxEXPAND);
root->Add(m_recovery, 1, wxEXPAND);
root->Add(m_dfu, 1, wxEXPAND);
root->Add(m_exploit, 1, wxEXPAND);
SetSizer(root);
Bind(EVT_DEVICE_STATE_UPDATE, [this](wxCommandEvent& e)
{
auto* state = static_cast<DeviceState*>(e.GetClientData());
if (!state)
return;
UpdateDeviceState(*state);
delete state;
});
ShowMain();
std::thread([this]()
{
idevice_event_subscribe(normal_device_event_cb, this);
while (true)
sleep(1);
}).detach();
std::thread([this]()
{
static irecv_device_event_context_t ctx = nullptr;
irecv_device_event_subscribe(
&ctx,
recovery_device_event_cb,
this
);
while (true)
sleep(1);
}).detach();
}
void MainFrame::ShowMain()
{
m_main->Show();
m_settings->Hide();
m_recovery->Hide();
m_dfu->Hide();
m_exploit->Hide();
Layout();
}
void MainFrame::ShowSettings()
{
m_main->Hide();
m_settings->Show();
m_recovery->Hide();
m_dfu->Hide();
m_exploit->Hide();
Layout();
}
void MainFrame::ShowRecovery()
{
m_main->Hide();
m_settings->Hide();
m_recovery->Show();
m_dfu->Hide();
m_exploit->Hide();
Layout();
}
void MainFrame::ShowDfu()
{
m_main->Hide();
m_settings->Hide();
m_recovery->Hide();
m_dfu->Show();
m_dfu->LoadDevice(m_state.productType);
m_exploit->Hide();
Layout();
}
void MainFrame::ShowExploit()
{
m_main->Hide();
m_settings->Hide();
m_recovery->Hide();
m_dfu->Hide();
m_exploit->Show();
m_exploit->StartExploit();
Layout();
}
void MainFrame::UpdateDeviceState(const DeviceState& state)
{
m_state = state;
if (m_main)
m_main->SetDeviceState(m_state);
if (m_recovery)
m_recovery->SetDeviceState(m_state);
if (m_dfu)
m_dfu->SetDeviceState(m_state);
if (m_exploit)
m_exploit->SetDeviceState(m_state);
}
bool PalerainApp::OnInit()
{
auto* frame = new MainFrame();
frame->Show(true);
return true;
}
wxIMPLEMENT_APP_NO_MAIN(PalerainApp);
#endif
+53
View File
@@ -0,0 +1,53 @@
#ifndef APPFRAME_H
#define APPFRAME_H
#ifdef WITH_GUI
#include <wx/wx.h>
#include "../state.hpp"
#include "MainPanel.hpp"
#include "SettingsPanel.hpp"
#include "RecoveryPanel.hpp"
#include "DfuPanel.hpp"
#include "ExploitPanel.hpp"
void send_device_state(MainFrame* frame, const DeviceState& state);
class MainFrame : public wxFrame
{
public:
MainFrame();
void ShowMain();
void ShowSettings();
void ShowRecovery();
void ShowDfu();
void ShowExploit();
const DeviceState& GetDeviceState() const { return m_state; }
void UpdateDeviceState(const DeviceState& state);
MainPanel* GetMainPanel() const { return m_main; }
SettingsPanel* GetSettingsPanel() const { return m_settings; }
RecoveryPanel* GetRecoveryPanel() const { return m_recovery; }
DfuPanel* GetDfuPanel() const { return m_dfu; }
ExploitPanel* GetExploitPanel() const { return m_exploit; }
private:
MainPanel* m_main = nullptr;
SettingsPanel* m_settings = nullptr;
RecoveryPanel* m_recovery = nullptr;
DfuPanel* m_dfu = nullptr;
ExploitPanel* m_exploit = nullptr;
DeviceState m_state;
};
class PalerainApp : public wxApp {
public:
bool OnInit() override;
};
#endif // WITH_GUI
#endif // APPFRAME_H
+38
View File
@@ -0,0 +1,38 @@
#ifndef DEVICEPANEL_H
#define DEVICEPANEL_H
#include <wx/wx.h>
#include "../state.hpp"
class MainFrame;
class DevicePanel : public wxPanel
{
public:
DevicePanel(MainFrame* frame, wxWindow* parent)
: wxPanel(parent),
m_frame(frame)
{
}
virtual void SetDeviceState(const DeviceState& state)
{
m_deviceState = state;
}
protected:
MainFrame* GetMainFrame() const
{
return m_frame;
}
const DeviceState& GetDeviceState() const
{
return m_deviceState;
}
private:
MainFrame* m_frame;
DeviceState m_deviceState;
};
#endif // DEVICEPANEL_H
+427
View File
@@ -0,0 +1,427 @@
#ifdef WITH_GUI
#include "DfuPanel.hpp"
#include "AppFrame.hpp"
#include "DevicePanel.hpp"
#include "../state.hpp"
#include "../sequence.hpp"
#include "../utils/log.h"
#include <thread>
#include <wx/wx.h>
#include <wx/mstream.h>
#include <wx/image.h>
#include <wx/bitmap.h>
#include "../gen/images/atv_std_brd.h"
#include "../gen/images/ipad.h"
#include "../gen/images/ipadmini.h"
#include "../gen/images/iphone6s.h"
#include "../gen/images/iphone7.h"
#include "../gen/images/iphone8.h"
#include "../gen/images/iphonese.h"
#include "../gen/images/iphonex.h"
#include "../gen/images/ipodtouch.h"
#include "../gen/images/siriremote.h"
#include <libirecovery.h>
static const wxColour kActive =
wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
static const wxColour kInactive =
wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
DfuPanel::DfuPanel(MainFrame* frame, wxWindow* parent)
: DevicePanel(frame, parent)
{
auto* root = new wxBoxSizer(wxVERTICAL);
m_headerText = new wxStaticText(this, wxID_ANY, "Time to put the device into DFU mode. Locate the buttons as marked below\non your device and check the instructions on the right.");
root->Add(m_headerText, 0, wxALL, 10);
auto* contentRow = new wxBoxSizer(wxHORIZONTAL);
m_devicePanel = new wxPanel(this);
m_devicePanel->SetMinSize(wxSize(310, 260));
m_deviceImage = new wxStaticBitmap(
m_devicePanel,
wxID_ANY,
wxBitmap()
);
contentRow->Add(m_devicePanel, 1, wxTOP, 10);
m_stepsSizer = new wxBoxSizer(wxVERTICAL);
contentRow->Add(m_stepsSizer, 2, wxEXPAND | wxALL, 0);
root->Add(contentRow, 1, wxEXPAND);
m_backButton = new wxButton(this, wxID_ANY, "Back");
m_startButton = new wxButton(this, wxID_ANY, "Start");
m_backButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowMain();
});
m_startButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent&)
{
m_isEnteringDfu = true;
m_backButton->Disable();
m_startButton->Disable();
StartSequence(m_sequence);
});
m_timer.Bind(wxEVT_TIMER, [this](wxTimerEvent&)
{
RunStep();
});
m_stagnentTimer.Bind(wxEVT_TIMER, [this](wxTimerEvent&)
{
m_backButton->Enable();
m_startButton->Enable();
GetMainFrame()->ShowExploit();
});
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
bottomRow->AddStretchSpacer();
bottomRow->Add(m_backButton, 0, wxALL, 10);
bottomRow->Add(m_startButton, 0, wxALL, 10);
root->Add(bottomRow, 0, wxEXPAND);
SetSizer(root);
}
void DfuPanel::SetDeviceState(const DeviceState& state)
{
DevicePanel::SetDeviceState(state);
if (!(this->IsShown()))
return;
if (m_isEnteringDfu && state.mode == DeviceMode::DFU)
{
m_isEnteringDfu = false;
m_headerText->SetLabel("Device entered DFU mode successfully.\n");
if (!m_stagnentTimer.IsRunning())
m_stagnentTimer.StartOnce(3000);
}
if (m_isEnteringDfu && state.mode == DeviceMode::Normal)
{
m_isEnteringDfu = false;
m_backButton->Enable();
m_startButton->Enable();
GetMainFrame()->ShowRecovery();
GetMainFrame()->GetRecoveryPanel()->SetStatusText("Hmm... It seems like the device didn't enter DFU mode.");
}
if (m_isEnteringDfu && state.mode == DeviceMode::Recovery)
{
m_isEnteringDfu = false;
m_backButton->Enable();
m_startButton->Enable();
GetMainFrame()->ShowMain();
}
}
void DfuPanel::LoadDevice(const std::string& productType)
{
m_sequence = ParseSequence(productType);
m_index = 0;
m_deviceImage->SetBitmap(wxBitmap());
for (auto* lbl : m_stepLabels)
lbl->Destroy();
m_stepLabels.clear();
m_stepsSizer->Clear(false);
for (auto* lbl : m_buttonLabels)
lbl->Destroy();
m_buttonLabels.clear();
const unsigned char* imageData = nullptr;
size_t imageSize = 0;
if (m_sequence.imageName == "ipadmini")
{
imageData = ipadmini;
imageSize = ipadmini_len;
}
else if (m_sequence.imageName == "ipad")
{
imageData = ipad;
imageSize = ipad_len;
}
else if (m_sequence.imageName == "iphonese")
{
imageData = iphonese;
imageSize = iphonese_len;
}
else if (m_sequence.imageName == "iphone6s")
{
imageData = iphone6s;
imageSize = iphone6s_len;
}
else if (m_sequence.imageName == "iphone7")
{
imageData = iphone7;
imageSize = iphone7_len;
}
else if (m_sequence.imageName == "iphone8")
{
imageData = iphone8;
imageSize = iphone8_len;
}
else if (m_sequence.imageName == "iphonex")
{
imageData = iphonex;
imageSize = iphonex_len;
}
else if (m_sequence.imageName == "ipodtouch")
{
imageData = ipodtouch;
imageSize = ipodtouch_len;
}
else if (m_sequence.imageName == "siriremote")
{
imageData = siriremote;
imageSize = siriremote_len;
}
else if (m_sequence.imageName == "atv_std_brd")
{
imageData = atv_std_brd;
imageSize = atv_std_brd_len;
}
if (imageData)
{
wxMemoryInputStream stream(imageData, imageSize);
wxImage img(stream, wxBITMAP_TYPE_PNG);
if (img.IsOk())
{
img = img.Scale(
m_sequence.imageWidth,
m_sequence.imageHeight,
wxIMAGE_QUALITY_HIGH
);
m_deviceImage->SetBitmap(wxBitmap(img));
m_deviceImage->SetPosition(wxPoint(m_sequence.imageOffsetX, 0));
}
}
for (const auto& button : m_sequence.buttons)
{
auto* lbl = new wxStaticText(
m_devicePanel,
wxID_ANY,
button.name
);
lbl->SetPosition(wxPoint(button.x, button.y));
m_buttonLabels.push_back(lbl);
}
for (size_t i = 0; i < m_sequence.steps.size(); i++)
{
const auto& step = m_sequence.steps[i];
wxString label = wxString::Format(
"%zu. %s (%d)",
i + 1,
step.description,
step.duration
);
auto* lbl = new wxStaticText(
this,
wxID_ANY,
label
);
lbl->SetForegroundColour(i == 0 ? kActive : kInactive);
m_stepsSizer->Add(lbl, 0, wxBOTTOM, 5);
m_stepLabels.push_back(lbl);
}
m_devicePanel->Layout();
m_stepsSizer->Layout();
Layout();
Fit();
Refresh();
}
void DfuPanel::StartSequence(const DfuSequence& seq)
{
m_sequence = seq;
m_index = 0;
m_stepRemaining = -1;
m_actionExecutedIndex = -1;
RunStep();
m_timer.StartOnce(1000);
}
void DfuPanel::RunStep()
{
if (m_sequence.steps.empty())
return;
if (m_index >= m_sequence.steps.size())
{
for (auto* lbl : m_stepLabels)
lbl->SetForegroundColour(kInactive);
Layout();
Refresh();
m_timer.Stop();
return;
}
const auto& step = m_sequence.steps[m_index];
if (m_stepRemaining < 0)
m_stepRemaining = step.duration;
if (m_stepRemaining > 0)
--m_stepRemaining;
bool finished = (m_stepRemaining == 0);
size_t completedIndex = m_index;
if (finished)
{
++m_index;
m_stepRemaining = -1;
}
for (size_t i = 0; i < m_stepLabels.size(); i++)
{
auto* lbl = m_stepLabels[i];
if (i == m_index)
{
lbl->SetForegroundColour(kActive);
lbl->SetLabel(wxString::Format(
"%zu. %s (%d)",
i + 1,
m_sequence.steps[i].description,
m_stepRemaining < 0 ? m_sequence.steps[i].duration : m_stepRemaining
));
}
else if (finished && i == completedIndex)
{
lbl->SetForegroundColour(kInactive);
lbl->SetLabel(wxString::Format(
"%zu. %s (0)",
i + 1,
m_sequence.steps[i].description
));
}
else
{
lbl->SetForegroundColour(kInactive);
}
}
for (auto* lbl : m_buttonLabels)
lbl->SetForegroundColour(kInactive);
const auto& activeStep =
(m_index < m_sequence.steps.size())
? m_sequence.steps[m_index]
: m_sequence.steps.back();
for (const auto& buttonId : activeStep.activeButtons)
{
for (const auto& btn : m_sequence.buttons)
{
if (btn.id == buttonId)
{
for (auto* lbl : m_buttonLabels)
{
if (lbl->GetLabel() == btn.name)
lbl->SetForegroundColour(kActive);
}
}
}
}
if (m_index < m_sequence.steps.size())
{
const auto& activeStep = m_sequence.steps[m_index];
if (!activeStep.action.empty() && m_actionExecutedIndex != m_index)
{
m_actionExecutedIndex = m_index;
if (activeStep.action == "reboot")
{
Reboot();
}
}
}
Layout();
Refresh();
Update();
m_timer.StartOnce(1000);
}
void DfuPanel::Reboot()
{
std::thread([this]()
{
const auto state = GetDeviceState();
if (!state.connected || state.mode != DeviceMode::Recovery)
return;
irecv_client_t client = nullptr;
int attempts = 0;
const int max_attempts = 8;
while (attempts < max_attempts)
{
if (irecv_open_with_ecid(&client, state.ecid) == IRECV_E_SUCCESS)
break;
attempts++;
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
if (!client)
{
return;
}
irecv_setenv(client, "auto-boot", "true");
irecv_saveenv(client);
irecv_reboot(client);
irecv_close(client);
}).detach();
}
#endif // WITH_GUI
+47
View File
@@ -0,0 +1,47 @@
#ifndef DFUPANEL_H
#define DFUPANEL_H
#ifdef WITH_GUI
#include <wx/wx.h>
#include "DevicePanel.hpp"
#include "../state.hpp"
#include "../sequence.hpp"
class DfuPanel;
class DfuPanel : public DevicePanel
{
public:
explicit DfuPanel(MainFrame* frame, wxWindow* parent);
void SetDeviceState(const DeviceState& state) override;
void LoadDevice(const std::string& productType);
void StartSequence(const DfuSequence& seq);
void RunStep();
void Reboot();
private:
wxStaticText* m_headerText = nullptr;
wxButton* m_backButton = nullptr;
wxButton* m_startButton = nullptr;
wxBoxSizer* m_stepsSizer = nullptr;
std::vector<wxStaticText*> m_stepLabels;
DfuSequence m_sequence;
size_t m_index = 0;
int m_stepRemaining = 0;
wxTimer m_timer;
wxTimer m_stagnentTimer;
bool m_isEnteringDfu = false;
wxPanel* m_devicePanel = nullptr;
wxStaticBitmap* m_deviceImage = nullptr;
std::vector<wxStaticText*> m_buttonLabels;
size_t m_actionExecutedIndex = std::numeric_limits<size_t>::max();
};
#endif // WITH_GUI
#endif // DFUPANEL_H
+72
View File
@@ -0,0 +1,72 @@
#ifdef WITH_GUI
#include "ExploitPanel.hpp"
#include <thread>
#include <wx/wx.h>
#include "AppFrame.hpp"
#include "DevicePanel.hpp"
#include "../state.hpp"
#include "../utils/log.h"
ExploitPanel::ExploitPanel(MainFrame* frame, wxWindow* parent)
: DevicePanel(frame, parent)
{
auto* root = new wxBoxSizer(wxVERTICAL);
auto* text = new wxStaticText(this, wxID_ANY,
"Installing jailbreak, this will take a moment. If the device asks for a passcode\nplease enter it. Do not disconnect the device until finished.");
m_statusText = new wxStaticText(this, wxID_ANY, "");
root->Add(text, 0, wxALL, 10);
root->Add(m_statusText, 0, wxALL, 10);
m_backButton = new wxButton(this, wxID_ANY, "Back");
m_backButton->Disable();
m_backButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowMain();
});
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
bottomRow->AddStretchSpacer();
bottomRow->Add(m_backButton, 0, wxALL, 10);
root->AddStretchSpacer();
root->Add(bottomRow, 0, wxEXPAND);
SetSizer(root);
}
void ExploitPanel::SetDeviceState(const DeviceState& state)
{
DevicePanel::SetDeviceState(state);
if (!(this->IsShown()))
return;
if (state.mode == DeviceMode::Normal)
{
m_statusText->SetLabel("Done.");
m_backButton->Enable();
}
}
void ExploitPanel::StartExploit()
{
m_statusText->SetLabel("Exploiting device...");
m_backButton->Disable();
std::thread([this]()
{
const auto state = GetDeviceState();
if (!state.connected || state.mode != DeviceMode::DFU)
return;
LOG("Starting exploit on worker thread...");
}).detach();
}
#endif // WITH_GUI
+24
View File
@@ -0,0 +1,24 @@
#ifndef EXPLOITPANEL_HPP
#define EXPLOITPANEL_HPP
#ifdef WITH_GUI
#include <wx/wx.h>
#include "DevicePanel.hpp"
#include "../state.hpp"
class ExploitPanel;
class ExploitPanel : public DevicePanel
{
public:
explicit ExploitPanel(MainFrame* frame, wxWindow* parent);
void SetDeviceState(const DeviceState& state) override;
void StartExploit();
private:
wxButton* m_backButton = nullptr;
wxStaticText* m_statusText = nullptr;
};
#endif // WITH_GUI
#endif // EXPLOITPANEL_HPP
+164
View File
@@ -0,0 +1,164 @@
#ifdef WITH_GUI
#include "MainPanel.hpp"
#include <wx/wx.h>
#include <wx/mstream.h>
#include <wx/image.h>
#include <wx/bitmap.h>
#include <wx/statline.h>
#include "AppFrame.hpp"
#include "DevicePanel.hpp"
#include "../state.hpp"
#include "../gen/images/logo.h"
const char* deviceTextString = "Connect your iPhone, iPod touch, iPad, or AppleTV to begin.";
MainPanel::MainPanel(MainFrame* frame, wxWindow* parent)
: DevicePanel(frame, parent)
{
auto* root = new wxBoxSizer(wxVERTICAL);
wxInitAllImageHandlers();
wxMemoryInputStream stream(logo, logo_len);
wxImage img(stream, wxBITMAP_TYPE_PNG);
wxBitmap bmp(img);
auto* logo = new wxStaticBitmap(this, wxID_ANY, bmp);
auto* titletext = new wxStaticText(this, wxID_ANY, "Welcome to palera1n!");
wxFont titlefont = titletext->GetFont();
titlefont.SetWeight(wxFONTWEIGHT_BOLD);
titletext->SetFont(titlefont);
m_deviceText = new wxStaticText(
this,
wxID_ANY,
deviceTextString
);
auto* left = new wxBoxSizer(wxVERTICAL);
left->Add(titletext, 0, wxTOP | wxLEFT, 10);
left->Add(m_deviceText, 0, wxTOP | wxLEFT, 10);
auto* row = new wxBoxSizer(wxHORIZONTAL);
row->Add(left, 0, wxALIGN_TOP);
row->AddStretchSpacer();
row->Add(logo, 0, wxTOP | wxRIGHT, 10);
root->Add(row, 0, wxEXPAND);
root->Add(new wxStaticLine(this), 0, wxEXPAND | wxALL, 10);
auto* credtext = new wxStaticText(this, wxID_ANY,
"Made by: asdfugil, kok3shidoll, claration, mineek, staturnz\n\n"
"Thanks to: itsnebulalol, llsc12, lrdsnow, nikias (libimobiledevice), Checkra1n\n"
"(Siguza, axi0mx, littlelailo et al.), Procursus (Hayden Seay, Cameron Katri,\n"
"Keto et al.)\n\n"
"With 💖 from C (claration)");
root->Add(credtext, 0, wxLEFT | wxRIGHT, 10);
root->Add(new wxStaticLine(this), 0, wxEXPAND | wxALL, 10);
auto* notetext = new wxStaticText(this, wxID_ANY,
"NOTE: Please ensure you have a backup of your device before applying the\n"
"jailbreak. While data loss is unlikely, we won't be responsible if something goes\n"
"wrong. Use at your own risk.");
wxFont notefont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
notefont.SetPointSize(12);
notefont.SetStyle(wxFONTSTYLE_ITALIC);
notetext->SetFont(notefont);
root->Add(notetext, 0, wxLEFT | wxRIGHT, 10);
root->AddStretchSpacer();
auto* btn = new wxButton(this, wxID_ANY, "Options");
m_startButton = new wxButton(this, wxID_ANY, "Start");
m_startButton->Disable();
btn->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowSettings();
});
m_startButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
if (frame->GetDeviceState().mode == DeviceMode::Normal)
{
frame->ShowRecovery();
}
else if (frame->GetDeviceState().mode == DeviceMode::Recovery)
{
frame->ShowDfu();
}
});
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
bottomRow->AddStretchSpacer();
bottomRow->Add(btn, 0, wxALL, 10);
bottomRow->Add(m_startButton, 0, wxALL, 10);
root->Add(bottomRow, 0, wxEXPAND);
SetSizer(root);
}
void MainPanel::SetDeviceState(const DeviceState& state)
{
DevicePanel::SetDeviceState(state);
if (m_deviceText)
{
if (!state.connected)
{
m_deviceText->SetLabel(deviceTextString);
m_startButton->Enable(false);
}
else
{
const std::string versionString =
state.productVersion.empty() ? "Unknown" : state.productVersion;
const std::string productString =
state.productType.empty() ? "Unknown" : state.productType;
const std::string ecidString = state.ecid != 0 ? ("ECID: " + std::to_string(state.ecid)) : "ECID: Unknown";
switch (state.mode)
{
case DeviceMode::Normal:
if (state.isSupported) {
m_deviceText->SetLabel("Connected " + productString + " (iOS " + versionString + ") in normal mode.\n" + ecidString);
m_startButton->Enable();
} else {
m_deviceText->SetLabel("Sorry, " + productString + " (iOS " + versionString + ") is not supported.\n" + ecidString);
m_startButton->Enable(false);
}
break;
case DeviceMode::Recovery:
if (state.isSupported) {
m_deviceText->SetLabel("Connected " + productString + " in recovery mode.\n" + ecidString);
m_startButton->Enable();
} else {
m_deviceText->SetLabel("Sorry, " + productString + " is not supported.\n" + ecidString);
m_startButton->Enable(false);
}
break;
case DeviceMode::DFU:
m_deviceText->SetLabel("Sorry, DFU mode is not supported.");
m_startButton->Enable(false);
break;
case DeviceMode::None:
m_deviceText->SetLabel(deviceTextString);
m_startButton->Enable(false);
break;
}
}
}
}
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef MAINPANEL_H
#define MAINPANEL_H
#ifdef WITH_GUI
#include <wx/wx.h>
#include "DevicePanel.hpp"
#include "../state.hpp"
class MainPanel;
class MainPanel : public DevicePanel
{
public:
explicit MainPanel(MainFrame* frame, wxWindow* parent);
void SetDeviceState(const DeviceState& state) override;
private:
wxStaticText* m_deviceText = nullptr;
wxButton* m_startButton = nullptr;
};
#endif // WITH_GUI
#endif // MAINPANEL_H
+130
View File
@@ -0,0 +1,130 @@
#ifdef WITH_GUI
#include "RecoveryPanel.hpp"
#include <wx/wx.h>
#include "AppFrame.hpp"
#include "DevicePanel.hpp"
#include "../state.hpp"
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libirecovery.h>
RecoveryPanel::RecoveryPanel(MainFrame* frame, wxWindow* parent)
: DevicePanel(frame, parent)
{
auto* root = new wxBoxSizer(wxVERTICAL);
root->Add(new wxStaticText(this, wxID_ANY,
"The device needs to be put into DFU mode to apply the jailbreak. This is a\n"
"manual process and we will guide you through it.\n\n"
"In order to prevent filesystem corruption through hard reset, the device will\n"
"be put into recovery mode first. Click next when you are ready."), 0, wxALL, 10);
m_statusText = new wxStaticText(this, wxID_ANY, "");
root->Add(m_statusText, 0, wxALL, 10);
m_backButton = new wxButton(this, wxID_ANY, "Back");
m_nextButton = new wxButton(this, wxID_ANY, "Next");
m_backButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowMain();
});
m_nextButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent&)
{
m_statusText->SetLabel("Entering recovery mode...");
m_backButton->Disable();
m_nextButton->Disable();
EnterRecoveryMode();
});
m_timer.Bind(wxEVT_TIMER, [this](wxTimerEvent&)
{
m_backButton->Enable();
m_nextButton->Enable();
m_isEnteringRecovery = false;
GetMainFrame()->ShowDfu();
m_statusText->SetLabel("");
});
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
bottomRow->AddStretchSpacer();
bottomRow->Add(m_backButton, 0, wxALL, 10);
bottomRow->Add(m_nextButton, 0, wxALL, 10);
root->AddStretchSpacer();
root->Add(bottomRow, 0, wxEXPAND);
SetSizer(root);
}
void RecoveryPanel::SetDeviceState(const DeviceState& state)
{
DevicePanel::SetDeviceState(state);
if (!(this->IsShown()))
return;
if (m_isEnteringRecovery && state.mode == DeviceMode::Recovery)
{
m_statusText->SetLabel("Device is now in recovery mode.");
m_timer.StartOnce(3000);
}
if (m_isEnteringRecovery && state.mode == DeviceMode::Normal)
{
m_isEnteringRecovery = false;
m_statusText->SetLabel("Hmm... It seems like the device didn't enter recovery mode. Please try again.");
m_backButton->Enable();
m_nextButton->Enable();
}
if (!m_isEnteringRecovery && state.mode == DeviceMode::None)
{
m_backButton->Enable();
m_nextButton->Enable();
GetMainFrame()->ShowMain();
}
}
void RecoveryPanel::EnterRecoveryMode()
{
const auto& state = GetDeviceState();
if (!state.connected)
return;
idevice_t device = nullptr;
lockdownd_client_t client = nullptr;
if (idevice_new(&device, state.udid.c_str()) != IDEVICE_E_SUCCESS)
return;
if (lockdownd_client_new_with_handshake(
device,
&client,
"palera1n") != LOCKDOWN_E_SUCCESS)
{
idevice_free(device);
return;
}
m_isEnteringRecovery = true;
lockdownd_enter_recovery(client);
lockdownd_client_free(client);
idevice_free(device);
}
void RecoveryPanel::SetStatusText(const wxString& text)
{
m_statusText->SetLabel(text);
}
#endif
+28
View File
@@ -0,0 +1,28 @@
#ifndef RECOVERYPANEL_H
#define RECOVERYPANEL_H
#ifdef WITH_GUI
#include <wx/wx.h>
#include "DevicePanel.hpp"
class RecoveryPanel;
class RecoveryPanel : public DevicePanel
{
public:
explicit RecoveryPanel(MainFrame* frame, wxWindow* parent);
void SetDeviceState(const DeviceState& state) override;
void SetStatusText(const wxString& text);
void EnterRecoveryMode();
private:
wxButton* m_backButton = nullptr;
wxButton* m_nextButton = nullptr;
wxStaticText* m_statusText = nullptr;
wxTimer m_timer;
bool m_isEnteringRecovery = false;
};
#endif // WITH_GUI
#endif // RECOVERYPANEL_H
+84
View File
@@ -0,0 +1,84 @@
#ifdef WITH_GUI
#include "SettingsPanel.hpp"
#include <wx/wx.h>
#include "AppFrame.hpp"
#include "DevicePanel.hpp"
#include "../utils/constants.h"
#include "../utils/paleinfo.h"
SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent)
: DevicePanel(frame, parent)
{
auto* root = new wxBoxSizer(wxVERTICAL);
root->Add(new wxStaticText(this, wxID_ANY,
"You may set the following options. If you don't know what they mean you'll\n"
"probably have no reason to set them."), 0, wxALL, 10);
auto* option_safemode = new wxCheckBox(this, wxID_ANY, "Safe Mode");
auto* option_verbose = new wxCheckBox(this, wxID_ANY, "Verbose Boot");
auto* option_revert = new wxCheckBox(this, wxID_ANY, "Restore System");
auto* option_dark_blockchain = new wxCheckBox(this, wxID_ANY, "Dark Blockchain");
option_safemode->SetValue(palerain_flags & palerain_option_safemode);
option_verbose->SetValue(palerain_flags & palerain_option_verbose_boot);
option_revert->SetValue(palerain_flags & palerain_option_force_revert);
option_dark_blockchain->SetValue(true);
option_safemode->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
palerain_flags |= palerain_option_safemode;
else
palerain_flags &= ~palerain_option_safemode;
});
option_verbose->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
palerain_flags |= palerain_option_verbose_boot;
else
palerain_flags &= ~palerain_option_verbose_boot;
});
option_revert->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
palerain_flags |= palerain_option_force_revert;
else
palerain_flags &= ~palerain_option_force_revert;
});
root->Add(option_safemode, 0, wxLEFT | wxRIGHT, 10);
root->Add(option_verbose, 0, wxLEFT | wxRIGHT | wxTOP, 10);
root->Add(new wxStaticText(this, wxID_ANY, "Boot Arguments:"), 0, wxALL, 10);
auto* bootArgs = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize);
root->Add(bootArgs, 0, wxLEFT | wxRIGHT | wxEXPAND, 30);
root->Add(option_revert, 0, wxLEFT | wxRIGHT | wxTOP, 10);
root->Add(option_dark_blockchain, 0, wxLEFT | wxRIGHT | wxTOP, 10);
root->AddStretchSpacer();
auto* back = new wxButton(this, wxID_ANY, "Back");
back->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowMain();
});
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
bottomRow->AddStretchSpacer();
bottomRow->Add(back, 0, wxALL, 10);
root->Add(bottomRow, 0, wxEXPAND);
SetSizer(root);
}
#endif // WITH_GUI
+18
View File
@@ -0,0 +1,18 @@
#ifndef SETTINGSPANEL_H
#define SETTINGSPANEL_H
#ifdef WITH_GUI
#include <wx/wx.h>
#include "DevicePanel.hpp"
class SettingsPanel;
class SettingsPanel : public DevicePanel
{
public:
explicit SettingsPanel(MainFrame* frame, wxWindow* parent);
};
#endif // WITH_GUI
#endif // SETTINGSPANEL_H