irecv_error_t mobiledevice_openpipes(irecv_client_t client) { if (client->iBootPath && !(client->hIB = CreateFile(client->iBootPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL))) { irecv_close(client); return IRECV_E_UNABLE_TO_CONNECT; } if (client->DfuPath && !(client->hDFU = CreateFile(client->DfuPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL))) { irecv_close(client); return IRECV_E_UNABLE_TO_CONNECT; } if (client->iBootPath == NULL) { client->mode = kDfuMode; client->handle = client->hDFU; } else { client->mode = kRecoveryMode2; client->handle = client->hIB; } return IRECV_E_SUCCESS; }
int recovery_send_applelogo(const char* ipsw, plist_t tss) { irecv_client_t recovery = NULL; const char* component = "applelogo"; irecv_error_t recovery_error = IRECV_E_SUCCESS; info("Sending %s...\n", component); if (recovery_open_with_timeout(&recovery) < 0) { return -1; } if (recovery_send_signed_component(recovery, ipsw, tss, "AppleLogo") < 0) { error("ERROR: Unable to send %s to device.\n", component); irecv_close(recovery); return -1; } recovery_error = irecv_send_command(recovery, "setpicture 1"); if (recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to set %s\n", component); irecv_close(recovery); return -1; } recovery_error = irecv_send_command(recovery, "bgcolor 0 0 0"); if (recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to display %s\n", component); irecv_close(recovery); return -1; } irecv_close(recovery); recovery = NULL; return 0; }
int recovery_send_kernelcache(const char* ipsw, plist_t tss) { irecv_client_t recovery = NULL; const char* component = "kernelcache"; irecv_error_t recovery_error = IRECV_E_SUCCESS; if (recovery_open_with_timeout(&recovery) < 0) { return -1; } if (recovery_send_signed_component(recovery, ipsw, tss, "RestoreKernelCache") < 0) { error("ERROR: Unable to send %s to device.\n", component); irecv_close(recovery); return -1; } recovery_error = irecv_send_command(recovery, "bootx"); if (recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to execute %s\n", component); irecv_close(recovery); return -1; } irecv_close(recovery); recovery = NULL; return 0; }
int normal_enter_recovery(struct idevicerestore_client_t* client) { idevice_t device = NULL; irecv_client_t recovery = NULL; lockdownd_client_t lockdown = NULL; irecv_error_t recovery_error = IRECV_E_SUCCESS; idevice_error_t device_error = IDEVICE_E_SUCCESS; lockdownd_error_t lockdown_error = LOCKDOWN_E_SUCCESS; device_error = idevice_new(&device, client->uuid); if (device_error != IDEVICE_E_SUCCESS) { error("ERROR: Unable to find device\n"); return -1; } lockdown_error = lockdownd_client_new(device, &lockdown, "idevicerestore"); if (lockdown_error != LOCKDOWN_E_SUCCESS) { error("ERROR: Unable to connect to lockdownd service\n"); idevice_free(device); return -1; } lockdown_error = lockdownd_enter_recovery(lockdown); if (lockdown_error != LOCKDOWN_E_SUCCESS) { error("ERROR: Unable to place device in recovery mode\n"); lockdownd_client_free(lockdown); idevice_free(device); return -1; } lockdownd_client_free(lockdown); idevice_free(device); lockdown = NULL; device = NULL; if (recovery_open_with_timeout(client) < 0) { error("ERROR: Unable to enter recovery mode\n"); return -1; } recovery_error = irecv_send_command(recovery, "setenv auto-boot true"); if (recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset auto-boot variable\n"); irecv_close(recovery); return -1; } recovery_error = irecv_send_command(recovery, "saveenv"); if (recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to save auto-boot variable\n"); irecv_close(recovery); return -1; } //client->mode = &idevicerestore_modes[MODE_RECOVERY]; irecv_close(recovery); recovery = NULL; 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 main(int argc, char *argv[]) { printf("iRecovery - Recovery Utility\n"); printf("by westbaer\nThanks to pod2g, tom3q, planetbeing, geohot and posixninja.\n\n"); if(argc < 2) { irecv_usage(); return -1; } struct usb_dev_handle* handle = irecv_init(RECV_MODE); if (handle == NULL) { handle = irecv_init(WTF_MODE); if (handle == NULL) { printf("No iPhone/iPod found.\n"); return -1; } else { printf("Found iPhone/iPod in DFU/WTF mode\n"); } } else { printf("Found iPhone/iPod in Recovery mode\n"); } if(!strcmp(argv[1], "-f")) { if(argc == 3) { irecv_upload(handle, argv[2]); } } else if(!strcmp(argv[1], "-c")) { if(argc >= 3) { irecv_command(handle, argc-2, &argv[2]); } } else if(!strcmp(argv[1], "-k")) { if(argc >= 3) { irecv_exploit(handle, argv[2]); } else { irecv_exploit(handle, NULL); } } else if(!strcmp(argv[1], "-s")) { if(argc >= 3) { irecv_console(handle, argv[2]); } else { irecv_console(handle, NULL); } } else if(!strcmp(argv[1], "-r")) { irecv_reset(handle); } else if (!strcmp(argv[1], "-l")) { irecv_list(handle, argv[2]); } else if (!strcmp(argv[1], "-x")) { if(argc == 3) { irecv_upload(handle, argv[2]); irecv_reset(handle); } } irecv_close(handle); return 0; }
/* * Class: Jsyringe * Method: wait_for_connect * Signature: (I)Ljava/lang/Boolean; */ JNIEXPORT jboolean JNICALL Java_Jsyringe_wait_1for_1connect (JNIEnv *env, jclass jClass) { jboolean jresult = JNI_FALSE; if (g_syringe_client != NULL) { irecv_close(&g_syringe_client); } if (0 == irecv_open(&g_syringe_client) && g_syringe_client->mode == kDfuMode) { if (irecv_get_device(g_syringe_client, &g_syringe_device) == IRECV_E_SUCCESS) { g_model = g_syringe_device->model; jresult = JNI_TRUE; } } cleanup: if (g_syringe_client != NULL) irecv_close(&g_syringe_client); return jresult; }
int recovery_check_mode() { irecv_client_t recovery = NULL; irecv_error_t recovery_error = IRECV_E_SUCCESS; recovery_error = irecv_open(&recovery); if (recovery_error != IRECV_E_SUCCESS) { return -1; } if (recovery->mode == kDfuMode) { irecv_close(recovery); return -1; } irecv_close(recovery); recovery = NULL; return 0; }
int recovery_get_bdid(uint32_t* bdid) { irecv_client_t recovery = NULL; irecv_error_t recovery_error = IRECV_E_SUCCESS; if (recovery_open_with_timeout(&recovery) < 0) { return -1; } recovery_error = irecv_get_bdid(recovery, bdid); if (recovery_error != IRECV_E_SUCCESS) { irecv_close(recovery); return -1; } irecv_close(recovery); recovery = NULL; return 0; }
void recovery_client_free(struct idevicerestore_client_t* client) { if(client) { if (client->recovery) { if(client->recovery->client) { irecv_close(client->recovery->client); client->recovery->client = NULL; } free(client->recovery); client->recovery = NULL; } } }
void dfu_client_free(struct idevicerestore_client_t* client) { if(client != NULL) { if (client->dfu != NULL) { if(client->dfu->client != NULL) { irecv_close(client->dfu->client); client->dfu->client = NULL; } free(client->dfu); } client->dfu = NULL; } }
int recovery_check_mode(struct idevicerestore_client_t* client) { irecv_client_t recovery = NULL; irecv_error_t recovery_error = IRECV_E_SUCCESS; irecv_init(); recovery_error=irecv_open(&recovery, client->ecid); if (recovery_error != IRECV_E_SUCCESS) { return -1; } if ((recovery->mode == kDfuMode) || (recovery->mode == kWTFMode)) { irecv_close(recovery); return -1; } irecv_close(recovery); recovery = NULL; return 0; }
int recovery_send_ibec(const char* ipsw, plist_t tss) { irecv_client_t recovery = NULL; const char* component = "iBEC"; irecv_error_t recovery_error = IRECV_E_SUCCESS; if (recovery_open_with_timeout(&recovery) < 0) { return -1; } recovery_error = irecv_send_command(recovery, "setenv auto-boot true"); if (recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to set auto-boot environmental variable\n"); irecv_close(recovery); return -1; } recovery_error = irecv_send_command(recovery, "saveenv"); if (recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to save environmental variable\n"); irecv_close(recovery); return -1; } if (recovery_send_signed_component(recovery, ipsw, tss, "iBEC") < 0) { error("ERROR: Unable to send %s to device.\n", component); irecv_close(recovery); return -1; } recovery_error = irecv_send_command(recovery, "go"); if (recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to execute %s\n", component); 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; irecv_init(); dfu_error=irecv_open(&dfu, client->ecid); if (dfu_error != IRECV_E_SUCCESS) { return -1; } if ((dfu->mode != kDfuMode) && (dfu->mode != kWTFMode)) { irecv_close(dfu); return -1; } *mode = (dfu->mode == kWTFMode) ? MODE_WTF : MODE_DFU; irecv_close(dfu); 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 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; }
irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause) { irecv_error_t error = 0; irecv_client_t new_client = NULL; irecv_event_cb_t progress_callback = client->progress_callback; #ifdef _WIN32 #ifdef _GUI_ENABLE_ char buffer[256]; #endif #endif if (check_context(client) == IRECV_E_SUCCESS) { irecv_close(client); } #ifdef _WIN32 #ifdef _GUI_ENABLE_ snprintf(buffer, 256, "Waiting %d seconds for the device...\n", initial_pause); SendMessage(hStatus3, WM_SETTEXT, 0, (LPARAM)buffer); InvalidateRect(window, NULL, TRUE); #endif #endif if (initial_pause > 0) { DPRINT("Waiting %d seconds for the device to pop up...\n", initial_pause); sleep(initial_pause); } #ifdef _WIN32 #ifdef _GUI_ENABLE_ SendMessage(hStatus3, WM_SETTEXT, 0, (LPARAM) TEXT(" ")); InvalidateRect(window, NULL, TRUE); #endif #endif error = irecv_open_attempts(&new_client, 10); if (error != IRECV_E_SUCCESS) { return NULL; } new_client->progress_callback = progress_callback; return new_client; }
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 dfu_send_buffer(struct idevicerestore_client_t* client, char* buffer, uint32_t size) { irecv_error_t error = 0; info("Sending data (%d bytes)...\n", size); error = irecv_send_buffer(client->dfu->client, buffer, size, 1); if (error != IRECV_E_SUCCESS) { error("ERROR: Unable to send data: %s\n", irecv_strerror(error)); return -1; } error = irecv_reset(client->dfu->client); if (error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset device\n"); irecv_close(client->dfu->client); return -1; } return 0; }
/* * Class: Jsyringe * Method: exploit * Signature: ()I */ JNIEXPORT jint JNICALL Java_Jsyringe_exploit (JNIEnv * env, jclass jClass) { int result = 0; irecv_error_t ir_error = IRECV_E_SUCCESS; irecv_client_t client = g_syringe_client; libpois0n_debug = 1; pois0n_init(); info("Waiting for device to enter DFU mode\n"); while(pois0n_is_ready()) { sleep(1); } info("Found device in DFU mode\n"); result = pois0n_is_compatible(); if (result < 0) { error("Your device in incompatible with this exploit!\n"); goto cleanup; } result = pois0n_injectonly(); if (result < 0) { error("Exploit injection failed!\n"); goto cleanup; } result = 0; cleanup: fflush(stderr); if (g_syringe_client) { irecv_close(&g_syringe_client); g_syringe_client = NULL; } //pois0n_exit(); return result; }
irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause) { irecv_error_t error = 0; irecv_client_t new_client = NULL; irecv_event_cb_t progress_callback = client->progress_callback; if (check_context(client) == IRECV_E_SUCCESS) { irecv_close(client); } if (initial_pause > 0) { debug("Waiting %d seconds for the device to pop up...\n", initial_pause); sleep(initial_pause); } error = irecv_open_attempts(&new_client, 10); if(error != IRECV_E_SUCCESS) { return NULL; } new_client->progress_callback = progress_callback; return new_client; }
void irecv_sendcmd(char *cmd) { int length; char *sendbuf; irecv_init(RECV_MODE); if(devPhone == 0) { printf("No iPhone/iPod found.\n"); exit(EXIT_FAILURE); } sendbuf = malloc(160); length = (int)(((strlen(cmd)-1)/0x10)+1)*0x10; memset(sendbuf, 0, length); memcpy(sendbuf, cmd, strlen(cmd)); if(!usb_control_msg(devPhone, 0x40, 0, 0, 0, sendbuf, length, 1000)) { printf("[!] %s", usb_strerror()); } free(sendbuf); irecv_close(devPhone); }
int pois0n_is_ready() { irecv_error_t error = IRECV_E_SUCCESS; ////////////////////////////////////// // Begin // debug("Connecting to device\n"); error = irecv_open(&client, device->chip_id); 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"); if (client->mode != kDfuMode) { error("Device must be in DFU mode to continue\n"); irecv_close(client); return -1; } return 0; }
int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity) { irecv_client_t dfu = NULL; const char* component = "iBSS"; irecv_error_t dfu_error = IRECV_E_SUCCESS; if (recovery_open_with_timeout(client) < 0 || dfu->mode != kDfuMode) { error("ERROR: Unable to connect to DFU device\n"); if (dfu) irecv_close(dfu); return -1; } if (recovery_send_component(client, build_identity, component) < 0) { error("ERROR: Unable to send %s to device\n", component); irecv_close(dfu); return -1; } dfu_error = irecv_reset(client->dfu->client); if (dfu_error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset device\n"); irecv_close(dfu); return -1; } irecv_close(client->dfu->client); client->dfu->client = NULL; // Reconnect to device, but this time make sure we're not still in DFU mode if (recovery_open_with_timeout(client) < 0 || client->mode->index != kDfuMode) { error("ERROR: Unable to connect to recovery device\n"); if (client->dfu->client) irecv_close(client->dfu->client); return -1; } client->mode = &idevicerestore_modes[MODE_RECOVERY]; irecv_close(client->dfu->client); client->dfu->client = NULL; return 0; }
irecv_error_t mobiledevice_connect(irecv_client_t* client) { irecv_error_t ret; SP_DEVICE_INTERFACE_DATA currentInterface; HDEVINFO usbDevices; DWORD i; LPSTR path; irecv_client_t _client = (irecv_client_t) malloc(sizeof(struct irecv_client)); memset(_client, 0, sizeof(struct irecv_client)); // Get DFU paths usbDevices = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DFU, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if(!usbDevices) { return IRECV_E_UNABLE_TO_CONNECT; } currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for(i = 0; SetupDiEnumDeviceInterfaces(usbDevices, NULL, &GUID_DEVINTERFACE_DFU, i, ¤tInterface); i++) { DWORD requiredSize = 0; PSP_DEVICE_INTERFACE_DETAIL_DATA details; SetupDiGetDeviceInterfaceDetail(usbDevices, ¤tInterface, NULL, 0, &requiredSize, NULL); details = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(requiredSize); details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if(!SetupDiGetDeviceInterfaceDetail(usbDevices, ¤tInterface, details, requiredSize, NULL, NULL)) { irecv_close(_client); free(details); SetupDiDestroyDeviceInfoList(usbDevices); return IRECV_E_UNABLE_TO_CONNECT; } else { LPSTR result = (LPSTR) malloc(requiredSize - sizeof(DWORD)); memcpy((void*) result, details->DevicePath, requiredSize - sizeof(DWORD)); free(details); path = (LPSTR) malloc(requiredSize - sizeof(DWORD)); memcpy((void*) path, (void*) result, requiredSize - sizeof(DWORD)); TCHAR* pathEnd = strstr(path, "#{"); *pathEnd = '\0'; _client->DfuPath = result; break; } } SetupDiDestroyDeviceInfoList(usbDevices); // Get iBoot path usbDevices = SetupDiGetClassDevs(&GUID_DEVINTERFACE_IBOOT, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if(!usbDevices) { irecv_close(_client); return IRECV_E_UNABLE_TO_CONNECT; } currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for(i = 0; SetupDiEnumDeviceInterfaces(usbDevices, NULL, &GUID_DEVINTERFACE_IBOOT, i, ¤tInterface); i++) { DWORD requiredSize = 0; PSP_DEVICE_INTERFACE_DETAIL_DATA details; SetupDiGetDeviceInterfaceDetail(usbDevices, ¤tInterface, NULL, 0, &requiredSize, NULL); details = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(requiredSize); details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if(!SetupDiGetDeviceInterfaceDetail(usbDevices, ¤tInterface, details, requiredSize, NULL, NULL)) { irecv_close(_client); free(details); SetupDiDestroyDeviceInfoList(usbDevices); return IRECV_E_UNABLE_TO_CONNECT; } else { LPSTR result = (LPSTR) malloc(requiredSize - sizeof(DWORD)); memcpy((void*) result, details->DevicePath, requiredSize - sizeof(DWORD)); free(details); if(strstr(result, path) == NULL) { free(result); continue; } _client->iBootPath = result; break; } } SetupDiDestroyDeviceInfoList(usbDevices); free(path); ret = mobiledevice_openpipes(_client); if (ret != IRECV_E_SUCCESS) return ret; *client = _client; return IRECV_E_SUCCESS; }
int main(int argc, char* argv[]) { int i = 0; int opt = 0; int action = 0; char* argument = NULL; irecv_error_t error = 0; if (argc == 1) print_usage(); while ((opt = getopt(argc, argv, "vhrsc:f:e:k::")) > 0) { switch (opt) { case 'v': verbose += 1; break; case 'h': print_usage(); 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(&client) != IRECV_E_SUCCESS) sleep(1); else break; if (i == 5) { return -1; } } 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_send_exploit(client); debug("%s\n", irecv_strerror(error)); break; case kStartShell: init_shell(client); break; case kSendScript: error = irecv_execute_script(client, argument); if(error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); } break; default: fprintf(stderr, "Unknown action\n"); break; } irecv_close(client); return 0; }
void pois0n_exit() { debug("Exiting libpois0n\n"); irecv_close(client); irecv_exit(); }
int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity) { irecv_error_t dfu_error = IRECV_E_SUCCESS; if (dfu_client_new(client) < 0) { error("ERROR: Unable to connect to DFU device\n"); return -1; } if (client->dfu->client->mode != kDfuMode) { 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); return -1; } 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); return -1; } if (client->build[0] > '8') { /* reconnect */ dfu_client_free(client); sleep(1); dfu_client_new(client); /* get nonce */ unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (dfu_get_nonce(client, &nonce, &nonce_size) < 0) { error("ERROR: Unable to get nonce 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_shsh_blobs(client, client->ecid, client->nonce, client->nonce_size, 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_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); return -1; } 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); 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 || client->recovery->client->mode == kDfuMode) { error("ERROR: Unable to connect to recovery device\n"); if (client->recovery->client) irecv_close(client->recovery->client); return -1; } return 0; }
void irecv_sendfile(char *filename) { FILE *file; int packets, len, last, i, a, c, sl; char *fbuf, buf[6]; if(!filename) return; file = fopen(filename, "rb"); if(file == NULL) { printf("File %s not found.\n", filename); exit(EXIT_FAILURE); } fseek(file, 0, 0); fclose(file); irecv_init(WTF_MODE); if(!devPhone) { devPhone = irecv_init(RECV_MODE); if(devPhone) { printf("Found iPhone/iPod in Recovery mode\n"); } } else { printf("Found iPhone/iPod in DFU/WTF mode\n"); } if(!devPhone) { printf("No iPhone/iPod found.\n"); exit(EXIT_FAILURE); } if(usb_set_configuration(devPhone, 1)) { printf("Error setting configuration\n"); } printf("\n"); file = fopen(filename, "rb"); fseek(file, 0, SEEK_END); len = ftell(file); fseek(file, 0, 0); packets = len / 0x800; if(len % 0x800) packets++; last = len % 0x800; printf("Loaded image file (len: 0x%x, packets: %d, last: 0x%x).\n", len, packets, last); fbuf = malloc(packets * 0x800); if(!last) { last = 0x800; } fread(fbuf, 1, len, file); fclose(file); printf("Sending 0x%x bytes\n", len); for(i=0, a=0, c=0; i<packets; i++, a+=0x800, c++) { sl = 0x800; if(i == packets-1) { sl = last; } printf("Sending 0x%x bytes in packet %d... ", sl, c); if(usb_control_msg(devPhone, 0x21, 1, c, 0, &fbuf[a], sl, 1000)) { printf(" OK\n"); } else{ printf(" x\n"); } if(usb_control_msg(devPhone, 0xA1, 3, 0, 0, buf, 6, 1000) != 6){ printf("Error receiving status!\n"); } else { irecv_hexdump(buf, 6); if(buf[4]!=5) { printf("Status error!\n"); } } } printf("Successfully uploaded file!\nExecuting it...\n"); usb_control_msg(devPhone, 0x21, 1, c, 0, fbuf, 0, 1000); for(i=6; i<=8; i++) { if(usb_control_msg(devPhone, 0xA1, 3, 0, 0, buf, 6, 1000) != 6){ printf("Error receiving status!\n"); } else { irecv_hexdump(buf, 6); if(buf[4]!=i) { printf("Status error!\n"); } } } free(fbuf); irecv_close(devPhone); }
int tethered_boot(const char *ibssFile, const char *ibecFile, const char *kernelcacheFile, const char *ramdiskFile, const char *devicetreeFile) { int result = 0; irecv_error_t ir_error = IRECV_E_SUCCESS; irecv_client_t client = g_syringe_client; libpois0n_debug = 1; pois0n_init(); info("Waiting for device to enter DFU mode\n"); while(pois0n_is_ready()) { sleep(1); } info("Found device in DFU mode\n"); result = pois0n_is_compatible(); if (result < 0) { error("Your device in incompatible with this exploit!\n"); goto cleanup; } result = pois0n_injectonly(); if (result < 0) { error("Exploit injection failed!\n"); goto cleanup; } client = g_syringe_client; if (ibssFile != NULL) { debug("Uploading %s to device, mode: 0x%x\n", ibssFile, client->mode); ir_error = irecv_send_file(client, ibssFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload iBSS\n"); debug("%s\n", irecv_strerror(ir_error)); result = -1; goto cleanup; } sleep(10); } else { error("ibss can't be null\n"); result = -1; goto cleanup; } if (ibecFile != NULL) { client = g_syringe_client = irecv_reconnect(client, 10); debug("Uploading iBEC %s to device, mode: 0x%x\n", ibecFile, client->mode); ir_error = irecv_send_file(client, ibecFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload iBEC\n"); debug("%s\n", irecv_strerror(ir_error)); result = -1; goto cleanup; } sleep(5); } client = g_syringe_client = irecv_reconnect(client, 10); if (ramdiskFile != NULL) { debug("Uploading ramdisk %s to device\n", ramdiskFile); ir_error = irecv_send_file(client, ramdiskFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload ramdisk\n"); debug("%s\n", irecv_strerror(ir_error)); result = -1; goto cleanup; } sleep(5); ir_error = irecv_send_command(client, "ramdisk"); if(ir_error != IRECV_E_SUCCESS) { error("Unable send the ramdisk command\n"); result = -1; goto cleanup; } } if (devicetreeFile != NULL) { debug("Uploading device tree %s to device\n", devicetreeFile); ir_error = irecv_send_file(client, devicetreeFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload device tree\n"); debug("%s\n", irecv_strerror(ir_error)); result = -1; goto cleanup; } ir_error = irecv_send_command(client, "devicetree"); if(ir_error != IRECV_E_SUCCESS) { error("Unable to send the devicetree command\n"); result = -1; goto cleanup; } } if (kernelcacheFile != NULL) { debug("Uploading kernel %s to device, mode: 0x%x\n", kernelcacheFile, client->mode); ir_error = irecv_send_file(client, kernelcacheFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload kernelcache\n"); debug("%s\n", irecv_strerror(ir_error)); result = -1; goto cleanup; } ir_error = irecv_send_command(client, "bootx"); if(ir_error != IRECV_E_SUCCESS) { error("Unable send the bootx command\n"); result = -1; goto cleanup; } } else { error("kernelcache can't be null\n"); result = -1; goto cleanup; } result = 0; cleanup: fflush(stderr); if (g_syringe_client) { irecv_close(&g_syringe_client); g_syringe_client = NULL; } //pois0n_exit(); return result; }