int boot_iboot() { irecv_error_t error = IRECV_E_SUCCESS; debug("Loading iBoot\n"); if (device->chip_id == 8720) { error = irecv_send_command(client, "go image load 0x69626F74 0x9000000"); } else { error = irecv_send_command(client, "go image load 0x69626F74 0x41000000"); } if (error != IRECV_E_SUCCESS) { error("Unable load iBoot to memory\n"); return -1; } debug("Shifting iBoot\n"); if (device->chip_id == 8720) { error = irecv_send_command(client, "go memory move 0x9000040 0x9000000 0x48000"); } else { error = irecv_send_command(client, "go memory move 0x41000040 0x41000000 0x48000"); } if (error != IRECV_E_SUCCESS) { error("Unable to move iBoot into memory\n"); return -1; } debug("Patching iBoot\n"); if (device->chip_id == 8720) { error = irecv_send_command(client, "go patch 0x9000000 0x48000"); } else { error = irecv_send_command(client, "go patch 0x41000000 0x48000"); } if (error != IRECV_E_SUCCESS) { error("Unable to patch iBoot\n"); return -1; } irecv_setenv(client, "auto-boot", "false"); irecv_saveenv(client); debug("Jumping into iBoot\n"); if (device->chip_id == 8720) { error = irecv_send_command(client, "go jump 0x9000000"); } else { error = irecv_send_command(client, "go jump 0x41000000"); } if (error != IRECV_E_SUCCESS) { error("Unable to jump into iBoot\n"); return -1; } debug("Reconnecting to device\n"); client = irecv_reconnect(client, 10); if (client == NULL) { error("Unable to boot the device tethered\n"); return -1; } irecv_setenv(client, "auto-boot", "true"); irecv_saveenv(client); if (upload_firmware_payload("iBoot") < 0) { error("Unable to boot the device tethered\n"); return -1; } debug("Initializing greenpois0n in iBoot\n"); irecv_send_command(client, "go"); return 0; }
int boot_ramdisk() { irecv_error_t error = IRECV_E_SUCCESS; // Add an exception for this since it's very different if(device->index == DEVICE_APPLETV2) { debug("Preparing to upload ramdisk\n"); if(upload_ramdisk() < 0) { error("Unable to upload ramdisk\n"); return -1; } debug("Executing ramdisk\n"); error = irecv_send_command(client, "ramdisk"); if(error != IRECV_E_SUCCESS) { error("Unable to execute ramdisk command\n"); return -1; } debug("Setting kernel bootargs\n"); error = irecv_send_command(client, "go kernel bootargs rd=md0 -v keepsyms=1"); if(error != IRECV_E_SUCCESS) { error("Unable to set kernel bootargs\n"); return -1; } debug("Preparing to upload kernelcache\n"); if(upload_kernelcache() < 0) { error("Unable to upload kernelcache\n"); return -1; } error = irecv_send_command(client, "bootx"); if(error != IRECV_E_SUCCESS) { error("Unable to move iBoot into memory\n"); return -1; } return 0; } debug("Preparing to boot iBoot\n"); if(boot_iboot() < 0) { error("Unable to boot iBoot\n"); return -1; } debug("Preparing to upload ramdisk\n"); if(upload_ramdisk() < 0) { error("Unable to upload ramdisk\n"); return -1; } debug("Executing ramdisk\n"); error = irecv_send_command(client, "go ramdisk 1 1"); if(error != IRECV_E_SUCCESS) { error("Unable to execute ramdisk command\n"); return -1; } debug("Moving ramdisk\n"); if(device->chip_id == 8720) { error = irecv_send_command(client, "go memory move 0x9000040 0xC000000 0x100000"); } else { error = irecv_send_command(client, "go memory move 0x41000040 0x44000000 0x100000"); } if(error != IRECV_E_SUCCESS) { error("Unable to move ramdisk\n"); return -1; } debug("Setting kernel bootargs\n"); error = irecv_send_command(client, "go kernel bootargs rd=md0 -v keepsyms=1"); if(error != IRECV_E_SUCCESS) { error("Unable to set kernel bootargs\n"); return -1; } irecv_setenv(client, "boot-args", "0"); irecv_setenv(client, "auto-boot", "true"); irecv_saveenv(client); error = irecv_send_command(client, "go fsboot"); if (error != IRECV_E_SUCCESS) { error("Unable to fsboot\n"); return -1; } return 0; }
int boot_tethered() { irecv_error_t error = IRECV_E_SUCCESS; debug("Initializing greenpois0n in iBoot\n"); irecv_send_command(client, "go"); // Add an exception for this since it's very different if (device->index == DEVICE_APPLETV2) { debug("Preparing to upload kernelcache\n"); if (upload_kernelcache() < 0) { error("Unable to upload kernelcache\n"); return -1; } debug("Hooking jump_to command\n"); error = irecv_send_command(client, "go rdboot"); if (error != IRECV_E_SUCCESS) { error("Unable to hook jump_to\n"); return -1; } debug("Booting kernel\n"); error = irecv_send_command(client, "bootx"); if (error != IRECV_E_SUCCESS) { error("Unable to boot kernel\n"); return -1; } return 0; } debug("Preparing to boot iBoot\n"); if (boot_iboot() < 0) { error("Unable to boot iBoot\n"); return -1; } debug("Preparing to upload ramdisk\n"); if (upload_ramdisk() < 0) { error("Unable to upload ramdisk\n"); return -1; } debug("Executing ramdisk\n"); error = irecv_send_command(client, "go ramdisk 1 1"); if (error != IRECV_E_SUCCESS) { error("Unable to execute ramdisk command\n"); return -1; } debug("Setting kernel bootargs\n"); error = irecv_send_command(client, "go kernel bootargs rd=disk0s1 -v keepsyms=1"); if (error != IRECV_E_SUCCESS) { error("Unable to set kernel bootargs\n"); return -1; } irecv_setenv(client, "boot-args", "0"); irecv_setenv(client, "auto-boot", "true"); irecv_saveenv(client); error = irecv_send_command(client, "go fsboot"); if (error != IRECV_E_SUCCESS) { error("Unable to fsboot\n"); 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; }