From b1ac92e52e8b82b44ff70fb4d56953d1ac9bbb5a Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Mon, 7 Oct 2019 13:53:19 +0200 Subject: DFU: Properly detect iBSS and iBEC execution (via device reconnect) Also prevent sending the iBEC twice which happened due to the changes in device detection logic. --- src/dfu.c | 46 ++++++++++++++++++++++++++++++++-------------- src/idevicerestore.c | 11 ++++------- 2 files changed, 36 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/dfu.c b/src/dfu.c index 8c65b93..f147cde 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -319,7 +319,8 @@ int dfu_get_sep_nonce(struct idevicerestore_client_t* client, unsigned char** no return 0; } -int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity) { +int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity) +{ int mode = 0; if (dfu_client_new(client) < 0) { @@ -345,7 +346,22 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide if (client->build_major > 8) { /* reconnect */ dfu_client_free(client); - sleep(2); + debug("Waiting for device to disconnect...\n"); + WAIT_FOR(client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (client->flags & FLAG_QUIT), 10); + if (client->mode != &idevicerestore_modes[MODE_UNKNOWN] || (client->flags & FLAG_QUIT)) { + if (!(client->flags & FLAG_QUIT)) { + error("ERROR: Device did not disconnect. Possibly invalid iBSS. Reset device and try again.\n"); + } + return -1; + } + debug("Waiting for device to reconnect in DFU mode...\n"); + WAIT_FOR(client->mode == &idevicerestore_modes[MODE_DFU] || (client->flags & FLAG_QUIT), 10); + if (client->mode != &idevicerestore_modes[MODE_DFU] || (client->flags & FLAG_QUIT)) { + if (!(client->flags & FLAG_QUIT)) { + error("ERROR: Device did not reconnect in DFU mode. Possibly invalid iBSS. Reset device and try again.\n"); + } + return -1; + } dfu_client_new(client); /* get nonce */ @@ -401,24 +417,26 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide 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; + debug("Waiting for device to disconnect...\n"); + WAIT_FOR(client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (client->flags & FLAG_QUIT), 10); + if (client->mode != &idevicerestore_modes[MODE_UNKNOWN] || (client->flags & FLAG_QUIT)) { + if (!(client->flags & FLAG_QUIT)) { + error("ERROR: Device did not disconnect. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS"); + } + return -1; + } + debug("Waiting for device to reconnect in recovery mode...\n"); + WAIT_FOR(client->mode == &idevicerestore_modes[MODE_RECOVERY] || (client->flags & FLAG_QUIT), 10); + if (client->mode != &idevicerestore_modes[MODE_RECOVERY] || (client->flags & FLAG_QUIT)) { + if (!(client->flags & FLAG_QUIT)) { + error("ERROR: Device did not reconnect in recovery mode. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS"); } return -1; } - irecv_get_mode(client->recovery->client, &mode); - - if (mode == IRECV_K_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); diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 6a9add0..80924af 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -1109,8 +1109,8 @@ int idevicerestore_start(struct idevicerestore_client_t* client) return -1; } - // if the device is in DFU mode, place device into recovery mode if (client->mode->index == MODE_DFU) { + // if the device is in DFU mode, place it into recovery mode dfu_client_free(client); recovery_client_free(client); if ((client->flags & FLAG_CUSTOM) && limera1n_is_supported(client->device)) { @@ -1133,7 +1133,7 @@ int idevicerestore_start(struct idevicerestore_client_t* client) info("exploited\n"); } if (dfu_enter_recovery(client, build_identity) < 0) { - error("ERROR: Unable to place device into recovery mode from %s mode\n", client->mode->string); + error("ERROR: Unable to place device into recovery mode from DFU mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); @@ -1141,11 +1141,8 @@ int idevicerestore_start(struct idevicerestore_client_t* client) unlink(filesystem); return -2; } - } - - if (client->mode->index == MODE_DFU) { - client->mode = &idevicerestore_modes[MODE_RECOVERY]; - } else { + } else if (client->mode->index == MODE_RECOVERY) { + // device is in recovery mode if ((client->build_major > 8) && !(client->flags & FLAG_CUSTOM)) { if (!client->image4supported) { /* send ApTicket */ -- cgit v1.1-32-gdbae