int dfu_client_new(struct idevicerestore_client_t* client) { int i = 0; int attempts = 10; irecv_client_t dfu = NULL; irecv_error_t dfu_error = IRECV_E_UNKNOWN_ERROR; if (client->dfu == NULL) { client->dfu = (struct dfu_client_t*)malloc(sizeof(struct dfu_client_t)); memset(client->dfu, 0, sizeof(struct dfu_client_t)); if (client->dfu == NULL) { error("ERROR: Out of memory\n"); return -1; } } for (i = 1; i <= attempts; i++) { dfu_error = irecv_open_with_ecid(&dfu, client->ecid); if (dfu_error == IRECV_E_SUCCESS) { break; } if (i >= attempts) { error("ERROR: Unable to connect to device in DFU mode\n"); return -1; } sleep(1); debug("Retrying connection...\n"); } irecv_event_subscribe(dfu, IRECV_PROGRESS, &dfu_progress_callback, NULL); client->dfu->client = dfu; return 0; }
int pois0n_is_ready() { irecv_error_t error = IRECV_E_SUCCESS; ////////////////////////////////////// // Begin // debug("Connecting to device\n"); error = irecv_open_with_ecid(&client, 0); if (error != IRECV_E_SUCCESS) { debug("Device must be in DFU mode to continue\n"); return -1; } irecv_event_subscribe(client, IRECV_PROGRESS, &recovery_callback, NULL); ////////////////////////////////////// // Check device // debug("Checking the device mode\n"); int mode; if (irecv_get_mode(client, &mode) != IRECV_E_SUCCESS) { error("Unable to get current mode\n"); return -1; } if (mode != IRECV_K_DFU_MODE) { error("Device must be in DFU mode to continue\n"); irecv_close(client); return -1; } return 0; }
int recovery_client_new(struct idevicerestore_client_t* client) { int i = 0; int attempts = 20; irecv_client_t recovery = NULL; irecv_error_t recovery_error = IRECV_E_UNKNOWN_ERROR; if(client->recovery == NULL) { client->recovery = (struct recovery_client_t*)malloc(sizeof(struct recovery_client_t)); if (client->recovery == NULL) { error("ERROR: Out of memory\n"); return -1; } memset(client->recovery, 0, sizeof(struct recovery_client_t)); } for (i = 1; i <= attempts; i++) { recovery_error = irecv_open_with_ecid(&recovery, client->ecid); if (recovery_error == IRECV_E_SUCCESS) { break; } if (i >= attempts) { error("ERROR: Unable to connect to device in recovery mode\n"); return -1; } sleep(4); debug("Retrying connection...\n"); } if (client->srnm == NULL) { const struct irecv_device_info *device_info = irecv_get_device_info(recovery); if (device_info && device_info->srnm) { client->srnm = strdup(device_info->srnm); info("INFO: device serial number is %s\n", client->srnm); } } irecv_event_subscribe(recovery, IRECV_PROGRESS, &recovery_progress_callback, NULL); client->recovery->client = recovery; return 0; }
const char* dfu_check_hardware_model(struct idevicerestore_client_t* client) { irecv_client_t dfu = NULL; irecv_error_t dfu_error = IRECV_E_SUCCESS; irecv_device_t device = NULL; irecv_init(); dfu_error = irecv_open_with_ecid(&dfu, client->ecid); if (dfu_error != IRECV_E_SUCCESS) { return NULL; } dfu_error = irecv_devices_get_device_by_client(dfu, &device); if (dfu_error != IRECV_E_SUCCESS) { return NULL; } irecv_close(dfu); return device->hardware_model; }
int recovery_check_mode(struct idevicerestore_client_t* client) { irecv_client_t recovery = NULL; irecv_error_t recovery_error = IRECV_E_SUCCESS; int mode = 0; irecv_init(); recovery_error=irecv_open_with_ecid(&recovery, client->ecid); if (recovery_error != IRECV_E_SUCCESS) { return -1; } irecv_get_mode(recovery, &mode); if ((mode == IRECV_K_DFU_MODE) || (mode == IRECV_K_WTF_MODE)) { irecv_close(recovery); return -1; } irecv_close(recovery); recovery = NULL; return 0; }
int dfu_check_mode(struct idevicerestore_client_t* client, int* mode) { irecv_client_t dfu = NULL; irecv_error_t dfu_error = IRECV_E_SUCCESS; int probe_mode = -1; irecv_init(); dfu_error = irecv_open_with_ecid(&dfu, client->ecid); if (dfu_error != IRECV_E_SUCCESS) { return -1; } irecv_get_mode(dfu, &probe_mode); if ((probe_mode != IRECV_K_DFU_MODE) && (probe_mode != IRECV_K_WTF_MODE)) { irecv_close(dfu); return -1; } *mode = (probe_mode == IRECV_K_WTF_MODE) ? MODE_WTF : MODE_DFU; irecv_close(dfu); return 0; }
int main(int argc, char* argv[]) { int i = 0; int opt = 0; int action = 0; unsigned long long ecid = 0; int mode = -1; char* argument = NULL; irecv_error_t error = 0; char* buffer = NULL; uint64_t buffer_length = 0; if (argc == 1) { print_usage(argc, argv); return 0; } while ((opt = getopt(argc, argv, "i:vhrsmnc:f:e:k::")) > 0) { switch (opt) { case 'i': if (optarg) { char* tail = NULL; ecid = strtoull(optarg, &tail, 16); if (tail && (tail[0] != '\0')) { ecid = 0; } if (ecid == 0) { fprintf(stderr, "ERROR: Could not parse ECID from argument '%s'\n", optarg); return -1; } } break; case 'v': verbose += 1; break; case 'h': print_usage(argc, argv); return 0; case 'm': action = kShowMode; break; case 'n': action = kRebootToNormalMode; break; case 'r': action = kResetDevice; break; case 's': action = kStartShell; break; case 'f': action = kSendFile; argument = optarg; break; case 'c': action = kSendCommand; argument = optarg; break; case 'k': action = kSendExploit; argument = optarg; break; case 'e': action = kSendScript; argument = optarg; break; default: fprintf(stderr, "Unknown argument\n"); return -1; } } if (verbose) irecv_set_debug_level(verbose); irecv_init(); irecv_client_t client = NULL; for (i = 0; i <= 5; i++) { debug("Attempting to connect... \n"); if (irecv_open_with_ecid(&client, ecid) != IRECV_E_SUCCESS) sleep(1); else break; if (i == 5) { return -1; } } irecv_device_t device = NULL; irecv_devices_get_device_by_client(client, &device); if (device) debug("Connected to %s, model %s, cpid 0x%04x, bdid 0x%02x\n", device->product_type, device->hardware_model, device->chip_id, device->board_id); switch (action) { case kResetDevice: irecv_reset(client); break; case kSendFile: irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL); error = irecv_send_file(client, argument, 1); debug("%s\n", irecv_strerror(error)); break; case kSendCommand: error = irecv_send_command(client, argument); debug("%s\n", irecv_strerror(error)); break; case kSendExploit: if (argument != NULL) { irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL); error = irecv_send_file(client, argument, 0); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); break; } } error = irecv_trigger_limera1n_exploit(client); debug("%s\n", irecv_strerror(error)); break; case kStartShell: init_shell(client); break; case kSendScript: buffer_read_from_filename(argument, &buffer, &buffer_length); if (buffer) { buffer[buffer_length] = '\0'; error = irecv_execute_script(client, buffer); if(error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); } free(buffer); } else { fprintf(stderr, "Could not read file '%s'\n", argument); } break; case kShowMode: irecv_get_mode(client, &mode); printf("%s Mode\n", mode_to_str(mode)); break; case kRebootToNormalMode: error = irecv_setenv(client, "auto-boot", "true"); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); break; } error = irecv_saveenv(client); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); break; } error = irecv_reboot(client); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); } else { debug("%s\n", irecv_strerror(error)); } break; default: fprintf(stderr, "Unknown action\n"); break; } irecv_close(client); return 0; }