mirror of
https://github.com/palera1n/palera1n.git
synced 2026-10-23 18:49:48 +02:00
refactor: yolodfu detection, pongo compression
Update run.c
This commit is contained in:
13 files changed
+278
-236
No files matched your search
+44
-6
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "../utils.h"
|
#include "../utils.h"
|
||||||
#include "../usb/shim.h"
|
#include "../usb/shim.h"
|
||||||
|
#include "../usb/pongo_helper.h"
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
uint8_t b_len, b_descriptor_type;
|
uint8_t b_len, b_descriptor_type;
|
||||||
@@ -162,12 +163,8 @@ bool checkm8_stage_patch(const usb_handle_t *handle, struct DeviceConfiguration
|
|||||||
uint64_t* p = (uint64_t*)blank;
|
uint64_t* p = (uint64_t*)blank;
|
||||||
p[5] = payloadConfig->insecure_memory_base;
|
p[5] = payloadConfig->insecure_memory_base;
|
||||||
|
|
||||||
create_pongo_payload_for_device(deviceConfig->cpid, &payload, &data_sz);
|
ret = create_pongo_payload_for_device(deviceConfig->cpid, &payload, &data_sz);
|
||||||
|
if (!ret) return false;
|
||||||
if (payload == NULL || data_sz == 0) {
|
|
||||||
LOG_ERROR("unsupported cpid 0x%X", (unsigned)deviceConfig->cpid);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_VERBOSE("setting up stage 2 for CPID 0x%X", (unsigned)deviceConfig->cpid);
|
LOG_VERBOSE("setting up stage 2 for CPID 0x%X", (unsigned)deviceConfig->cpid);
|
||||||
|
|
||||||
@@ -200,3 +197,44 @@ bool checkm8_stage_patch(const usb_handle_t *handle, struct DeviceConfiguration
|
|||||||
free(data);
|
free(data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkm8_boot_pongo(usb_handle_t *handle)
|
||||||
|
{
|
||||||
|
transfer_ret_t transfer_ret;
|
||||||
|
|
||||||
|
uint8_t *out;
|
||||||
|
size_t out_len;
|
||||||
|
|
||||||
|
if (!prepare_pongo(&out, &out_len)) {
|
||||||
|
LOG_ERROR("Failed to prepare pongoOS payload");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
while (len < out_len)
|
||||||
|
{
|
||||||
|
size_t chunk = (out_len - len > 0x800) ? 0x800 : (out_len - len);
|
||||||
|
|
||||||
|
retry:
|
||||||
|
send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, out + len, chunk, &transfer_ret);
|
||||||
|
|
||||||
|
if (transfer_ret.sz != chunk || transfer_ret.ret != USB_TRANSFER_OK)
|
||||||
|
{
|
||||||
|
LOG_VERBOSE("retrying at len = %zu", len);
|
||||||
|
sleep_ms(100);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += chunk;
|
||||||
|
LOG_VERBOSE("len = %zu", len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(out);
|
||||||
|
|
||||||
|
send_usb_control_request_no_data(handle, 0x21, 4, 0, 0, 0, NULL);
|
||||||
|
LOG_SUCCESS("PongoOS has been sent off");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -18,5 +18,6 @@ bool checkm8_stage_reset(const usb_handle_t *handle);
|
|||||||
bool checkm8_stage_setup(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig);
|
bool checkm8_stage_setup(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig);
|
||||||
bool checkm8_stage_spray(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig);
|
bool checkm8_stage_spray(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig);
|
||||||
bool checkm8_stage_patch(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig);
|
bool checkm8_stage_patch(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig);
|
||||||
|
bool checkm8_boot_pongo(usb_handle_t *handle);
|
||||||
|
|
||||||
#endif // CHECKM8_H
|
#endif // CHECKM8_H
|
||||||
+5
-4
@@ -237,12 +237,12 @@ static const yolo_payload_t yolo_payloads[] = {
|
|||||||
{0x7000, payloads_yolo_t7000_bin, payloads_yolo_t7000_bin_len},
|
{0x7000, payloads_yolo_t7000_bin, payloads_yolo_t7000_bin_len},
|
||||||
};
|
};
|
||||||
|
|
||||||
void create_pongo_payload_for_device(
|
bool create_pongo_payload_for_device(
|
||||||
uint16_t cpid,
|
uint16_t cpid,
|
||||||
const uint8_t **payload,
|
const uint8_t **payload,
|
||||||
size_t *payloadSize)
|
size_t *payloadSize)
|
||||||
{
|
{
|
||||||
LOG_VERBOSE("Preparing YoloDFU payload for CPID 0x%x.", cpid);
|
LOG_VERBOSE("Preparing YoloDFU payload for CPID 0x%x", cpid);
|
||||||
|
|
||||||
*payload = NULL;
|
*payload = NULL;
|
||||||
*payloadSize = 0;
|
*payloadSize = 0;
|
||||||
@@ -253,9 +253,10 @@ void create_pongo_payload_for_device(
|
|||||||
if (yolo_payloads[i].cpid == cpid) {
|
if (yolo_payloads[i].cpid == cpid) {
|
||||||
*payload = yolo_payloads[i].data;
|
*payload = yolo_payloads[i].data;
|
||||||
*payloadSize = yolo_payloads[i].len;
|
*payloadSize = yolo_payloads[i].len;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("Failed to prepare payload for device with CPID 0x%x.", cpid);
|
LOG("Failed to prepare payload for device with CPID 0x%x", cpid);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
+1
-1
@@ -46,6 +46,6 @@ typedef struct {
|
|||||||
|
|
||||||
bool checkm8_find_device_configuration_for_cpid(uint16_t cpid, struct DeviceConfiguration *config);
|
bool checkm8_find_device_configuration_for_cpid(uint16_t cpid, struct DeviceConfiguration *config);
|
||||||
bool checkm8_find_payload_configuration_for_cpid(uint16_t cpid, struct PayloadConfiguration *config);
|
bool checkm8_find_payload_configuration_for_cpid(uint16_t cpid, struct PayloadConfiguration *config);
|
||||||
void create_pongo_payload_for_device(uint16_t cpid, const uint8_t **payload, size_t *payloadSize);
|
bool create_pongo_payload_for_device(uint16_t cpid, const uint8_t **payload, size_t *payloadSize);
|
||||||
|
|
||||||
#endif // PAYLOAD_H
|
#endif // PAYLOAD_H
|
||||||
+113
-118
@@ -19,164 +19,161 @@
|
|||||||
#include "dfu.h"
|
#include "dfu.h"
|
||||||
#include "payload.h"
|
#include "payload.h"
|
||||||
|
|
||||||
|
#define VID_APPLE (0x5AC)
|
||||||
|
#define PID_PONGO (0x4141)
|
||||||
|
#define PID_DFU (0x1227)
|
||||||
|
|
||||||
static void *exploit_thread(void *arg)
|
static void *exploit_thread(void *arg)
|
||||||
{
|
{
|
||||||
|
LOG_VERBOSE("Starting thread for DFU devices");
|
||||||
LOG("Waiting for DFU devices...");
|
LOG("Waiting for DFU devices...");
|
||||||
|
|
||||||
shared_t *s = (shared_t *)arg;
|
shared_t *s = (shared_t *)arg;
|
||||||
|
|
||||||
usb_handle_t handle;
|
usb_handle_t handle;
|
||||||
struct DeviceConfiguration deviceConfig;
|
struct DeviceConfiguration deviceConfig;
|
||||||
struct PayloadConfiguration payloadConfig;
|
struct PayloadConfiguration payloadConfig;
|
||||||
|
|
||||||
int stage = STAGE_PREPARE;
|
int stage = STAGE_RESET;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
init_usb_handle(&handle, 0x5AC, 0x1227);
|
init_usb_handle(&handle, VID_APPLE, PID_DFU);
|
||||||
|
|
||||||
while (stage != STAGE_JAILBREAK && !atomic_load(&s->stop)) {
|
while (!atomic_load(&s->stop)) {
|
||||||
if (!wait_usb_handle(&handle)) {
|
if (!wait_usb_handle(&handle)) {
|
||||||
atomic_store(&s->result, -1);
|
reset_usb_handle(&handle);
|
||||||
atomic_store(&s->stop, true);
|
continue;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *sn = get_usb_serial_number(&handle);
|
||||||
|
if (!sn) {
|
||||||
|
reset_usb_handle(&handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t cpid = dfu_serial_number_get_cpid(sn);
|
||||||
|
if (!checkm8_find_device_configuration_for_cpid(cpid, &deviceConfig)
|
||||||
|
|| !checkm8_find_payload_configuration_for_cpid(cpid, &payloadConfig))
|
||||||
|
{
|
||||||
|
free(sn);
|
||||||
|
reset_usb_handle(&handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dfu_serial_number_is_pwned(sn)) {
|
||||||
|
LOG_WARN("Detected already PWN'd device, skipping");
|
||||||
|
free(sn);
|
||||||
|
reset_usb_handle(&handle);
|
||||||
|
continue;
|
||||||
|
} else if (dfu_serial_number_is_in_dfu_mode(sn)) {
|
||||||
|
LOG_SUCCESS("Detected DFU device");
|
||||||
|
} else if (dfu_serial_number_is_in_yolo_dfu(sn)) {
|
||||||
|
LOG_SUCCESS("Detected YoloDFU device");
|
||||||
|
stage = STAGE_YOLODFU;
|
||||||
|
} else {
|
||||||
|
free(sn);
|
||||||
|
reset_usb_handle(&handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(sn);
|
||||||
atomic_store(&s->stage, stage);
|
atomic_store(&s->stage, stage);
|
||||||
|
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case STAGE_PREPARE: {
|
case STAGE_RESET:
|
||||||
char *sn = get_usb_serial_number(&handle);
|
ret = checkm8_stage_reset(&handle);
|
||||||
if (!sn) goto fail;
|
stage = ret ? STAGE_SETUP : STAGE_RESET;
|
||||||
|
break;
|
||||||
uint64_t cpid = dfu_serial_number_get_cpid(sn);
|
case STAGE_SETUP:
|
||||||
|
LOG("Checking if device is ready");
|
||||||
if (!checkm8_find_device_configuration_for_cpid(cpid, &deviceConfig)) {
|
ret = checkm8_stage_setup(&handle, &deviceConfig);
|
||||||
free(sn);
|
stage = ret ? STAGE_SPRAY : STAGE_RESET;
|
||||||
goto fail;
|
break;
|
||||||
}
|
case STAGE_SPRAY:
|
||||||
|
LOG("Setting up the exploit (this is the heap spray)");
|
||||||
if (!checkm8_find_payload_configuration_for_cpid(cpid, &payloadConfig)) {
|
ret = checkm8_stage_spray(&handle, &deviceConfig);
|
||||||
free(sn);
|
stage = ret ? STAGE_PATCH : STAGE_RESET;
|
||||||
goto fail;
|
break;
|
||||||
}
|
case STAGE_PATCH:
|
||||||
|
LOG("Right before trigger (this is the real bug setup)");
|
||||||
if (!dfu_serial_number_is_in_dfu_mode(sn)) {
|
ret = checkm8_stage_patch(&handle, &deviceConfig, &payloadConfig);
|
||||||
free(sn);
|
stage = STAGE_RESET;
|
||||||
goto fail;
|
if (!ret) {
|
||||||
}
|
LOG_ERROR("Failed doing trigger");
|
||||||
|
break;
|
||||||
free(sn);
|
}
|
||||||
stage = STAGE_RESET;
|
continue;
|
||||||
break;
|
case STAGE_YOLODFU:
|
||||||
}
|
LOG("Booting PongoOS...");
|
||||||
case STAGE_RESET:
|
ret = checkm8_boot_pongo(&handle);
|
||||||
ret = checkm8_stage_reset(&handle);
|
if (!ret) LOG_ERROR("Failed to send PongoOS to device");
|
||||||
stage = ret ? STAGE_SETUP : STAGE_PREPARE;
|
stage = STAGE_RESET;
|
||||||
break;
|
break;
|
||||||
case STAGE_SETUP:
|
|
||||||
LOG("Setting up the device for exploitation");
|
|
||||||
ret = checkm8_stage_setup(&handle, &deviceConfig);
|
|
||||||
stage = ret ? STAGE_SPRAY : STAGE_PREPARE;
|
|
||||||
break;
|
|
||||||
case STAGE_SPRAY:
|
|
||||||
LOG("Spraying the device with USB requests");
|
|
||||||
ret = checkm8_stage_spray(&handle, &deviceConfig);
|
|
||||||
stage = ret ? STAGE_PATCH : STAGE_PREPARE;
|
|
||||||
break;
|
|
||||||
case STAGE_PATCH:
|
|
||||||
LOG("Right before trigger (bug setup)");
|
|
||||||
ret = checkm8_stage_patch(&handle, &deviceConfig, &payloadConfig);
|
|
||||||
if (!ret) goto fail;
|
|
||||||
stage = STAGE_PONGO;
|
|
||||||
break;
|
|
||||||
case STAGE_PONGO:
|
|
||||||
LOG("Booting pongoOS");
|
|
||||||
|
|
||||||
close_usb_handle(&handle);
|
|
||||||
sleep_ms(3000);
|
|
||||||
|
|
||||||
checkm8_boot_pongo(&handle);
|
|
||||||
|
|
||||||
atomic_store(&s->exploit_done, true);
|
|
||||||
atomic_store(&s->pongo_done, true);
|
|
||||||
atomic_store(&s->stage, STAGE_JAILBREAK);
|
|
||||||
|
|
||||||
stage = STAGE_JAILBREAK;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_usb_handle(&handle);
|
reset_usb_handle(&handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_store(&s->result, 1);
|
close_usb_handle(&handle);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
atomic_store(&s->result, -1);
|
|
||||||
atomic_store(&s->stop, true);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *pongo_thread(void *arg)
|
static void *pongo_thread(void *arg)
|
||||||
{
|
{
|
||||||
LOG("Waiting for Pongo devices...");
|
LOG_VERBOSE("Starting thread for PongoOS devices");
|
||||||
|
|
||||||
shared_t *s = (shared_t *)arg;
|
shared_t *s = (shared_t *)arg;
|
||||||
|
|
||||||
usb_handle_t handle;
|
usb_handle_t handle;
|
||||||
bool seen = false;
|
bool seen = false;
|
||||||
|
|
||||||
init_usb_handle(&handle, 0x5AC, 0x4141);
|
init_usb_handle(&handle, VID_APPLE, PID_PONGO);
|
||||||
|
|
||||||
while (!atomic_load(&s->stop)) {
|
while (!atomic_load(&s->stop)) {
|
||||||
|
|
||||||
if (!wait_usb_handle(&handle)) {
|
if (!wait_usb_handle(&handle)) {
|
||||||
atomic_store(&s->result, -1);
|
if (atomic_load(&s->stop)) break;
|
||||||
atomic_store(&s->stop, true);
|
reset_usb_handle(&handle);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!seen) {
|
if (seen) continue;
|
||||||
seen = true;
|
seen = true;
|
||||||
|
|
||||||
LOG_SUCCESS("Pongo device detected!");
|
LOG_SUCCESS("Detected PongoOS device");
|
||||||
|
|
||||||
if (palerain_flags & palerain_option_pongo_exit) {
|
atomic_store(&s->stage, STAGE_PONGO);
|
||||||
close_usb_handle(&handle);
|
|
||||||
atomic_store(&s->pongo_done, true);
|
|
||||||
atomic_store(&s->stage, STAGE_DONE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
char paleinfo[64];
|
if (palerain_flags & palerain_option_pongo_exit) {
|
||||||
snprintf(paleinfo, sizeof(paleinfo), "palera1n_flags 0x%" PRIx64, palerain_flags);
|
close_usb_handle(&handle);
|
||||||
|
|
||||||
char xargs_cmd[0x270];
|
|
||||||
snprintf(xargs_cmd, sizeof(xargs_cmd), "xargs %s", boot_args);
|
|
||||||
if ((palerain_flags & palerain_option_setup_rootful)) {
|
|
||||||
strncat(xargs_cmd, " wdt=-1", 0x270 - strlen(xargs_cmd) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG("Boot arguments: %s", xargs_cmd);
|
|
||||||
|
|
||||||
issue_pongo_command(&handle, "fuse lock");
|
|
||||||
issue_pongo_command(&handle, "sep auto");
|
|
||||||
upload_buffer_to_pongo(&handle, g_payload_kpf.data, g_payload_kpf.data_len);
|
|
||||||
issue_pongo_command(&handle, "modload");
|
|
||||||
issue_pongo_command(&handle, paleinfo);
|
|
||||||
upload_buffer_to_pongo(&handle, g_payload_ramdisk.data, g_payload_ramdisk.data_len);
|
|
||||||
issue_pongo_command(&handle, "ramdisk");
|
|
||||||
upload_buffer_to_pongo(&handle, g_payload_overlay.data, g_payload_overlay.data_len);
|
|
||||||
issue_pongo_command(&handle, "overlay");
|
|
||||||
if (strlen(boot_args) > 0)
|
|
||||||
issue_pongo_command(&handle, xargs_cmd);
|
|
||||||
issue_pongo_command(&handle, "bootx");
|
|
||||||
|
|
||||||
atomic_store(&s->pongo_done, true);
|
|
||||||
atomic_store(&s->stage, STAGE_DONE);
|
atomic_store(&s->stage, STAGE_DONE);
|
||||||
|
atomic_store(&s->stop, true);
|
||||||
break;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char paleinfo[64];
|
||||||
|
snprintf(paleinfo, sizeof(paleinfo), "palera1n_flags 0x%" PRIx64, palerain_flags);
|
||||||
|
|
||||||
|
char xargs_cmd[0x270];
|
||||||
|
snprintf(xargs_cmd, sizeof(xargs_cmd), "xargs %s", boot_args);
|
||||||
|
if (palerain_flags & palerain_option_setup_rootful) {
|
||||||
|
strncat(xargs_cmd, " wdt=-1", sizeof(xargs_cmd) - strlen(xargs_cmd) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_pongo_command(&handle, "fuse lock");
|
||||||
|
issue_pongo_command(&handle, "sep auto");
|
||||||
|
upload_buffer_to_pongo(&handle, g_payload_kpf.data, g_payload_kpf.data_len);
|
||||||
|
issue_pongo_command(&handle, "modload");
|
||||||
|
issue_pongo_command(&handle, paleinfo);
|
||||||
|
upload_buffer_to_pongo(&handle, g_payload_ramdisk.data, g_payload_ramdisk.data_len);
|
||||||
|
issue_pongo_command(&handle, "ramdisk");
|
||||||
|
upload_buffer_to_pongo(&handle, g_payload_overlay.data, g_payload_overlay.data_len);
|
||||||
|
issue_pongo_command(&handle, "overlay");
|
||||||
|
if (strlen(boot_args) > 0) issue_pongo_command(&handle, xargs_cmd);
|
||||||
|
issue_pongo_command(&handle, "bootx");
|
||||||
|
|
||||||
|
atomic_store(&s->stage, STAGE_DONE);
|
||||||
|
atomic_store(&s->stop, true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
close_usb_handle(&handle);
|
close_usb_handle(&handle);
|
||||||
@@ -193,7 +190,5 @@ bool exploit(shared_t *state)
|
|||||||
pthread_join(t1, NULL);
|
pthread_join(t1, NULL);
|
||||||
pthread_join(t2, NULL);
|
pthread_join(t2, NULL);
|
||||||
|
|
||||||
return atomic_load(&state->result) == 1 &&
|
return atomic_load(&state->result) == 1 && atomic_load(&state->stop);
|
||||||
atomic_load(&state->exploit_done) &&
|
|
||||||
atomic_load(&state->pongo_done);
|
|
||||||
}
|
}
|
||||||
+7
-12
@@ -13,23 +13,18 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum exploit_stage {
|
enum exploit_stage {
|
||||||
STAGE_PREPARE = 0,
|
STAGE_RESET = 0,
|
||||||
STAGE_RESET = 1,
|
STAGE_SETUP = 1,
|
||||||
STAGE_SETUP = 2,
|
STAGE_SPRAY = 2,
|
||||||
STAGE_SPRAY = 3,
|
STAGE_PATCH = 3,
|
||||||
STAGE_PATCH = 4,
|
STAGE_YOLODFU = 4,
|
||||||
STAGE_PONGO = 5,
|
STAGE_PONGO = 5,
|
||||||
STAGE_JAILBREAK = 6,
|
STAGE_DONE = 6,
|
||||||
STAGE_DONE = 7,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
atomic_int result;
|
atomic_int result;
|
||||||
atomic_bool stop;
|
atomic_bool stop;
|
||||||
|
|
||||||
atomic_bool exploit_done;
|
|
||||||
atomic_bool pongo_done;
|
|
||||||
|
|
||||||
atomic_int stage;
|
atomic_int stage;
|
||||||
} shared_t;
|
} shared_t;
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -1,9 +1,10 @@
|
|||||||
#include <unistd.h> // isatty, STDIN_FILENO
|
#include <unistd.h>
|
||||||
#include <cstdlib> // getenv
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#ifdef WITH_GUI
|
#ifdef WITH_GUI
|
||||||
# include <wx/wx.h>
|
# include <wx/wx.h>
|
||||||
|
|||||||
+63
-48
@@ -14,57 +14,72 @@
|
|||||||
|
|
||||||
#include "../gen/payloads/lz4dec.h"
|
#include "../gen/payloads/lz4dec.h"
|
||||||
|
|
||||||
void compress_pongo(void *out, size_t *out_len) {
|
static bool compress_pongo(uint8_t **out, size_t *out_len)
|
||||||
size_t len = g_payload_pongo.data_len;
|
{
|
||||||
size_t out_len_ = *out_len;
|
const uint8_t *src = g_payload_pongo.data;
|
||||||
*out_len = LZ4_compress_HC(g_payload_pongo.data, out, len, out_len_, LZ4HC_CLEVEL_MAX);
|
int src_size = (int)g_payload_pongo.data_len;
|
||||||
|
|
||||||
|
int max_size = LZ4_compressBound(src_size);
|
||||||
|
|
||||||
|
uint8_t *buf = malloc(max_size);
|
||||||
|
if (!buf) return false;
|
||||||
|
|
||||||
|
int size = LZ4_compress_HC(
|
||||||
|
(const char *)src,
|
||||||
|
(char *)buf,
|
||||||
|
src_size,
|
||||||
|
max_size,
|
||||||
|
LZ4HC_CLEVEL_MAX
|
||||||
|
);
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
free(buf);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = buf;
|
||||||
|
*out_len = (size_t)size;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkm8_boot_pongo(usb_handle_t *handle) {
|
#define SHELLCODE_SZ (512)
|
||||||
transfer_ret_t transfer_ret;
|
#define PONGO_MAX_SZ (0x7fe00)
|
||||||
LOG_VERBOSE("Booting pongoOS");
|
|
||||||
LOG_VERBOSE("Compressing pongoOS");
|
bool prepare_pongo(uint8_t **out, size_t *out_len)
|
||||||
LOG_VERBOSE("Appending shellcode to the top of pongoOS (512 bytes)");
|
{
|
||||||
void *shellcode = malloc(512);
|
if (g_payload_pongo.data_len > PONGO_MAX_SZ) {
|
||||||
memcpy(shellcode, payloads_lz4dec_bin, payloads_lz4dec_bin_len);
|
LOG_ERROR("Pongo payload too large: %zu bytes (max 511 KB)", g_payload_pongo.data_len);
|
||||||
size_t out_len = g_payload_pongo.data_len;
|
return false;
|
||||||
void *out = malloc(out_len);
|
|
||||||
compress_pongo(out, &out_len);
|
|
||||||
LOG_VERBOSE("Compressed pongoOS from %u to %zu bytes", g_payload_pongo.data_len, out_len);
|
|
||||||
void *tmp = malloc(out_len + 512);
|
|
||||||
memcpy(tmp, shellcode, 512);
|
|
||||||
memcpy(tmp + 512, out, out_len);
|
|
||||||
free(out);
|
|
||||||
out = tmp;
|
|
||||||
out_len += 512;
|
|
||||||
free(shellcode);
|
|
||||||
LOG_VERBOSE("Setting the compressed size into the shellcode");
|
|
||||||
uint32_t* size = (uint32_t*)(out + 0x1fc);
|
|
||||||
*size = out_len - 512;
|
|
||||||
LOG_VERBOSE("Reconnecting to device");
|
|
||||||
init_usb_handle(handle, 0x5AC, 0x1227);
|
|
||||||
LOG_VERBOSE("Waiting for device to be ready");
|
|
||||||
wait_usb_handle(handle);
|
|
||||||
{
|
|
||||||
size_t len = 0;
|
|
||||||
size_t size;
|
|
||||||
while(len < out_len)
|
|
||||||
{
|
|
||||||
retry:
|
|
||||||
size = ((out_len - len) > 0x800) ? 0x800 : (out_len - len);
|
|
||||||
send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, (unsigned char*)&out[len], size, &transfer_ret);
|
|
||||||
if(transfer_ret.sz != size || transfer_ret.ret != USB_TRANSFER_OK)
|
|
||||||
{
|
|
||||||
LOG_VERBOSE("retrying at len = %zu", len);
|
|
||||||
sleep_ms(100);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
len += size;
|
|
||||||
LOG_VERBOSE("len = %zu", len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
send_usb_control_request_no_data(handle, 0x21, 4, 0, 0, 0, NULL);
|
|
||||||
LOG_VERBOSE("pongoOS sent, should be booting");
|
size_t pongoSize;
|
||||||
|
uint8_t *pongo;
|
||||||
|
|
||||||
|
if (!compress_pongo(&pongo, &pongoSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint8_t *payload = malloc(SHELLCODE_SZ + pongoSize);
|
||||||
|
if (!payload) {
|
||||||
|
free(pongo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(payload, payloads_lz4dec_bin, SHELLCODE_SZ);
|
||||||
|
memcpy(payload + SHELLCODE_SZ, pongo, pongoSize);
|
||||||
|
|
||||||
|
free(pongo);
|
||||||
|
|
||||||
|
pongo = payload;
|
||||||
|
pongoSize += SHELLCODE_SZ;
|
||||||
|
|
||||||
|
uint32_t *pongoSizeInData = (uint32_t *)(pongo + 0x1fc);
|
||||||
|
*pongoSizeInData = (uint32_t)pongoSize - SHELLCODE_SZ;
|
||||||
|
|
||||||
|
*out = pongo;
|
||||||
|
*out_len = pongoSize;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int issue_pongo_command(const usb_handle_t *handle, const char *command) {
|
int issue_pongo_command(const usb_handle_t *handle, const char *command) {
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
|
|
||||||
#define CMD_LENGTH_MAX 512
|
#define CMD_LENGTH_MAX 512
|
||||||
|
|
||||||
void compress_pongo(void *out, size_t *out_len);
|
bool prepare_pongo(uint8_t **out, size_t *out_len);
|
||||||
void checkm8_boot_pongo(usb_handle_t *handle);
|
|
||||||
int issue_pongo_command(const usb_handle_t *handle, const char *command);
|
int issue_pongo_command(const usb_handle_t *handle, const char *command);
|
||||||
bool upload_buffer_to_pongo(usb_handle_t *handle, const void *data, size_t length);
|
bool upload_buffer_to_pongo(usb_handle_t *handle, const void *data, size_t length);
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -88,10 +88,9 @@ DfuPanel::DfuPanel(MainFrame* frame, wxWindow* parent)
|
|||||||
});
|
});
|
||||||
|
|
||||||
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
|
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
bottomRow->AddStretchSpacer();
|
bottomRow->AddStretchSpacer();
|
||||||
bottomRow->Add(m_backButton, 0, wxALL, 12);
|
bottomRow->Add(m_backButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 12);
|
||||||
bottomRow->Add(m_startButton, 0, wxALL, 12);
|
bottomRow->Add(m_startButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 12);
|
||||||
|
|
||||||
root->Add(bottomRow, 0, wxEXPAND);
|
root->Add(bottomRow, 0, wxEXPAND);
|
||||||
|
|
||||||
|
|||||||
+35
-37
@@ -9,34 +9,31 @@
|
|||||||
|
|
||||||
#include "AppFrame.hpp"
|
#include "AppFrame.hpp"
|
||||||
#include "../m8/run.h"
|
#include "../m8/run.h"
|
||||||
|
#include "../utils.h"
|
||||||
|
|
||||||
static const char* stage_to_string(int stage)
|
static const char* stage_to_string(int stage)
|
||||||
{
|
{
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case STAGE_PREPARE: return "Checking if device is ready";
|
case STAGE_SETUP: return "Checking if device is ready";
|
||||||
case STAGE_RESET: return "Checking if device is ready";
|
case STAGE_SPRAY: return "Setting up the exploit (this is the heap spray)";
|
||||||
case STAGE_SETUP: return "Setting up the exploit (this is the heap spray)";
|
case STAGE_PATCH: return "Right before trigger (this is the real bug setup)";
|
||||||
case STAGE_SPRAY: return "Setting up the exploit (this is the heap spray)";
|
case STAGE_YOLODFU: return "Booting PongoOS...";
|
||||||
case STAGE_PATCH: return "Right before trigger (this is the real bug setup)";
|
case STAGE_PONGO: return "Booting...";
|
||||||
case STAGE_PONGO: return "Booting...";
|
case STAGE_DONE: return "Done.";
|
||||||
case STAGE_JAILBREAK: return "Booting...";
|
default: return "Idle.";
|
||||||
case STAGE_DONE: return "Done.";
|
|
||||||
default: return "Working...";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stage_to_progress(int stage)
|
static int stage_to_progress(int stage)
|
||||||
{
|
{
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case STAGE_PREPARE: return 5;
|
case STAGE_SETUP: return 30;
|
||||||
case STAGE_RESET: return 15;
|
case STAGE_SPRAY: return 40;
|
||||||
case STAGE_SETUP: return 30;
|
case STAGE_PATCH: return 50;
|
||||||
case STAGE_SPRAY: return 50;
|
case STAGE_YOLODFU: return 60;
|
||||||
case STAGE_PATCH: return 70;
|
case STAGE_PONGO: return 70;
|
||||||
case STAGE_PONGO: return 90;
|
case STAGE_DONE: return 100;
|
||||||
case STAGE_JAILBREAK: return 95;
|
default: return 0;
|
||||||
case STAGE_DONE: return 100;
|
|
||||||
default: return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +64,11 @@ ExploitPanel::ExploitPanel(MainFrame* frame, wxWindow* parent)
|
|||||||
root->Add(m_progressBar, 0, wxALL | wxEXPAND, 20);
|
root->Add(m_progressBar, 0, wxALL | wxEXPAND, 20);
|
||||||
|
|
||||||
root->AddStretchSpacer();
|
root->AddStretchSpacer();
|
||||||
root->Add(m_backButton, 0, wxALL | wxALIGN_RIGHT, 12);
|
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
bottomRow->AddStretchSpacer();
|
||||||
|
bottomRow->Add(m_backButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 12);
|
||||||
|
|
||||||
|
root->Add(bottomRow, 0, wxEXPAND);
|
||||||
|
|
||||||
SetSizer(root);
|
SetSizer(root);
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,6 @@ void ExploitPanel::SetDeviceState(const DeviceState& state)
|
|||||||
|
|
||||||
void ExploitPanel::StartExploit()
|
void ExploitPanel::StartExploit()
|
||||||
{
|
{
|
||||||
m_statusText->SetLabel("Starting...");
|
|
||||||
m_backButton->Disable();
|
m_backButton->Disable();
|
||||||
|
|
||||||
std::thread([this]()
|
std::thread([this]()
|
||||||
@@ -91,38 +91,36 @@ void ExploitPanel::StartExploit()
|
|||||||
if (!deviceState.connected || deviceState.mode != DeviceMode::DFU)
|
if (!deviceState.connected || deviceState.mode != DeviceMode::DFU)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
shared_t state{};
|
auto state = std::make_shared<shared_t>();
|
||||||
atomic_init(&state.result, 0);
|
atomic_init(&state->stage, STAGE_RESET);
|
||||||
atomic_init(&state.stop, false);
|
atomic_init(&state->stop, false);
|
||||||
atomic_init(&state.exploit_done, false);
|
atomic_init(&state->result, 0);
|
||||||
atomic_init(&state.pongo_done, false);
|
|
||||||
atomic_init(&state.stage, STAGE_PREPARE);
|
|
||||||
|
|
||||||
std::thread worker([&]() {
|
std::thread worker([state]()
|
||||||
exploit(&state);
|
{
|
||||||
|
exploit(state.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.detach();
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int stage = atomic_load(&state.stage);
|
int stage = atomic_load(&state->stage);
|
||||||
int progress = stage_to_progress(stage);
|
int progress = stage_to_progress(stage);
|
||||||
|
|
||||||
wxTheApp->CallAfter([this, stage, progress]() {
|
wxTheApp->CallAfter([this, stage, progress]()
|
||||||
|
{
|
||||||
m_statusText->SetLabel(stage_to_string(stage));
|
m_statusText->SetLabel(stage_to_string(stage));
|
||||||
m_progressBar->SetValue(progress);
|
m_progressBar->SetValue(progress);
|
||||||
|
if (stage == STAGE_DONE) m_backButton->Enable();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (stage == STAGE_DONE) {
|
if (stage == STAGE_DONE)
|
||||||
wxTheApp->CallAfter([this]() {
|
|
||||||
m_backButton->Enable();
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (worker.joinable())
|
||||||
|
worker.join();
|
||||||
}).detach();
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ RecoveryPanel::RecoveryPanel(MainFrame* frame, wxWindow* parent)
|
|||||||
|
|
||||||
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
|
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
|
||||||
bottomRow->AddStretchSpacer();
|
bottomRow->AddStretchSpacer();
|
||||||
bottomRow->Add(m_backButton, 0, wxALL, 12);
|
bottomRow->Add(m_backButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 12);
|
||||||
bottomRow->Add(m_nextButton, 0, wxALL, 12);
|
bottomRow->Add(m_nextButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 12);
|
||||||
|
|
||||||
root->AddStretchSpacer();
|
root->AddStretchSpacer();
|
||||||
root->Add(bottomRow, 0, wxEXPAND);
|
root->Add(bottomRow, 0, wxEXPAND);
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent)
|
|||||||
|
|
||||||
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
|
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
|
||||||
bottomRow->AddStretchSpacer();
|
bottomRow->AddStretchSpacer();
|
||||||
bottomRow->Add(back, 0, wxALL, 12);
|
bottomRow->Add(back, 0, wxRIGHT | wxLEFT | wxBOTTOM, 12);
|
||||||
|
|
||||||
root->Add(bottomRow, 0, wxEXPAND);
|
root->Add(bottomRow, 0, wxEXPAND);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user