feat: wxWidgets gui
No files matched your search
@@ -1,5 +1,3 @@
|
|||||||
build/
|
build/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
src/exploit/payloads/
|
src/gen/
|
||||||
src/exploit/userland/
|
|
||||||
src/exploit/logo.h
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"cmake.loadCompileCommands": true,
|
||||||
|
"cmake.configureOnOpen": true,
|
||||||
|
"cmake.buildDirectory": "${workspaceFolder}/build",
|
||||||
|
"cmake.copyCompileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||||
|
}
|
||||||
@@ -1,62 +1,359 @@
|
|||||||
# Project
|
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(palera1n VERSION 3.0)
|
project(palera1n VERSION 3.0)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
include(ExternalProject)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
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_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_ARCHITECTURES "arm64")
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13")
|
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_GUI)
|
||||||
if(WITH_STATIC)
|
if(WITH_STATIC)
|
||||||
set(wxBUILD_SHARED OFF)
|
set(wxBUILD_SHARED OFF CACHE BOOL "" FORCE)
|
||||||
FetchContent_Declare(
|
|
||||||
wxWidgets
|
FetchContent_Declare(
|
||||||
GIT_REPOSITORY https://github.com/wxWidgets/wxWidgets.git
|
wxWidgets
|
||||||
GIT_SHALLOW ON
|
GIT_REPOSITORY https://github.com/wxWidgets/wxWidgets.git
|
||||||
)
|
GIT_SHALLOW ON
|
||||||
FetchContent_MakeAvailable(wxWidgets)
|
)
|
||||||
set(WX_LIBRARIES wxWidgets::core wxWidgets::base wxWidgets::net)
|
|
||||||
else()
|
FetchContent_MakeAvailable(wxWidgets)
|
||||||
find_package(wxWidgets REQUIRED COMPONENTS core base net)
|
|
||||||
include(${wxWidgets_USE_FILE})
|
set(WX_LIBRARIES wxcore wxbase wxnet)
|
||||||
set(WX_LIBRARIES ${wxWidgets_LIBRARIES})
|
|
||||||
endif()
|
else()
|
||||||
|
find_package(wxWidgets REQUIRED COMPONENTS core base net)
|
||||||
|
include(${wxWidgets_USE_FILE})
|
||||||
|
set(WX_LIBRARIES ${wxWidgets_LIBRARIES})
|
||||||
|
endif()
|
||||||
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)
|
if(APPLE AND WITH_GUI)
|
||||||
|
set(APP_ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/palera1n.icns)
|
||||||
|
|
||||||
add_executable(palera1n MACOSX_BUNDLE ${SOURCES})
|
add_executable(palera1n MACOSX_BUNDLE ${SOURCES})
|
||||||
set_target_properties(palera1n PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/resources/Info.plist)
|
|
||||||
elseif(APPLE)
|
target_sources(palera1n PRIVATE ${APP_ICON})
|
||||||
add_executable(palera1n ${SOURCES})
|
|
||||||
|
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()
|
else()
|
||||||
add_executable(palera1n WIN32 ${SOURCES} resources/main.exe.manifest)
|
add_executable(palera1n ${SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include_directories(${DEPS_PREFIX}/include)
|
||||||
|
link_directories(${DEPS_PREFIX}/lib)
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# APPLE FRAMEWORKS
|
||||||
|
# =========================
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
find_library(IOKIT IOKit)
|
find_library(IOKIT IOKit)
|
||||||
find_library(COREFOUNDATION CoreFoundation)
|
find_library(COREFOUNDATION CoreFoundation)
|
||||||
target_link_libraries(palera1n PRIVATE ${IOKIT} ${COREFOUNDATION})
|
|
||||||
|
target_link_libraries(palera1n PRIVATE
|
||||||
|
${IOKIT}
|
||||||
|
${COREFOUNDATION}
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# wxWidgets
|
||||||
|
# =========================
|
||||||
if(WITH_GUI)
|
if(WITH_GUI)
|
||||||
if(WITH_STATIC)
|
target_link_libraries(palera1n PRIVATE ${WX_LIBRARIES})
|
||||||
target_link_libraries(palera1n PRIVATE wxcore wxnet)
|
target_compile_definitions(palera1n PRIVATE WITH_GUI)
|
||||||
else()
|
|
||||||
target_link_libraries(palera1n PRIVATE ${wxWidgets_LIBRARIES})
|
|
||||||
endif()
|
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()
|
endif()
|
||||||
@@ -5,19 +5,21 @@ WITH_STATIC ?= 0
|
|||||||
BUILD_TYPE ?= Debug
|
BUILD_TYPE ?= Debug
|
||||||
|
|
||||||
payloads:
|
payloads:
|
||||||
@mkdir -p src/exploit/payloads
|
@for file in images/*; do \
|
||||||
@for file in payloads/*; do \
|
name=$$(basename "$$file"); \
|
||||||
|
name=$${name%.*}; \
|
||||||
echo " XXD $$file"; \
|
echo " XXD $$file"; \
|
||||||
xxd -i $$file > src/exploit/$$file.h; \
|
xxd -i -n "$$name" "$$file" > "src/gen/images/$$name.h"; \
|
||||||
done
|
done
|
||||||
xxd -i resources/logo.png > src/exploit/logo.h
|
|
||||||
|
xxd -i -n "DFUHelperDeviceInfo" resources/DFUHelperDeviceInfo.json > src/gen/DFUHelperDeviceInfo.h
|
||||||
|
|
||||||
palera1n: payloads
|
palera1n: payloads
|
||||||
@cmake -S . -B build \
|
@cmake -S . -B build \
|
||||||
-DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \
|
-DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \
|
||||||
-DWITH_GUI=$(WITH_GUI) \
|
-DWITH_GUI=$(WITH_GUI) \
|
||||||
-DWITH_STATIC=$(WITH_STATIC) && \
|
-DWITH_STATIC=$(WITH_STATIC) && \
|
||||||
cmake --build build -- -j$(sysctl -n hw.ncpu)
|
cmake --build build -- -j4
|
||||||
|
|
||||||
palera1n_xcode: payloads
|
palera1n_xcode: payloads
|
||||||
@cmake -S . -B build \
|
@cmake -S . -B build \
|
||||||
|
|||||||
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
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
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>palera.in.palera1n</string>
|
<string>English</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>English</string>
|
<string>palera1n</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>APPL</string>
|
<string>palera1n.icns</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>NSApplication</string>
|
<string>palera1n</string>
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<true/>
|
<string>6.0</string>
|
||||||
</dict>
|
<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>
|
</plist>
|
||||||
@@ -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>
|
|
||||||
|
Before Width: | Height: | Size: 6.0 KiB |
@@ -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
|
||||||
@@ -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
|
||||||
@@ -5,12 +5,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
#include <IOKit/IOKitLib.h>
|
|
||||||
#include <IOKit/usb/IOUSBLib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WITH_GUI
|
#ifdef WITH_GUI
|
||||||
# include <wx/wx.h>
|
# include <wx/wx.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -21,9 +15,16 @@
|
|||||||
|
|
||||||
void print_credits() {
|
void print_credits() {
|
||||||
printf(
|
printf(
|
||||||
":: ========================== ::\n"
|
"#\n"
|
||||||
":: palera1n: " PALERAIN_VERSION "\n"
|
"# palera1n: " PALERAIN_VERSION "\n"
|
||||||
":: ========================== ::\n\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"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
|
||||||
@@ -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,7 +1,7 @@
|
|||||||
#ifndef CONSTANTS_H
|
#ifndef CONSTANTS_H
|
||||||
#define CONSTANTS_H
|
#define CONSTANTS_H
|
||||||
|
|
||||||
#define PALERAIN_VERSION "2.4.0"
|
#define PALERAIN_VERSION "3.0.0"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||