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 upload_dfu_image(const char* type) { char image[255]; struct stat buf; irecv_error_t error = IRECV_E_SUCCESS; memset(image, '\0', 255); snprintf(image, 254, "%s.%s", type, device->hardware_model); debug("Checking if %s already exists\n", image); if (stat(image, &buf) != 0) { if (fetch_dfu_image(type, image) < 0) { error("Unable to upload DFU image\n"); return -1; } } 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) { debug("Resetting device counters\n"); error = irecv_reset_counters(client); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); return -1; } } debug("Uploading %s to device\n", image); error = irecv_send_file(client, image, 1); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); return -1; } return 0; }
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 dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity) { irecv_error_t dfu_error = IRECV_E_SUCCESS; int mode = 0; if (dfu_client_new(client) < 0) { error("ERROR: Unable to connect to DFU device\n"); return -1; } irecv_get_mode(client->dfu->client, &mode); if (mode != IRECV_K_DFU_MODE) { info("NOTE: device is not in DFU mode, assuming recovery mode.\n"); client->mode = &idevicerestore_modes[MODE_RECOVERY]; return 0; } if (dfu_send_component(client, build_identity, "iBSS") < 0) { error("ERROR: Unable to send iBSS to device\n"); irecv_close(client->dfu->client); client->dfu->client = NULL; return -1; } irecv_usb_control_transfer(client->dfu->client, 0x21, 1, 0, 0, 0, 0, 5000); dfu_error = irecv_reset(client->dfu->client); if (dfu_error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset device\n"); irecv_close(client->dfu->client); client->dfu->client = NULL; return -1; } if (client->build_major > 8) { /* reconnect */ dfu_client_free(client); sleep(2); dfu_client_new(client); /* get nonce */ unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (dfu_get_ap_nonce(client, &nonce, &nonce_size) < 0) { error("ERROR: Unable to get ApNonce from device!\n"); return -1; } if (!client->nonce || (nonce_size != client->nonce_size) || (memcmp(nonce, client->nonce, nonce_size) != 0)) { nonce_changed = 1; if (client->nonce) { free(client->nonce); } client->nonce = nonce; client->nonce_size = nonce_size; } else { free(nonce); } info("Nonce: "); int i; for (i = 0; i < client->nonce_size; i++) { info("%02x ", client->nonce[i]); } info("\n"); if (nonce_changed && !(client->flags & FLAG_CUSTOM)) { // Welcome iOS5. We have to re-request the TSS with our nonce. plist_free(client->tss); if (get_tss_response(client, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } if (!client->tss) { error("ERROR: can't continue without TSS\n"); return -1; } fixup_tss(client->tss); } if (irecv_usb_set_configuration(client->dfu->client, 1) < 0) { error("ERROR: set configuration failed\n"); } /* send iBEC */ if (dfu_send_component(client, build_identity, "iBEC") < 0) { error("ERROR: Unable to send iBEC to device\n"); irecv_close(client->dfu->client); client->dfu->client = NULL; return -1; } irecv_usb_control_transfer(client->dfu->client, 0x21, 1, 0, 0, 0, 0, 5000); dfu_error = irecv_reset(client->dfu->client); if (dfu_error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset device\n"); irecv_close(client->dfu->client); client->dfu->client = NULL; return -1; } } dfu_client_free(client); sleep(7); // Reconnect to device, but this time make sure we're not still in DFU mode if (recovery_client_new(client) < 0) { error("ERROR: Unable to connect to recovery device\n"); if (client->recovery->client) { irecv_close(client->recovery->client); client->recovery->client = NULL; } return -1; } irecv_get_mode(client->recovery->client, &mode); if (mode == IRECV_K_DFU_MODE) { error("ERROR: Unable to connect to recovery device\n"); if (client->recovery->client) { irecv_close(client->recovery->client); client->recovery->client = NULL; } return -1; } 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; }
static void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) { char* cmd = strdup((char*)command); char* action = strtok(cmd, " "); if (!strcmp(cmd, "/exit")) { quit = 1; } else if (!strcmp(cmd, "/help")) { shell_usage(); } else if (!strcmp(cmd, "/upload")) { char* filename = strtok(NULL, " "); debug("Uploading files %s\n", filename); if (filename != NULL) { irecv_send_file(client, filename, 0); } } else if (!strcmp(cmd, "/deviceinfo")) { int ret, mode; unsigned int cpid, bdid; unsigned long long ecid; char srnm[12], imei[15]; ret = irecv_get_cpid(client, &cpid); if(ret == IRECV_E_SUCCESS) { printf("CPID: %d\n", cpid); } ret = irecv_get_bdid(client, &bdid); if(ret == IRECV_E_SUCCESS) { printf("BDID: %d\n", bdid); } ret = irecv_get_ecid(client, &ecid); if(ret == IRECV_E_SUCCESS) { printf("ECID: " _FMT_lld "\n", ecid); } ret = irecv_get_srnm(client, srnm); if(ret == IRECV_E_SUCCESS) { printf("SRNM: %s\n", srnm); } ret = irecv_get_imei(client, imei); if(ret == IRECV_E_SUCCESS) { printf("IMEI: %s\n", imei); } ret = irecv_get_mode(client, &mode); if (ret == IRECV_E_SUCCESS) { printf("MODE: %s\n", mode_to_str(mode)); } } else if (!strcmp(cmd, "/limera1n")) { char* filename = strtok(NULL, " "); debug("Sending limera1n payload %s\n", filename); if (filename != NULL) { irecv_send_file(client, filename, 0); } irecv_trigger_limera1n_exploit(client); } else if (!strcmp(cmd, "/execute")) { char* filename = strtok(NULL, " "); debug("Executing script %s\n", filename); if (filename != NULL) { char* buffer = NULL; uint64_t buffer_length = 0; buffer_read_from_filename(filename, &buffer, &buffer_length); if (buffer) { buffer[buffer_length] = '\0'; irecv_execute_script(client, buffer); free(buffer); } else { printf("Could not read file '%s'\n", filename); } } } free(action); }
static void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) { char* cmd = strdup((char*)command); char* action = strtok(cmd, " "); if (!strcmp(cmd, "/exit")) { quit = 1; } else if (!strcmp(cmd, "/help")) { shell_usage(); } else if (!strcmp(cmd, "/upload")) { char* filename = strtok(NULL, " "); debug("Uploading file %s\n", filename); if (filename != NULL) { irecv_send_file(client, filename, 0); } } else if (!strcmp(cmd, "/deviceinfo")) { int ret, mode; const struct irecv_device_info *devinfo = irecv_get_device_info(client); if (devinfo) { printf("CPID: %04x\n", devinfo->cpid); printf("CPRV: %02x\n", devinfo->cprv); printf("BDID: %02x\n", devinfo->bdid); printf("ECID: " _FMT_lld "\n", devinfo->ecid); printf("CPFM: %02x\n", devinfo->cpfm); printf("SCEP: %02x\n", devinfo->scep); printf("IBFL: %02x\n", devinfo->ibfl); printf("SRNM: %s\n", (devinfo->srnm) ? devinfo->srnm : "N/A"); printf("IMEI: %s\n", (devinfo->imei) ? devinfo->imei : "N/A"); } else { printf("Could not get device info?!\n"); } ret = irecv_get_mode(client, &mode); if (ret == IRECV_E_SUCCESS) { printf("MODE: %s\n", mode_to_str(mode)); } } else if (!strcmp(cmd, "/limera1n")) { char* filename = strtok(NULL, " "); debug("Sending limera1n payload %s\n", filename); if (filename != NULL) { irecv_send_file(client, filename, 0); } irecv_trigger_limera1n_exploit(client); } else if (!strcmp(cmd, "/execute")) { char* filename = strtok(NULL, " "); debug("Executing script %s\n", filename); if (filename != NULL) { char* buffer = NULL; uint64_t buffer_length = 0; buffer_read_from_filename(filename, &buffer, &buffer_length); if (buffer) { buffer[buffer_length] = '\0'; irecv_execute_script(client, buffer); free(buffer); } else { printf("Could not read file '%s'\n", filename); } } } else { printf("Unsupported command %s. Use /help to get a list of available commands.\n", cmd); } free(action); }