int main(int argc, char* argv[]) { idevice_t device = NULL; lockdownd_client_t lockdownd = NULL; afc_client_t afc = NULL; idevice_error_t device_error = IDEVICE_E_SUCCESS; lockdownd_error_t lockdownd_error = LOCKDOWN_E_SUCCESS; afc_error_t afc_error = AFC_E_SUCCESS; int i; const char* udid = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--extract")) { extract_raw_crash_reports = 1; continue; } else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keep")) { keep_crash_reports = 1; continue; } else if (target_directory == NULL) { target_directory = argv[i]; continue; } else { print_usage(argc, argv); return 0; } } /* ensure a target directory was supplied */ if (!target_directory) { print_usage(argc, argv); return 0; } /* check if target directory exists */ if (!file_exists(target_directory)) { fprintf(stderr, "ERROR: Directory '%s' does not exist.\n", target_directory); print_usage(argc, argv); return 0; } device_error = idevice_new(&device, udid); if (device_error != IDEVICE_E_SUCCESS) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } lockdownd_error = lockdownd_client_new_with_handshake(device, &lockdownd, "idevicecrashreport"); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", lockdownd_error); idevice_free(device); return -1; } /* start crash log mover service */ lockdownd_service_descriptor_t service = NULL; lockdownd_error = lockdownd_start_service(lockdownd, "com.apple.crashreportmover", &service); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } /* trigger move operation on device */ idevice_connection_t connection = NULL; device_error = idevice_connect(device, service->port, &connection); if(device_error != IDEVICE_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } /* read "ping" message which indicates the crash logs have been moved to a safe harbor */ char *ping = malloc(4); int attempts = 0; while ((strncmp(ping, "ping", 4) != 0) && (attempts > 10)) { uint32_t bytes = 0; device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); if ((bytes == 0) && (device_error == IDEVICE_E_SUCCESS)) { attempts++; continue; } else if (device_error < 0) { fprintf(stderr, "ERROR: Crash logs could not be moved. Connection interrupted.\n"); break; } } idevice_disconnect(connection); free(ping); if (service) { lockdownd_service_descriptor_free(service); service = NULL; } if (device_error != IDEVICE_E_SUCCESS || attempts > 10) { fprintf(stderr, "ERROR: Failed to receive ping message from crash report mover.\n"); lockdownd_client_free(lockdownd); idevice_free(device); return -1; } lockdownd_error = lockdownd_start_service(lockdownd, "com.apple.crashreportcopymobile", &service); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } lockdownd_client_free(lockdownd); afc = NULL; afc_error = afc_client_new(device, service, &afc); if(afc_error != AFC_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } /* recursively copy crash reports from the device to a local directory */ if (afc_client_copy_and_remove_crash_reports(afc, ".", target_directory) < 0) { fprintf(stderr, "ERROR: Failed to get crash reports from device.\n"); afc_client_free(afc); idevice_free(device); return -1; } printf("Done.\n"); afc_client_free(afc); idevice_free(device); return 0; }
int main(int argc, char *argv[]) { int i; signal(SIGINT, clean_exit); signal(SIGTERM, clean_exit); #ifndef WIN32 signal(SIGQUIT, clean_exit); signal(SIGPIPE, SIG_IGN); #endif /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = _strdup(argv[i]); continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } int num = 0; char **devices = NULL; idevice_get_device_list(&devices, &num); idevice_device_list_free(devices); if (num == 0) { if (!udid) { fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n"); return -1; } else { fprintf(stderr, "Waiting for device with UDID %s to become available...\n", udid); } } idevice_event_subscribe(device_event_cb, NULL); while (!quit_flag) { sleep(1); } idevice_event_unsubscribe(); stop_logging(); if (udid) { free(udid); } return 0; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; idevice_t phone = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; char udid[41]; time_t setdate = 0; plist_t node = NULL; udid[0] = 0; uint64_t datetime = 0; time_t rawtime; struct tm * tmp; char const *format = NULL; char buffer[80]; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } strcpy(udid, argv[i]); continue; } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--set")) { i++; if (!argv[i] || (strlen(argv[i]) <= 1)) { print_usage(argc, argv); return 0; } setdate = atoi(argv[i]); if (setdate == 0) { printf("ERROR: Invalid timestamp value.\n"); print_usage(argc, argv); return 0; } continue; } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--sync")) { i++; /* get current time */ setdate = time(NULL); /* convert it to local time which sets timezone/daylight variables */ tmp = localtime(&setdate); /* recalculate to make it UTC */ setdate = mktime(tmp); continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } /* determine a date format */ if (!format) { format = DATE_FMT_LANGINFO (); if (!*format) { format = "%a %b %e %H:%M:%S %Z %Y"; } } if (udid[0] != 0) { ret = idevice_new(&phone, udid); if (ret != IDEVICE_E_SUCCESS) { printf("No device found with udid %s, is it plugged in?\n", udid); return -1; } } else { ret = idevice_new(&phone, NULL); if (ret != IDEVICE_E_SUCCESS) { printf("No device found, is it plugged in?\n"); return -1; } } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "idevicedate")) { idevice_free(phone); return -1; } /* get or set? */ if (setdate == 0) { /* get time value from device */ if(lockdownd_get_value(client, NULL, "TimeIntervalSince1970", &node) == LOCKDOWN_E_SUCCESS) { if (node) { plist_get_uint_val(node, &datetime); plist_free(node); node = NULL; /* date/time calculations */ rawtime = (time_t)datetime; tmp = localtime(&rawtime); /* finally we format and print the current date */ strftime(buffer, 80, format, tmp); puts(buffer); } } } else { datetime = setdate; if(lockdownd_set_value(client, NULL, "TimeIntervalSince1970", plist_new_uint(datetime)) == LOCKDOWN_E_SUCCESS) { tmp = localtime(&setdate); strftime(buffer, 80, format, tmp); puts(buffer); } else { printf("ERROR: Failed to set date on device.\n"); } } lockdownd_client_free(client); idevice_free(phone); return 0; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR; lockdownd_service_descriptor_t service = NULL; idevice_t device = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; int op = -1; int output_xml = 0; const char* udid = NULL; const char* param = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "install")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_INSTALL; continue; } else if (!strcmp(argv[i], "list")) { op = OP_LIST; } else if (!strcmp(argv[i], "copy")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_COPY; continue; } else if (!strcmp(argv[i], "remove")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_REMOVE; continue; } else if (!strcmp(argv[i], "dump")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_DUMP; continue; } else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--xml")) { output_xml = 1; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } if ((op == -1) || (op >= NUM_OPS)) { print_usage(argc, argv); return 0; } if (op == OP_DUMP) { int res = 0; unsigned char* profile_data = NULL; unsigned int profile_size = 0; if (profile_read_from_file(param, &profile_data, &profile_size) != 0) { return -1; } plist_t pdata = plist_new_data((char*)profile_data, profile_size); plist_t pl = profile_get_embedded_plist(pdata); plist_free(pdata); free(profile_data); if (pl) { if (output_xml) { char* xml = NULL; uint32_t xlen = 0; plist_to_xml(pl, &xml, &xlen); if (xml) { printf("%s\n", xml); free(xml); } } else { if (pl && (plist_get_node_type(pl) == PLIST_DICT)) { plist_print_to_stream(pl, stdout); } else { fprintf(stderr, "ERROR: unexpected node type in profile plist (not PLIST_DICT)\n"); res = -1; } } } else { fprintf(stderr, "ERROR: could not extract embedded plist from profile!\n"); } plist_free(pl); return res; } ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, "ideviceprovision"))) { fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ldret); idevice_free(device); return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_start_service(client, "com.apple.misagent", &service)) { fprintf(stderr, "Could not start service \"com.apple.misagent\"\n"); lockdownd_client_free(client); idevice_free(device); return -1; } lockdownd_client_free(client); client = NULL; misagent_client_t mis = NULL; if (misagent_client_new(device, service, &mis) != MISAGENT_E_SUCCESS) { fprintf(stderr, "Could not connect to \"com.apple.misagent\" on device\n"); if (service) lockdownd_service_descriptor_free(service); lockdownd_client_free(client); idevice_free(device); return -1; } if (service) lockdownd_service_descriptor_free(service); switch (op) { case OP_INSTALL: { unsigned char* profile_data = NULL; unsigned int profile_size = 0; if (profile_read_from_file(param, &profile_data, &profile_size) != 0) { break; } uint64_t psize = profile_size; plist_t pdata = plist_new_data((const char*)profile_data, psize); free(profile_data); if (misagent_install(mis, pdata) == MISAGENT_E_SUCCESS) { printf("Profile '%s' installed successfully.\n", param); } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not install profile '%s', status code: 0x%x\n", param, sc); } } break; case OP_LIST: case OP_COPY: { plist_t profiles = NULL; if (misagent_copy(mis, &profiles) == MISAGENT_E_SUCCESS) { uint32_t num_profiles = plist_array_get_size(profiles); printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); uint32_t j; for (j = 0; j < num_profiles; j++) { char* p_name = NULL; char* p_uuid = NULL; plist_t profile = plist_array_get_item(profiles, j); plist_t pl = profile_get_embedded_plist(profile); if (pl && (plist_get_node_type(pl) == PLIST_DICT)) { plist_t node; node = plist_dict_get_item(pl, "Name"); if (node && (plist_get_node_type(node) == PLIST_STRING)) { plist_get_string_val(node, &p_name); } node = plist_dict_get_item(pl, "UUID"); if (node && (plist_get_node_type(node) == PLIST_STRING)) { plist_get_string_val(node, &p_uuid); } } printf("%s - %s\n", (p_uuid) ? p_uuid : "(unknown id)", (p_name) ? p_name : "(no name)"); if (op == OP_COPY) { char pfname[512]; if (p_uuid) { sprintf(pfname, "%s/%s.mobileprovision", param, p_uuid); } else { sprintf(pfname, "%s/profile%d.mobileprovision", param, j); } FILE* f = fopen(pfname, "wb"); if (f) { char* dt = NULL; uint64_t ds = 0; plist_get_data_val(profile, &dt, &ds); fwrite(dt, 1, ds, f); fclose(f); printf(" => %s\n", pfname); } else { fprintf(stderr, "Could not open '%s' for writing\n", pfname); } } if (p_uuid) { free(p_uuid); } if (p_name) { free(p_name); } } } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); } } break; case OP_REMOVE: if (misagent_remove(mis, param) == MISAGENT_E_SUCCESS) { printf("Profile '%s' removed.\n", param); } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not remove profile '%s', status code 0x%x\n", param, sc); } break; default: break; } misagent_client_free(mis); idevice_free(device); return 0; }
int main(int argc, char* argv[]) { int opt = 0; int optindex = 0; char* ipsw = NULL; char* uuid = NULL; int tss_enabled = 0; int shsh_only = 0; char* shsh_dir = NULL; use_apple_server=1; // create an instance of our context struct idevicerestore_client_t* client = (struct idevicerestore_client_t*) malloc(sizeof(struct idevicerestore_client_t)); if (client == NULL) { error("ERROR: Out of memory\n"); return -1; } memset(client, '\0', sizeof(struct idevicerestore_client_t)); while ((opt = getopt_long(argc, argv, "dhcesxtpi:u:", longopts, &optindex)) > 0) { switch (opt) { case 'h': usage(argc, argv); return 0; case 'd': client->flags |= FLAG_DEBUG; idevicerestore_debug = 1; break; case 'e': client->flags |= FLAG_ERASE; break; case 'c': client->flags |= FLAG_CUSTOM; break; case 's': use_apple_server=0; break; case 'x': client->flags |= FLAG_EXCLUDE; break; case 'i': if (optarg) { char* tail = NULL; client->ecid = strtoull(optarg, &tail, 16); if (tail && (tail[0] != '\0')) { client->ecid = 0; } if (client->ecid == 0) { error("ERROR: Could not parse ECID from '%s'\n", optarg); return -1; } } break; case 'u': uuid = optarg; break; case 't': shsh_only = 1; break; case 'p': client->flags |= FLAG_PWN; break; default: usage(argc, argv); return -1; } } if (((argc-optind) == 1) || (client->flags & FLAG_PWN)) { argc -= optind; argv += optind; ipsw = argv[0]; } else { usage(argc, argv); return -1; } if (client->flags & FLAG_DEBUG) { idevice_set_debug_level(1); irecv_set_debug_level(1); } client->uuid = uuid; client->ipsw = ipsw; // update version data (from cache, or apple if too old) load_version_data(client); // check which mode the device is currently in so we know where to start if (check_mode(client) < 0 || client->mode->index == MODE_UNKNOWN) { error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n"); return -1; } info("Found device in %s mode\n", client->mode->string); if (client->mode->index == MODE_WTF) { int cpid = 0; if (dfu_client_new(client) != 0) { error("ERROR: Could not open device in WTF mode\n"); return -1; } if ((dfu_get_cpid(client, &cpid) < 0) || (cpid == 0)) { error("ERROR: Could not get CPID for WTF mode device\n"); dfu_client_free(client); return -1; } char* s_wtfurl = NULL; plist_t wtfurl = plist_access_path(client->version_data, 7, "MobileDeviceSoftwareVersionsByVersion", "5", "RecoverySoftwareVersions", "WTF", "304218112", "5", "FirmwareURL"); if (wtfurl && (plist_get_node_type(wtfurl) == PLIST_STRING)) { plist_get_string_val(wtfurl, &s_wtfurl); } if (!s_wtfurl) { info("Using hardcoded x12220000_5_Recovery.ipsw URL\n"); s_wtfurl = strdup("http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPhone/061-6618.20090617.Xse7Y/x12220000_5_Recovery.ipsw"); } // make a local file name char* fnpart = strrchr(s_wtfurl, '/'); if (!fnpart) { fnpart = "x12220000_5_Recovery.ipsw"; } else { fnpart++; } struct stat fst; char wtfipsw[256]; sprintf(wtfipsw, "cache/%s", fnpart); if (stat(wtfipsw, &fst) != 0) { __mkdir("cache", 0755); download_to_file(s_wtfurl, wtfipsw); } char wtfname[256]; sprintf(wtfname, "Firmware/dfu/WTF.s5l%04xxall.RELEASE.dfu", cpid); char* wtftmp = NULL; uint32_t wtfsize = 0; ipsw_extract_to_memory(wtfipsw, wtfname, &wtftmp, &wtfsize); if (!wtftmp) { error("ERROR: Could not extract WTF\n"); } else { if (dfu_send_buffer(client, wtftmp, wtfsize) != 0) { error("ERROR: Could not send WTF...\n"); } } dfu_client_free(client); sleep(1); free(wtftmp); client->mode = &idevicerestore_modes[MODE_DFU]; } // discover the device type if (check_device(client) < 0 || client->device->index == DEVICE_UNKNOWN) { error("ERROR: Unable to discover device type\n"); return -1; } info("Identified device as %s\n", client->device->product); if ((client->flags & FLAG_PWN) && (client->mode->index != MODE_DFU)) { error("ERROR: you need to put your device into DFU mode to pwn it.\n"); return -1; } if (client->flags & FLAG_PWN) { recovery_client_free(client); info("connecting to DFU\n"); if (dfu_client_new(client) < 0) { return -1; } info("exploiting with limera1n...\n"); // TODO: check for non-limera1n device and fail if (limera1n_exploit(client->device, client->dfu->client) != 0) { error("ERROR: limera1n exploit failed\n"); dfu_client_free(client); return -1; } dfu_client_free(client); info("Device should be in pwned DFU state now.\n"); return 0; } if (client->mode->index == MODE_RESTORE) { if (restore_reboot(client) < 0) { error("ERROR: Unable to exit restore mode\n"); return -1; } } // extract buildmanifest plist_t buildmanifest = NULL; if (client->flags & FLAG_CUSTOM) { info("Extracting Restore.plist from IPSW\n"); if (ipsw_extract_restore_plist(ipsw, &buildmanifest) < 0) { error("ERROR: Unable to extract Restore.plist from %s\n", ipsw); return -1; } } else { info("Extracting BuildManifest from IPSW\n"); if (ipsw_extract_build_manifest(ipsw, &buildmanifest, &tss_enabled) < 0) { error("ERROR: Unable to extract BuildManifest from %s\n", ipsw); return -1; } } /* check if device type is supported by the given build manifest */ if (build_manifest_check_compatibility(buildmanifest, client->device->product) < 0) { error("ERROR: could not make sure this firmware is suitable for the current device. refusing to continue.\n"); return -1; } /* print iOS information from the manifest */ build_manifest_get_version_information(buildmanifest, &client->version, &client->build); info("Product Version: %s\n", client->version); info("Product Build: %s\n", client->build); if (client->flags & FLAG_CUSTOM) { /* prevent signing custom firmware */ tss_enabled = 0; info("Custom firmware requested. Disabled TSS request.\n"); } // choose whether this is an upgrade or a restore (default to upgrade) client->tss = NULL; plist_t build_identity = NULL; if (client->flags & FLAG_CUSTOM) { build_identity = plist_new_dict(); { plist_t node; plist_t comp; plist_t info; plist_t manifest; info = plist_new_dict(); plist_dict_insert_item(info, "RestoreBehavior", plist_new_string((client->flags & FLAG_ERASE) ? "Erase" : "Update")); plist_dict_insert_item(info, "Variant", plist_new_string((client->flags & FLAG_ERASE) ? "Customer Erase Install (IPSW)" : "Customer Upgrade Install (IPSW)")); plist_dict_insert_item(build_identity, "Info", info); manifest = plist_new_dict(); char tmpstr[256]; char p_all_flash[128]; char lcmodel[8]; strcpy(lcmodel, client->device->model); int x = 0; while (lcmodel[x]) { lcmodel[x] = tolower(lcmodel[x]); x++; } sprintf(p_all_flash, "Firmware/all_flash/all_flash.%s.%s", lcmodel, "production"); strcpy(tmpstr, p_all_flash); strcat(tmpstr, "/manifest"); // get all_flash file manifest char *files[16]; char *fmanifest = NULL; uint32_t msize = 0; if (ipsw_extract_to_memory(ipsw, tmpstr, &fmanifest, &msize) < 0) { error("ERROR: could not extract %s from IPSW\n", tmpstr); return -1; } char *tok = strtok(fmanifest, "\r\n"); int fc = 0; while (tok) { files[fc++] = strdup(tok); if (fc >= 16) { break; } tok = strtok(NULL, "\r\n"); } free(fmanifest); for (x = 0; x < fc; x++) { info = plist_new_dict(); strcpy(tmpstr, p_all_flash); strcat(tmpstr, "/"); strcat(tmpstr, files[x]); plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); const char* compname = get_component_name(files[x]); if (compname) { plist_dict_insert_item(manifest, compname, comp); if (!strncmp(files[x], "DeviceTree", 10)) { plist_dict_insert_item(manifest, "RestoreDeviceTree", plist_copy(comp)); } } else { error("WARNING: unhandled component %s\n", files[x]); plist_free(comp); } free(files[x]); files[x] = NULL; } // add iBSS sprintf(tmpstr, "Firmware/dfu/iBSS.%s.%s.dfu", lcmodel, "RELEASE"); info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "iBSS", comp); // add iBEC sprintf(tmpstr, "Firmware/dfu/iBEC.%s.%s.dfu", lcmodel, "RELEASE"); info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "iBEC", comp); // add kernel cache node = plist_dict_get_item(buildmanifest, "KernelCachesByTarget"); if (node && (plist_get_node_type(node) == PLIST_DICT)) { char tt[4]; strncpy(tt, lcmodel, 3); tt[3] = 0; plist_t kdict = plist_dict_get_item(node, tt); if (kdict && (plist_get_node_type(kdict) == PLIST_DICT)) { plist_t kc = plist_dict_get_item(kdict, "Release"); if (kc && (plist_get_node_type(kc) == PLIST_STRING)) { info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_copy(kc)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "KernelCache", comp); plist_dict_insert_item(manifest, "RestoreKernelCache", plist_copy(comp)); } } } // add ramdisk node = plist_dict_get_item(buildmanifest, "RestoreRamDisks"); if (node && (plist_get_node_type(node) == PLIST_DICT)) { plist_t rd = plist_dict_get_item(node, (client->flags & FLAG_ERASE) ? "User" : "Update"); if (rd && (plist_get_node_type(rd) == PLIST_STRING)) { info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_copy(rd)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "RestoreRamDisk", comp); } } // add OS filesystem node = plist_dict_get_item(buildmanifest, "SystemRestoreImages"); if (!node) { error("ERROR: missing SystemRestoreImages in Restore.plist\n"); } plist_t os = plist_dict_get_item(node, "User"); if (!os) { error("ERROR: missing filesystem in Restore.plist\n"); } else { info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_copy(os)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "OS", comp); } // finally add manifest plist_dict_insert_item(build_identity, "Manifest", manifest); } } else if (client->flags & FLAG_ERASE) { build_identity = build_manifest_get_build_identity(buildmanifest, 0); if (build_identity == NULL) { error("ERROR: Unable to find any build identities\n"); plist_free(buildmanifest); return -1; } } else { // loop through all build identities in the build manifest // and list the valid ones int i = 0; int valid_builds = 0; int build_count = build_manifest_get_identity_count(buildmanifest); for (i = 0; i < build_count; i++) { build_identity = build_manifest_get_build_identity(buildmanifest, i); valid_builds++; } } /* print information about current build identity */ build_identity_print_information(build_identity); /* retrieve shsh blobs if required */ if (tss_enabled) { debug("Getting device's ECID for TSS request\n"); /* fetch the device's ECID for the TSS request */ if (get_ecid(client, &client->ecid) < 0) { error("ERROR: Unable to find device ECID\n"); return -1; } info("Found ECID " FMT_qu "\n", (long long unsigned int)client->ecid); if (get_shsh_blobs(client, client->ecid, NULL, 0, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } } if (shsh_only) { if (!tss_enabled) { info("This device does not require a TSS record"); return 0; } if (!client->tss) { error("ERROR: could not fetch TSS record"); plist_free(buildmanifest); return -1; } else { char *bin = NULL; uint32_t blen = 0; plist_to_bin(client->tss, &bin, &blen); if (bin) { char zfn[512]; sprintf(zfn, "shsh/" FMT_qu "-%s-%s.shsh", (long long int)client->ecid, client->device->product, client->version); __mkdir("shsh", 0755); struct stat fst; if (stat(zfn, &fst) != 0) { gzFile zf = gzopen(zfn, "wb"); gzwrite(zf, bin, blen); gzclose(zf); info("SHSH saved to '%s'\n", zfn); } else { info("SHSH '%s' already present.\n", zfn); } free(bin); } else { error("ERROR: could not get TSS record data\n"); } plist_free(client->tss); plist_free(buildmanifest); return 0; } } /* verify if we have tss records if required */ if ((tss_enabled) && (client->tss == NULL)) { error("ERROR: Unable to proceed without a TSS record.\n"); plist_free(buildmanifest); return -1; } if ((tss_enabled) && client->tss) { /* fix empty dicts */ fixup_tss(client->tss); } // Extract filesystem from IPSW and return its name char* filesystem = NULL; if (ipsw_extract_filesystem(client->ipsw, build_identity, &filesystem) < 0) { error("ERROR: Unable to extract filesystem from IPSW\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } // if the device is in normal mode, place device into recovery mode if (client->mode->index == MODE_NORMAL) { info("Entering recovery mode...\n"); if (normal_enter_recovery(client) < 0) { error("ERROR: Unable to place device into recovery mode\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } } // if the device is in DFU mode, place device into recovery mode if (client->mode->index == MODE_DFU) { recovery_client_free(client); if (client->flags & FLAG_CUSTOM) { info("connecting to DFU\n"); if (dfu_client_new(client) < 0) { return -1; } info("exploiting with limera1n\n"); // TODO: check for non-limera1n device and fail if (limera1n_exploit(client->device, client->dfu->client) != 0) { error("ERROR: limera1n exploit failed\n"); dfu_client_free(client); return -1; } dfu_client_free(client); info("exploited\n"); } if (dfu_enter_recovery(client, build_identity) < 0) { error("ERROR: Unable to place device into recovery mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); return -1; } } if (client->mode->index == MODE_DFU) { client->mode = &idevicerestore_modes[MODE_RECOVERY]; } else { /* now we load the iBEC */ if (recovery_send_ibec(client, build_identity) < 0) { error("ERROR: Unable to send iBEC\n"); return -1; } recovery_client_free(client); /* this must be long enough to allow the device to run the iBEC */ /* FIXME: Probably better to detect if the device is back then */ sleep(7); } if (client->build[0] > '8') { // we need another tss request with nonce. unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (get_nonce(client, &nonce, &nonce_size) < 0) { error("ERROR: Unable to get nonce from device!\n"); recovery_send_reset(client); 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); } } // now finally do the magic to put the device into restore mode if (client->mode->index == MODE_RECOVERY) { if (client->srnm == NULL) { error("ERROR: could not retrieve device serial number. Can't continue.\n"); return -1; } if (recovery_enter_restore(client, build_identity) < 0) { error("ERROR: Unable to place device into restore mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); return -1; } } // device is finally in restore mode, let's do this if (client->mode->index == MODE_RESTORE) { info("About to restore device... \n"); if (restore_device(client, build_identity, filesystem) < 0) { error("ERROR: Unable to restore device\n"); return -1; } } info("Cleaning up...\n"); if (filesystem) unlink(filesystem); info("DONE\n"); return 0; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR; idevice_t device = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; const char* udid = NULL; time_t setdate = 0; plist_t node = NULL; int node_type = -1; uint64_t datetime = 0; time_t rawtime; struct tm * tmp; char const *format = NULL; char buffer[80]; int result = 0; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--set")) { i++; if (!argv[i] || (strlen(argv[i]) <= 1)) { print_usage(argc, argv); return 0; } setdate = atoi(argv[i]); if (setdate == 0) { printf("ERROR: Invalid timestamp value.\n"); print_usage(argc, argv); return 0; } continue; } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--sync")) { i++; /* get current time */ setdate = time(NULL); /* convert it to local time which sets timezone/daylight variables */ tmp = localtime(&setdate); /* recalculate to make it UTC */ setdate = mktime(tmp); continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } /* determine a date format */ if (!format) { format = DATE_FMT_LANGINFO (); if (!*format) { format = "%a %b %e %H:%M:%S %Z %Y"; } } ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, "idevicedate"))) { fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ldret); result = -1; goto cleanup; } if(lockdownd_get_value(client, NULL, "TimeIntervalSince1970", &node) != LOCKDOWN_E_SUCCESS) { fprintf(stderr, "ERROR: Unable to retrieve 'TimeIntervalSince1970' node from device.\n"); result = -1; goto cleanup; } if (node == NULL) { fprintf(stderr, "ERROR: Empty node for 'TimeIntervalSince1970' received.\n"); result = -1; goto cleanup; } node_type = plist_get_node_type(node); /* get or set? */ if (setdate == 0) { /* get time value from device */ switch (node_type) { case PLIST_UINT: plist_get_uint_val(node, &datetime); break; case PLIST_REAL: { double rv = 0; plist_get_real_val(node, &rv); datetime = rv; } break; default: fprintf(stderr, "ERROR: Unexpected node type for 'TimeIntervalSince1970'\n"); break; } plist_free(node); node = NULL; /* date/time calculations */ rawtime = (time_t)datetime; tmp = localtime(&rawtime); /* finally we format and print the current date */ strftime(buffer, 80, format, tmp); puts(buffer); } else { datetime = setdate; plist_free(node); node = NULL; switch (node_type) { case PLIST_UINT: node = plist_new_uint(datetime); break; case PLIST_REAL: node = plist_new_real((double)datetime); break; default: fprintf(stderr, "ERROR: Unexpected node type for 'TimeIntervalSince1970'\n"); break; } if(lockdownd_set_value(client, NULL, "TimeIntervalSince1970", node) == LOCKDOWN_E_SUCCESS) { tmp = localtime(&setdate); strftime(buffer, 80, format, tmp); puts(buffer); } else { printf("ERROR: Failed to set date on device.\n"); } node = NULL; } cleanup: if (client) lockdownd_client_free(client); if (device) idevice_free(device); return result; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; idevice_t phone = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; int simple = 0; int format = FORMAT_KEY_VALUE; char uuid[41]; char *domain = NULL; char *key = NULL; char *xml_doc = NULL; uint32_t xml_length; plist_t node = NULL; plist_type node_type; uuid[0] = 0; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uuid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } strcpy(uuid, argv[i]); continue; } else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--domain")) { i++; if (!argv[i] || (strlen(argv[i]) < 4)) { print_usage(argc, argv); return 0; } if (!is_domain_known(argv[i])) { fprintf(stderr, "WARNING: Sending query with unknown domain \"%s\".\n", argv[i]); } domain = strdup(argv[i]); continue; } else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--key")) { i++; if (!argv[i] || (strlen(argv[i]) <= 1)) { print_usage(argc, argv); return 0; } key = strdup(argv[i]); continue; } else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--xml")) { format = FORMAT_XML; continue; } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--simple")) { simple = 1; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } if (uuid[0] != 0) { ret = idevice_new(&phone, uuid); if (ret != IDEVICE_E_SUCCESS) { printf("No device found with uuid %s, is it plugged in?\n", uuid); return -1; } } else { ret = idevice_new(&phone, NULL); if (ret != IDEVICE_E_SUCCESS) { printf("No device found, is it plugged in?\n"); return -1; } } if (LOCKDOWN_E_SUCCESS != (simple ? lockdownd_client_new(phone, &client, "ideviceinfo"): lockdownd_client_new_with_handshake(phone, &client, "ideviceinfo"))) { idevice_free(phone); return -1; } /* run query and output information */ if(lockdownd_get_value(client, domain, key, &node) == LOCKDOWN_E_SUCCESS) { if (node) { switch (format) { case FORMAT_XML: plist_to_xml(node, &xml_doc, &xml_length); printf("%s", xml_doc); free(xml_doc); break; case FORMAT_KEY_VALUE: node_type = plist_get_node_type(node); if (node_type == PLIST_DICT) { plist_dict_to_string(node); } else if (node_type == PLIST_ARRAY) { plist_array_to_string(node); break; } default: if (key != NULL) plist_node_to_string(node); break; } plist_free(node); node = NULL; } } if (domain != NULL) free(domain); lockdownd_client_free(client); idevice_free(phone); return 0; }
int main(int argc, char **argv) { idevice_t device = NULL; lockdownd_client_t lockdown_client = NULL; diagnostics_relay_client_t diagnostics_client = NULL; lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; lockdownd_service_descriptor_t service = NULL; int result = -1; int i; const char *udid = NULL; int cmd = CMD_NONE; char* cmd_arg = NULL; plist_t node = NULL; plist_t keys = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); result = 0; goto cleanup; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); result = 0; goto cleanup; } else if (!strcmp(argv[i], "sleep")) { cmd = CMD_SLEEP; } else if (!strcmp(argv[i], "restart")) { cmd = CMD_RESTART; } else if (!strcmp(argv[i], "shutdown")) { cmd = CMD_SHUTDOWN; } else if (!strcmp(argv[i], "diagnostics")) { cmd = CMD_DIAGNOSTICS; /* read type */ i++; if (!argv[i] || ((strcmp(argv[i], "All") != 0) && (strcmp(argv[i], "WiFi") != 0) && (strcmp(argv[i], "GasGauge") != 0) && (strcmp(argv[i], "NAND") != 0))) { if (argv[i] == NULL) { cmd_arg = strdup("All"); continue; } if (!strncmp(argv[i], "-", 1)) { cmd_arg = strdup("All"); i--; continue; } printf("Unknown TYPE %s\n", argv[i]); print_usage(argc, argv); goto cleanup; } cmd_arg = strdup(argv[i]); continue; } else if (!strcmp(argv[i], "mobilegestalt")) { cmd = CMD_MOBILEGESTALT; /* read keys */ i++; if (!argv[i] || argv[i] == NULL || (!strncmp(argv[i], "-", 1))) { printf("Please supply the key to query.\n"); print_usage(argc, argv); goto cleanup; } keys = plist_new_array(); while(1) { if (argv[i] && (strlen(argv[i]) >= 2) && (strncmp(argv[i], "-", 1) != 0)) { plist_array_append_item(keys, plist_new_string(argv[i])); i++; } else { i--; break; } } continue; } else if (!strcmp(argv[i], "ioreg")) { cmd = CMD_IOREGISTRY; /* read plane */ i++; if (argv[i]) { cmd_arg = strdup(argv[i]); } continue; } else { print_usage(argc, argv); return 0; } } /* verify options */ if (cmd == CMD_NONE) { print_usage(argc, argv); goto cleanup; } if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } goto cleanup; } if (LOCKDOWN_E_SUCCESS != (ret = lockdownd_client_new_with_handshake(device, &lockdown_client, "idevicediagnostics"))) { idevice_free(device); printf("ERROR: Could not connect to lockdownd, error code %d\n", ret); goto cleanup; } /* attempt to use newer diagnostics service available on iOS 5 and later */ ret = lockdownd_start_service(lockdown_client, "com.apple.mobile.diagnostics_relay", &service); if (ret != LOCKDOWN_E_SUCCESS) { /* attempt to use older diagnostics service */ ret = lockdownd_start_service(lockdown_client, "com.apple.iosdiagnostics.relay", &service); } lockdownd_client_free(lockdown_client); if ((ret == LOCKDOWN_E_SUCCESS) && service && (service->port > 0)) { if (diagnostics_relay_client_new(device, service, &diagnostics_client) != DIAGNOSTICS_RELAY_E_SUCCESS) { printf("Could not connect to diagnostics_relay!\n"); result = -1; } else { switch (cmd) { case CMD_SLEEP: if (diagnostics_relay_sleep(diagnostics_client) == DIAGNOSTICS_RELAY_E_SUCCESS) { printf("Putting device into deep sleep mode.\n"); result = EXIT_SUCCESS; } else { printf("Failed to put device into deep sleep mode.\n"); } break; case CMD_RESTART: if (diagnostics_relay_restart(diagnostics_client, DIAGNOSTICS_RELAY_ACTION_FLAG_WAIT_FOR_DISCONNECT) == DIAGNOSTICS_RELAY_E_SUCCESS) { printf("Restarting device.\n"); result = EXIT_SUCCESS; } else { printf("Failed to restart device.\n"); } break; case CMD_SHUTDOWN: if (diagnostics_relay_shutdown(diagnostics_client, DIAGNOSTICS_RELAY_ACTION_FLAG_WAIT_FOR_DISCONNECT) == DIAGNOSTICS_RELAY_E_SUCCESS) { printf("Shutting down device.\n"); result = EXIT_SUCCESS; } else { printf("Failed to shutdown device.\n"); } break; case CMD_MOBILEGESTALT: if (diagnostics_relay_query_mobilegestalt(diagnostics_client, keys, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { if (node) { print_xml(node); result = EXIT_SUCCESS; } } else { printf("Unable to query mobilegestalt keys.\n"); } break; case CMD_IOREGISTRY: if (diagnostics_relay_query_ioregistry_plane(diagnostics_client, cmd_arg == NULL ? "": cmd_arg, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { if (node) { print_xml(node); result = EXIT_SUCCESS; } } else { printf("Unable to retrieve IORegistry from device.\n"); } break; case CMD_DIAGNOSTICS: default: if (diagnostics_relay_request_diagnostics(diagnostics_client, cmd_arg, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { if (node) { print_xml(node); result = EXIT_SUCCESS; } } else { printf("Unable to retrieve diagnostics from device.\n"); } break; } diagnostics_relay_goodbye(diagnostics_client); diagnostics_relay_client_free(diagnostics_client); } } else { printf("Could not start diagnostics service!\n"); } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } idevice_free(device); cleanup: if (node) { plist_free(node); } if (keys) { plist_free(keys); } if (cmd_arg) { free(cmd_arg); } return result; }
int idevicerestore_start(struct idevicerestore_client_t* client) { int tss_enabled = 0; int result = 0; if (!client) { return -1; } if ((client->flags & FLAG_LATEST) && (client->flags & FLAG_CUSTOM)) { error("ERROR: FLAG_LATEST cannot be used with FLAG_CUSTOM.\n"); return -1; } if (!client->ipsw && !(client->flags & FLAG_PWN) && !(client->flags & FLAG_LATEST)) { error("ERROR: no ipsw file given\n"); return -1; } if (client->flags & FLAG_DEBUG) { idevice_set_debug_level(1); irecv_set_debug_level(1); idevicerestore_debug = 1; } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.0); // update version data (from cache, or apple if too old) load_version_data(client); // check which mode the device is currently in so we know where to start if (check_mode(client) < 0 || client->mode->index == MODE_UNKNOWN) { error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n"); return -1; } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.1); info("Found device in %s mode\n", client->mode->string); if (client->mode->index == MODE_WTF) { unsigned int cpid = 0; if (dfu_client_new(client) != 0) { error("ERROR: Could not open device in WTF mode\n"); return -1; } if ((dfu_get_cpid(client, &cpid) < 0) || (cpid == 0)) { error("ERROR: Could not get CPID for WTF mode device\n"); dfu_client_free(client); return -1; } char wtfname[256]; sprintf(wtfname, "Firmware/dfu/WTF.s5l%04xxall.RELEASE.dfu", cpid); unsigned char* wtftmp = NULL; unsigned int wtfsize = 0; // Prefer to get WTF file from the restore IPSW ipsw_extract_to_memory(client->ipsw, wtfname, &wtftmp, &wtfsize); if (!wtftmp) { // Download WTF IPSW char* s_wtfurl = NULL; plist_t wtfurl = plist_access_path(client->version_data, 7, "MobileDeviceSoftwareVersionsByVersion", "5", "RecoverySoftwareVersions", "WTF", "304218112", "5", "FirmwareURL"); if (wtfurl && (plist_get_node_type(wtfurl) == PLIST_STRING)) { plist_get_string_val(wtfurl, &s_wtfurl); } if (!s_wtfurl) { info("Using hardcoded x12220000_5_Recovery.ipsw URL\n"); s_wtfurl = strdup("http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPhone/061-6618.20090617.Xse7Y/x12220000_5_Recovery.ipsw"); } // make a local file name char* fnpart = strrchr(s_wtfurl, '/'); if (!fnpart) { fnpart = "x12220000_5_Recovery.ipsw"; } else { fnpart++; } struct stat fst; char wtfipsw[1024]; if (client->cache_dir) { if (stat(client->cache_dir, &fst) < 0) { mkdir_with_parents(client->cache_dir, 0755); } strcpy(wtfipsw, client->cache_dir); strcat(wtfipsw, "/"); strcat(wtfipsw, fnpart); } else { strcpy(wtfipsw, fnpart); } if (stat(wtfipsw, &fst) != 0) { download_to_file(s_wtfurl, wtfipsw, 0); } ipsw_extract_to_memory(wtfipsw, wtfname, &wtftmp, &wtfsize); if (!wtftmp) { error("ERROR: Could not extract WTF\n"); } } if (wtftmp) { if (dfu_send_buffer(client, wtftmp, wtfsize) != 0) { error("ERROR: Could not send WTF...\n"); } } dfu_client_free(client); sleep(1); free(wtftmp); client->mode = &idevicerestore_modes[MODE_DFU]; } // discover the device type if (check_product_type(client) == NULL || client->device == NULL) { error("ERROR: Unable to discover device type\n"); return -1; } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.2); info("Identified device as %s\n", client->device->product_type); if ((client->flags & FLAG_PWN) && (client->mode->index != MODE_DFU)) { error("ERROR: you need to put your device into DFU mode to pwn it.\n"); return -1; } if (client->flags & FLAG_PWN) { recovery_client_free(client); info("connecting to DFU\n"); if (dfu_client_new(client) < 0) { return -1; } info("exploiting with limera1n...\n"); // TODO: check for non-limera1n device and fail if (limera1n_exploit(client->device, &client->dfu->client) != 0) { error("ERROR: limera1n exploit failed\n"); dfu_client_free(client); return -1; } dfu_client_free(client); info("Device should be in pwned DFU state now.\n"); return 0; } if (client->flags & FLAG_LATEST) { char* ipsw = NULL; int res = ipsw_download_latest_fw(client->version_data, client->device->product_type, "cache", &ipsw); if (res != 0) { if (ipsw) { free(ipsw); } return res; } else { client->ipsw = ipsw; } } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.6); if (client->flags & FLAG_NOACTION) { return 0; } if (client->mode->index == MODE_RESTORE) { if (restore_reboot(client) < 0) { error("ERROR: Unable to exit restore mode\n"); return -2; } // we need to refresh the current mode again check_mode(client); info("Found device in %s mode\n", client->mode->string); } // verify if ipsw file exists if (access(client->ipsw, F_OK) < 0) { error("ERROR: Firmware file %s does not exist.\n", client->ipsw); return -1; } // extract buildmanifest plist_t buildmanifest = NULL; if (client->flags & FLAG_CUSTOM) { info("Extracting Restore.plist from IPSW\n"); if (ipsw_extract_restore_plist(client->ipsw, &buildmanifest) < 0) { error("ERROR: Unable to extract Restore.plist from %s. Firmware file might be corrupt.\n", client->ipsw); return -1; } } else { info("Extracting BuildManifest from IPSW\n"); if (ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &tss_enabled) < 0) { error("ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw); return -1; } } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.8); /* check if device type is supported by the given build manifest */ if (build_manifest_check_compatibility(buildmanifest, client->device->product_type) < 0) { error("ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n"); return -1; } /* print iOS information from the manifest */ build_manifest_get_version_information(buildmanifest, client); info("Product Version: %s\n", client->version); info("Product Build: %s Major: %d\n", client->build, client->build_major); if (client->flags & FLAG_CUSTOM) { /* prevent signing custom firmware */ tss_enabled = 0; info("Custom firmware requested. Disabled TSS request.\n"); } // choose whether this is an upgrade or a restore (default to upgrade) client->tss = NULL; plist_t build_identity = NULL; if (client->flags & FLAG_CUSTOM) { build_identity = plist_new_dict(); { plist_t node; plist_t comp; plist_t inf; plist_t manifest; char tmpstr[256]; char p_all_flash[128]; char lcmodel[8]; strcpy(lcmodel, client->device->hardware_model); int x = 0; while (lcmodel[x]) { lcmodel[x] = tolower(lcmodel[x]); x++; } sprintf(p_all_flash, "Firmware/all_flash/all_flash.%s.%s", lcmodel, "production"); strcpy(tmpstr, p_all_flash); strcat(tmpstr, "/manifest"); // get all_flash file manifest char *files[16]; char *fmanifest = NULL; uint32_t msize = 0; if (ipsw_extract_to_memory(client->ipsw, tmpstr, (unsigned char**)&fmanifest, &msize) < 0) { error("ERROR: could not extract %s from IPSW\n", tmpstr); return -1; } char *tok = strtok(fmanifest, "\r\n"); int fc = 0; while (tok) { files[fc++] = strdup(tok); if (fc >= 16) { break; } tok = strtok(NULL, "\r\n"); } free(fmanifest); manifest = plist_new_dict(); for (x = 0; x < fc; x++) { inf = plist_new_dict(); strcpy(tmpstr, p_all_flash); strcat(tmpstr, "/"); strcat(tmpstr, files[x]); plist_dict_insert_item(inf, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); const char* compname = get_component_name(files[x]); if (compname) { plist_dict_insert_item(manifest, compname, comp); if (!strncmp(files[x], "DeviceTree", 10)) { plist_dict_insert_item(manifest, "RestoreDeviceTree", plist_copy(comp)); } } else { error("WARNING: unhandled component %s\n", files[x]); plist_free(comp); } free(files[x]); files[x] = NULL; } // add iBSS sprintf(tmpstr, "Firmware/dfu/iBSS.%s.%s.dfu", lcmodel, "RELEASE"); inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "iBSS", comp); // add iBEC sprintf(tmpstr, "Firmware/dfu/iBEC.%s.%s.dfu", lcmodel, "RELEASE"); inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "iBEC", comp); // add kernel cache plist_t kdict = NULL; node = plist_dict_get_item(buildmanifest, "KernelCachesByTarget"); if (node && (plist_get_node_type(node) == PLIST_DICT)) { char tt[4]; strncpy(tt, lcmodel, 3); tt[3] = 0; kdict = plist_dict_get_item(node, tt); } else { // Populated in older iOS IPSWs kdict = plist_dict_get_item(buildmanifest, "RestoreKernelCaches"); } if (kdict && (plist_get_node_type(kdict) == PLIST_DICT)) { plist_t kc = plist_dict_get_item(kdict, "Release"); if (kc && (plist_get_node_type(kc) == PLIST_STRING)) { inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_copy(kc)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "KernelCache", comp); plist_dict_insert_item(manifest, "RestoreKernelCache", plist_copy(comp)); } } // add ramdisk node = plist_dict_get_item(buildmanifest, "RestoreRamDisks"); if (node && (plist_get_node_type(node) == PLIST_DICT)) { plist_t rd = plist_dict_get_item(node, (client->flags & FLAG_ERASE) ? "User" : "Update"); // if no "Update" ram disk entry is found try "User" ram disk instead if (!rd && !(client->flags & FLAG_ERASE)) { rd = plist_dict_get_item(node, "User"); // also, set the ERASE flag since we actually change the restore variant client->flags |= FLAG_ERASE; } if (rd && (plist_get_node_type(rd) == PLIST_STRING)) { inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_copy(rd)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "RestoreRamDisk", comp); } } // add OS filesystem node = plist_dict_get_item(buildmanifest, "SystemRestoreImages"); if (!node) { error("ERROR: missing SystemRestoreImages in Restore.plist\n"); } plist_t os = plist_dict_get_item(node, "User"); if (!os) { error("ERROR: missing filesystem in Restore.plist\n"); } else { inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_copy(os)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "OS", comp); } // add info inf = plist_new_dict(); plist_dict_insert_item(inf, "RestoreBehavior", plist_new_string((client->flags & FLAG_ERASE) ? "Erase" : "Update")); plist_dict_insert_item(inf, "Variant", plist_new_string((client->flags & FLAG_ERASE) ? "Customer Erase Install (IPSW)" : "Customer Upgrade Install (IPSW)")); plist_dict_insert_item(build_identity, "Info", inf); // finally add manifest plist_dict_insert_item(build_identity, "Manifest", manifest); } } else if (client->flags & FLAG_ERASE) { build_identity = build_manifest_get_build_identity(buildmanifest, 0); if (build_identity == NULL) { error("ERROR: Unable to find any build identities\n"); plist_free(buildmanifest); return -1; } } else { // loop through all build identities in the build manifest // and list the valid ones int i = 0; int valid_builds = 0; int build_count = build_manifest_get_identity_count(buildmanifest); for (i = 0; i < build_count; i++) { build_identity = build_manifest_get_build_identity(buildmanifest, i); valid_builds++; } } /* print information about current build identity */ build_identity_print_information(build_identity); idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.0); /* retrieve shsh blobs if required */ if (tss_enabled) { debug("Getting device's ECID for TSS request\n"); /* fetch the device's ECID for the TSS request */ if (get_ecid(client, &client->ecid) < 0) { error("ERROR: Unable to find device ECID\n"); return -1; } info("Found ECID " FMT_qu "\n", (long long unsigned int)client->ecid); if (client->build_major > 8) { unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (get_nonce(client, &nonce, &nonce_size) < 0) { /* the first nonce request with older firmware releases can fail and it's OK */ info("NOTE: Unable to get nonce from device\n"); } 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); } } 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->flags & FLAG_SHSHONLY) { if (!tss_enabled) { info("This device does not require a TSS record"); return 0; } if (!client->tss) { error("ERROR: could not fetch TSS record"); plist_free(buildmanifest); return -1; } else { char *bin = NULL; uint32_t blen = 0; plist_to_bin(client->tss, &bin, &blen); if (bin) { char zfn[1024]; if (client->cache_dir) { strcpy(zfn, client->cache_dir); strcat(zfn, "/shsh"); } else { strcpy(zfn, "shsh"); } mkdir_with_parents(zfn, 0755); sprintf(zfn+strlen(zfn), "/" FMT_qu "-%s-%s.shsh", (long long int)client->ecid, client->device->product_type, client->version); struct stat fst; if (stat(zfn, &fst) != 0) { gzFile zf = gzopen(zfn, "wb"); gzwrite(zf, bin, blen); gzclose(zf); info("SHSH saved to '%s'\n", zfn); } else { info("SHSH '%s' already present.\n", zfn); } free(bin); } else { error("ERROR: could not get TSS record data\n"); } plist_free(client->tss); plist_free(buildmanifest); return 0; } } /* verify if we have tss records if required */ if ((tss_enabled) && (client->tss == NULL)) { error("ERROR: Unable to proceed without a TSS record.\n"); plist_free(buildmanifest); return -1; } if ((tss_enabled) && client->tss) { /* fix empty dicts */ fixup_tss(client->tss); } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.1); // if the device is in normal mode, place device into recovery mode if (client->mode->index == MODE_NORMAL) { info("Entering recovery mode...\n"); if (normal_enter_recovery(client) < 0) { error("ERROR: Unable to place device into recovery mode from %s mode\n", client->mode->string); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -5; } } // Get filesystem name from build identity char* fsname = NULL; if (build_identity_get_component_path(build_identity, "OS", &fsname) < 0) { error("ERROR: Unable get path for filesystem component\n"); return -1; } // check if we already have an extracted filesystem int delete_fs = 0; char* filesystem = NULL; struct stat st; memset(&st, '\0', sizeof(struct stat)); char tmpf[1024]; if (client->cache_dir) { if (stat(client->cache_dir, &st) < 0) { mkdir_with_parents(client->cache_dir, 0755); } strcpy(tmpf, client->cache_dir); strcat(tmpf, "/"); char *ipswtmp = strdup(client->ipsw); strcat(tmpf, basename(ipswtmp)); free(ipswtmp); } else { strcpy(tmpf, client->ipsw); } char* p = strrchr((const char*)tmpf, '.'); if (p) { *p = '\0'; } if (stat(tmpf, &st) < 0) { __mkdir(tmpf, 0755); } strcat(tmpf, "/"); strcat(tmpf, fsname); memset(&st, '\0', sizeof(struct stat)); if (stat(tmpf, &st) == 0) { off_t fssize = 0; ipsw_get_file_size(client->ipsw, fsname, &fssize); if ((fssize > 0) && (st.st_size == fssize)) { info("Using cached filesystem from '%s'\n", tmpf); filesystem = strdup(tmpf); } } if (!filesystem) { char extfn[1024]; strcpy(extfn, tmpf); strcat(extfn, ".extract"); char lockfn[1024]; strcpy(lockfn, tmpf); strcat(lockfn, ".lock"); lock_info_t li; lock_file(lockfn, &li); FILE* extf = NULL; if (access(extfn, F_OK) != 0) { extf = fopen(extfn, "w"); } unlock_file(&li); if (!extf) { // use temp filename filesystem = tempnam(NULL, "ipsw_"); if (!filesystem) { error("WARNING: Could not get temporary filename, using '%s' in current directory\n", fsname); filesystem = strdup(fsname); } delete_fs = 1; } else { // use <fsname>.extract as filename filesystem = strdup(extfn); fclose(extf); } remove(lockfn); // Extract filesystem from IPSW info("Extracting filesystem from IPSW\n"); if (ipsw_extract_to_file(client->ipsw, fsname, filesystem) < 0) { error("ERROR: Unable to extract filesystem from IPSW\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } if (strstr(filesystem, ".extract")) { // rename <fsname>.extract to <fsname> rename(filesystem, tmpf); free(filesystem); filesystem = strdup(tmpf); } } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.3); // if the device is in DFU mode, place device into recovery mode if (client->mode->index == MODE_DFU) { recovery_client_free(client); if ((client->flags & FLAG_CUSTOM) && limera1n_is_supported(client->device)) { info("connecting to DFU\n"); if (dfu_client_new(client) < 0) { if (delete_fs && filesystem) unlink(filesystem); return -1; } info("exploiting with limera1n\n"); // TODO: check for non-limera1n device and fail if (limera1n_exploit(client->device, &client->dfu->client) != 0) { error("ERROR: limera1n exploit failed\n"); dfu_client_free(client); if (delete_fs && filesystem) unlink(filesystem); return -1; } dfu_client_free(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); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); if (delete_fs && filesystem) unlink(filesystem); return -2; } } if (client->mode->index == MODE_DFU) { client->mode = &idevicerestore_modes[MODE_RECOVERY]; } else { if ((client->build_major > 8) && !(client->flags & FLAG_CUSTOM)) { /* send ApTicket */ if (recovery_send_ticket(client) < 0) { error("WARNING: Unable to send APTicket\n"); } } /* now we load the iBEC */ if (recovery_send_ibec(client, build_identity) < 0) { error("ERROR: Unable to send iBEC\n"); if (delete_fs && filesystem) unlink(filesystem); return -2; } recovery_client_free(client); /* this must be long enough to allow the device to run the iBEC */ /* FIXME: Probably better to detect if the device is back then */ sleep(7); } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.5); if (client->build_major > 8) { // we need another tss request with nonce. unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (get_nonce(client, &nonce, &nonce_size) < 0) { error("ERROR: Unable to get nonce from device!\n"); recovery_send_reset(client); if (delete_fs && filesystem) unlink(filesystem); return -2; } 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); } 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"); if (delete_fs && filesystem) unlink(filesystem); return -1; } if (!client->tss) { error("ERROR: can't continue without TSS\n"); if (delete_fs && filesystem) unlink(filesystem); return -1; } fixup_tss(client->tss); } } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.7); // now finally do the magic to put the device into restore mode if (client->mode->index == MODE_RECOVERY) { if (client->srnm == NULL) { error("ERROR: could not retrieve device serial number. Can't continue.\n"); if (delete_fs && filesystem) unlink(filesystem); return -1; } if (recovery_enter_restore(client, build_identity) < 0) { error("ERROR: Unable to place device into restore mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); if (delete_fs && filesystem) unlink(filesystem); return -2; } recovery_client_free(client); } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.9); // device is finally in restore mode, let's do this if (client->mode->index == MODE_RESTORE) { info("About to restore device... \n"); result = restore_device(client, build_identity, filesystem); if (result < 0) { error("ERROR: Unable to restore device\n"); if (delete_fs && filesystem) unlink(filesystem); return result; } } info("Cleaning up...\n"); if (delete_fs && filesystem) unlink(filesystem); /* special handling of AppleTVs */ if (strncmp(client->device->product_type, "AppleTV", 7) == 0) { if (recovery_client_new(client) == 0) { if (recovery_set_autoboot(client, 1) == 0) { recovery_send_reset(client); } else { error("Setting auto-boot failed?!\n"); } } else { error("Could not connect to device in recovery mode.\n"); } } info("DONE\n"); if (result == 0) { idevicerestore_progress(client, RESTORE_NUM_STEPS-1, 1.0); } return result; }
int main(int argc, char *argv[]) { heartbeat_client_t heartbeat = NULL; idevice_t device = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; const char* udid = NULL; signal(SIGINT, clean_exit); signal(SIGTERM, clean_exit); #ifndef WIN32 signal(SIGQUIT, clean_exit); signal(SIGPIPE, SIG_IGN); #endif /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } /* start heartbeat service on device */ heartbeat_client_start_service(device, &heartbeat, "ideviceheartbeat"); if (heartbeat) { printf("< heartbeat started, listening...\n"); } else { printf("Failed to start heartbeat service\n"); idevice_free(device); return -1; } /* main loop */ uint8_t b = 0; uint64_t interval = 10000; plist_t message = NULL; plist_t node = NULL; do { /* await a "ping" message from the device every interval seconds */ heartbeat_receive_with_timeout(heartbeat, &message, (uint32_t)interval); if (message) { /* report device beat settings */ node = plist_dict_get_item(message, "SupportsSleepyTime"); if (node && plist_get_node_type(node) == PLIST_BOOLEAN) { plist_get_bool_val(node, &b); } node = plist_dict_get_item(message, "Interval"); if (node && plist_get_node_type(node) == PLIST_UINT) { plist_get_uint_val(node, &interval); } printf("> marco: supports_sleepy_time %d, interval %llu\n", b, interval); plist_free(message); message = NULL; /* answer with a "pong" message */ message = plist_new_dict(); plist_dict_insert_item(message, "Command", plist_new_string("Polo")); heartbeat_send(heartbeat, message); printf("< polo\n"); if (message) { plist_free(message); message = NULL; } } } while(!quit_flag); heartbeat_client_free(heartbeat); idevice_free(device); return 0; }
int main(int argc, char *argv[]) { unsigned int bytes = 0; uint16_t i = 0; lockdownd_service_descriptor_t service = NULL; lockdownd_client_t client = NULL; idevice_t phone = NULL; uint64_t lockfile = 0; np_client_t gnp = NULL; if (argc > 1 && !strcasecmp(argv[1], "--debug")) { idevice_set_debug_level(1); } else { idevice_set_debug_level(0); } if (IDEVICE_E_SUCCESS != idevice_new(&phone, NULL)) { printf("No device found, is it plugged in?\n"); return -1; } char *udid = NULL; if (IDEVICE_E_SUCCESS == idevice_get_udid(phone, &udid)) { printf("DeviceUniqueID : %s\n", udid); } if (udid) free(udid); if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "ideviceclient")) { idevice_free(phone); printf("Exiting.\n"); return -1; } char *nnn = NULL; if (LOCKDOWN_E_SUCCESS == lockdownd_get_device_name(client, &nnn)) { printf("DeviceName : %s\n", nnn); free(nnn); } lockdownd_start_service(client, "com.apple.afc", &service); if (service && service->port) { afc_client_t afc = NULL; afc_client_new(phone, service, &afc); if (afc) { service->port = 0; service->ssl_enabled = 0; lockdownd_start_service(client, "com.apple.mobile.notification_proxy", &service); if (service->port) { printf("Notification Proxy started.\n"); np_client_new(phone, service, &gnp); } else { printf("ERROR: Notification proxy could not be started.\n"); } if (gnp) { const char *nspec[5] = { NP_SYNC_CANCEL_REQUEST, NP_SYNC_SUSPEND_REQUEST, NP_SYNC_RESUME_REQUEST, NP_ITDBPREP_DID_END, NULL }; np_observe_notifications(gnp, nspec); np_set_notify_callback(gnp, notifier, NULL); } perform_notification(phone, client, NP_SYNC_WILL_START); afc_file_open(afc, "/com.apple.itunes.lock_sync", AFC_FOPEN_RW, &lockfile); if (lockfile) { printf("locking file\n"); afc_file_lock(afc, lockfile, AFC_LOCK_EX); perform_notification(phone, client, NP_SYNC_DID_START); } char **dirs = NULL; afc_read_directory(afc, "/eafaedf", &dirs); if (!dirs) afc_read_directory(afc, "/", &dirs); printf("Directory time.\n"); for (i = 0; dirs[i]; i++) { printf("/%s\n", dirs[i]); free(dirs[i]); } if (dirs) free(dirs); dirs = NULL; afc_get_device_info(afc, &dirs); if (dirs) { for (i = 0; dirs[i]; i += 2) { printf("%s: %s\n", dirs[i], dirs[i + 1]); free(dirs[i]); } free(dirs); } uint64_t my_file = 0; char **info = NULL; uint64_t fsize = 0; if (AFC_E_SUCCESS == afc_get_file_info(afc, "/readme.libimobiledevice.fx", &info) && info) { for (i = 0; info[i]; i += 2) { printf("%s: %s\n", info[i], info[i+1]); if (!strcmp(info[i], "st_size")) { fsize = atoll(info[i+1]); } } } if (AFC_E_SUCCESS == afc_file_open(afc, "/readme.libimobiledevice.fx", AFC_FOPEN_RDONLY, &my_file) && my_file) { printf("A file size: %llu\n", (long long)fsize); char *file_data = (char *) malloc(sizeof(char) * fsize); afc_file_read(afc, my_file, file_data, fsize, &bytes); if (bytes > 0) { printf("The file's data:\n"); fwrite(file_data, 1, bytes, stdout); } printf("\nClosing my file.\n"); afc_file_close(afc, my_file); free(file_data); } else printf("couldn't open a file\n"); afc_file_open(afc, "/readme.libimobiledevice.fx", AFC_FOPEN_WR, &my_file); if (my_file) { char *outdatafile = strdup("this is a bitchin text file\n"); afc_file_write(afc, my_file, outdatafile, strlen(outdatafile), &bytes); free(outdatafile); if (bytes > 0) printf("Wrote a surprise. ;)\n"); else printf("I wanted to write a surprise, but... :(\n"); afc_file_close(afc, my_file); } printf("Deleting a file...\n"); bytes = afc_remove_path(afc, "/delme"); if (bytes) printf("Success.\n"); else printf("Failure. (expected unless you have a /delme file on your phone)\n"); printf("Renaming a file...\n"); bytes = afc_rename_path(afc, "/renme", "/renme2"); if (bytes > 0) printf("Success.\n"); else printf("Failure. (expected unless you have a /renme file on your phone)\n"); printf("Seek & read\n"); afc_file_open(afc, "/readme.libimobiledevice.fx", AFC_FOPEN_RDONLY, &my_file); if (AFC_E_SUCCESS != afc_file_seek(afc, my_file, 5, SEEK_CUR)) printf("WARN: SEEK DID NOT WORK\n"); char *threeletterword = (char *) malloc(sizeof(char) * 5); afc_file_read(afc, my_file, threeletterword, 3, &bytes); threeletterword[3] = '\0'; if (bytes > 0) printf("Result: %s\n", threeletterword); else printf("Couldn't read!\n"); free(threeletterword); afc_file_close(afc, my_file); } if (gnp && lockfile) { printf("XXX sleeping\n"); sleep(5); printf("XXX unlocking file\n"); afc_file_lock(afc, lockfile, AFC_LOCK_UN); printf("XXX closing file\n"); afc_file_close(afc, lockfile); printf("XXX sleeping\n"); sleep(5); //perform_notification(phone, client, NP_SYNC_DID_FINISH); } if (gnp) { np_client_free(gnp); gnp = NULL; } afc_client_free(afc); lockdownd_service_descriptor_free(service); service = NULL; } else { printf("Start service failure.\n"); } printf("All done.\n"); lockdownd_client_free(client); idevice_free(phone); return 0; }
bool ibrowserAPI::init(F_SUCC,F_ERRO) { lockdownd_service_descriptor_t service = NULL; if (NULL == device) { if (IDEVICE_E_SUCCESS != idevice_new(&device, NULL)) { ERRO("idevice_new"); } idevice_set_debug_level(1); } if (NULL == lockdownd_client) { if (LOCKDOWN_E_SUCCESS != (lockdownd_client_new_with_handshake(device, &lockdownd_client, CLIENT_LABEL))) { ERRO("lockdownd_client_new_with_handshake"); } } if (NULL == instproxy_client) { if(LOCKDOWN_E_SUCCESS != (lockdownd_start_service(lockdownd_client,"com.apple.mobile.installation_proxy",&service) || !service->port)) { ERRO("lockdownd_start_service com.apple.mobile.installation_proxy"); } if(INSTPROXY_E_SUCCESS != instproxy_client_new(device,service,&instproxy_client) ) { ERRO("instproxy_client_new"); } } if (NULL == afc_client) { if(LOCKDOWN_E_SUCCESS != (lockdownd_start_service(lockdownd_client,"com.apple.afc",&service)) || !service->port) { ERRO("lockdownd_start_service com.apple.afc"); } if (afc_client_new(device, service, &afc_client) != AFC_E_SUCCESS) { ERRO("afc_client_new"); } } if (NULL == sbservices_client) { if(LOCKDOWN_E_SUCCESS != (lockdownd_start_service(lockdownd_client,"com.apple.springboardservices",&service)) || !service->port) { ERRO("lockdownd_start_service com.apple.springboardservices"); } if (sbservices_client_new(device, service, &sbservices_client) != AFC_E_SUCCESS) { ERRO("sbservices_client_new"); } } return true; }
int main(int argc, char *argv[]) { lockdownd_client_t lockdown = NULL; idevice_t device = NULL; idevice_connection_t connection = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; thread_t th; const char* udid = NULL; uint16_t port = 0; uint16_t local_port = 0; int result = EXIT_SUCCESS; int i; /* bind signals */ signal(SIGINT, clean_exit); signal(SIGTERM, clean_exit); #ifndef WIN32 signal(SIGQUIT, clean_exit); signal(SIGPIPE, SIG_IGN); #endif /* parse cmdline arguments */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { debug_mode = 1; idevice_set_debug_level(1); socket_set_verbose(3); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return EXIT_SUCCESS; } else if (atoi(argv[i]) > 0) { local_port = atoi(argv[i]); continue; } else { print_usage(argc, argv); return EXIT_SUCCESS; } } /* a PORT is mandatory */ if (!local_port) { fprintf(stderr, "Please specify a PORT.\n"); print_usage(argc, argv); goto leave_cleanup; } /* start services and connect to device */ ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { fprintf(stderr, "No device found with udid %s, is it plugged in?\n", udid); } else { fprintf(stderr, "No device found, is it plugged in?\n"); } result = EXIT_FAILURE; goto leave_cleanup; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lockdown, "idevicedebugserverproxy")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); result = EXIT_FAILURE; goto leave_cleanup; } if ((lockdownd_start_service(lockdown, "com.apple.debugserver", &port) != LOCKDOWN_E_SUCCESS) || !port) { fprintf(stderr, "Could not start com.apple.debugserver!\nPlease make sure to mount the developer disk image first.\n"); result = EXIT_FAILURE; goto leave_cleanup; } if (idevice_connect(device, port, &connection) != IDEVICE_E_SUCCESS) { fprintf(stderr, "Connection to debugserver port %d failed!\n", (int)port); result = EXIT_FAILURE; goto leave_cleanup; } /* free lockdown connection if running as it is not needed anymore */ if (lockdown) { lockdownd_client_free(lockdown); lockdown = NULL; } /* setup and create socket endpoint */ socket_info_t socket_info; socket_info.device_connection = connection; socket_info.local_port = local_port; socket_info.remote_port = port; /* create local socket */ socket_info.server_fd = socket_create(socket_info.local_port); if (socket_info.server_fd < 0) { fprintf(stderr, "Could not create socket\n"); result = EXIT_FAILURE; goto leave_cleanup; } while (!quit_flag) { debug("%s: Waiting for connection on local port %d\n", __func__, socket_info.local_port); /* wait for client */ socket_info.client_fd = socket_accept(socket_info.server_fd, socket_info.local_port); if (socket_info.client_fd < 0) { debug("%s: Continuing...\n", __func__); continue; } debug("%s: Handling new client connection...\n", __func__); if (thread_create(&th, connection_handler, (void*)&socket_info) != 0) { fprintf(stderr, "Could not start connection handler.\n"); socket_shutdown(socket_info.server_fd, SHUT_RDWR); socket_close(socket_info.server_fd); } } debug("%s: Shutting down debugserver proxy...\n", __func__); leave_cleanup: if (connection) { idevice_disconnect(connection); } if (lockdown) { lockdownd_client_free(lockdown); } if (device) { idevice_free(device); } return result; }
int main(int argc, char **argv) { idevice_t device = NULL; lockdownd_client_t client = NULL; char **dev_list = NULL; char *device_name = NULL; int ret = 0; int i; int mode = MODE_SHOW_ID; const char* udid = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) { mode = MODE_LIST_DEVICES; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } } /* check if udid was passed */ if (mode == MODE_SHOW_ID) { i--; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; } switch (mode) { case MODE_SHOW_ID: idevice_new(&device, udid); if (!device) { fprintf(stderr, "ERROR: No device with UDID=%s attached.\n", udid); return -2; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new(device, &client, "idevice_id")) { idevice_free(device); fprintf(stderr, "ERROR: Connecting to device failed!\n"); return -2; } if ((LOCKDOWN_E_SUCCESS != lockdownd_get_device_name(client, &device_name)) || !device_name) { fprintf(stderr, "ERROR: Could not get device name!\n"); ret = -2; } lockdownd_client_free(client); idevice_free(device); if (ret == 0) { printf("%s\n", device_name); } if (device_name) { free(device_name); } return ret; case MODE_LIST_DEVICES: default: if (idevice_get_device_list(&dev_list, &i) < 0) { fprintf(stderr, "ERROR: Unable to retrieve device list!\n"); return -1; } for (i = 0; dev_list[i] != NULL; i++) { printf("%s\n", dev_list[i]); } idevice_device_list_free(dev_list); return 0; } }
int main(int argc, char **argv) { idevice_t device = NULL; lockdownd_client_t lckd = NULL; screenshotr_client_t shotr = NULL; uint16_t port = 0; int result = -1; int i; const char *udid = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lckd, NULL)) { idevice_free(device); printf("Exiting.\n"); return -1; } lockdownd_start_service(lckd, "com.apple.mobile.screenshotr", &port); lockdownd_client_free(lckd); if (port > 0) { if (screenshotr_client_new(device, port, &shotr) != SCREENSHOTR_E_SUCCESS) { printf("Could not connect to screenshotr!\n"); } else { char *imgdata = NULL; char filename[36]; uint64_t imgsize = 0; time_t now = time(NULL); strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S.tiff", gmtime(&now)); if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) { FILE *f = fopen(filename, "wb"); if (f) { if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) { printf("Screenshot saved to %s\n", filename); result = 0; } else { printf("Could not save screenshot to file %s!\n", filename); } fclose(f); } else { printf("Could not open %s for writing: %s\n", filename, strerror(errno)); } } else { printf("Could not get screenshot!\n"); } screenshotr_client_free(shotr); } } else { printf("Could not start screenshotr service! Remember that you have to mount the Developer disk image on your device if you want to use the screenshotr service.\n"); } idevice_free(device); return result; }
int main(int argc, char* argv[]) { int opt = 0; int optindex = 0; char* ipsw = NULL; char* uuid = NULL; int tss_enabled = 0; // create an instance of our context struct idevicerestore_client_t* client = (struct idevicerestore_client_t*) malloc(sizeof(struct idevicerestore_client_t)); if (client == NULL) { error("ERROR: Out of memory\n"); return -1; } memset(client, '\0', sizeof(struct idevicerestore_client_t)); while ((opt = getopt_long(argc, argv, "dhcexu:", longopts, &optindex)) > 0) { switch (opt) { case 'h': usage(argc, argv); return 0; case 'd': client->flags |= FLAG_DEBUG; idevicerestore_debug = 1; break; case 'e': client->flags |= FLAG_ERASE; break; case 'c': client->flags |= FLAG_CUSTOM; break; case 'x': client->flags |= FLAG_EXCLUDE; break; case 'u': uuid = optarg; break; default: usage(argc, argv); return -1; } } if ((argc-optind) == 1) { argc -= optind; argv += optind; ipsw = argv[0]; } else { usage(argc, argv); return -1; } if (client->flags & FLAG_DEBUG) { idevice_set_debug_level(1); irecv_set_debug_level(1); } client->uuid = uuid; client->ipsw = ipsw; // check which mode the device is currently in so we know where to start if (check_mode(client) < 0 || client->mode->index == MODE_UNKNOWN) { error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n"); return -1; } info("Found device in %s mode\n", client->mode->string); // discover the device type if (check_device(client) < 0 || client->device->index == DEVICE_UNKNOWN) { error("ERROR: Unable to discover device type\n"); return -1; } info("Identified device as %s\n", client->device->product); if (client->mode->index == MODE_RESTORE) { if (restore_reboot(client) < 0) { error("ERROR: Unable to exit restore mode\n"); return -1; } } // extract buildmanifest plist_t buildmanifest = NULL; info("Extracting BuildManifest from IPSW\n"); if (ipsw_extract_build_manifest(ipsw, &buildmanifest, &tss_enabled) < 0) { error("ERROR: Unable to extract BuildManifest from %s\n", ipsw); return -1; } /* print iOS information from the manifest */ build_manifest_print_information(buildmanifest); if (client->flags & FLAG_CUSTOM) { /* prevent signing custom firmware */ tss_enabled = 0; info("Custom firmware requested. Disabled TSS request.\n"); } // choose whether this is an upgrade or a restore (default to upgrade) client->tss = NULL; plist_t build_identity = NULL; if (client->flags & FLAG_ERASE) { build_identity = build_manifest_get_build_identity(buildmanifest, 0); if (build_identity == NULL) { error("ERROR: Unable to find any build identities\n"); plist_free(buildmanifest); return -1; } } else { // loop through all build identities in the build manifest // and list the valid ones int i = 0; int valid_builds = 0; int build_count = build_manifest_get_identity_count(buildmanifest); for (i = 0; i < build_count; i++) { build_identity = build_manifest_get_build_identity(buildmanifest, i); valid_builds++; } } /* print information about current build identity */ build_identity_print_information(build_identity); /* retrieve shsh blobs if required */ if (tss_enabled) { debug("Getting device's ECID for TSS request\n"); /* fetch the device's ECID for the TSS request */ if (get_ecid(client, &client->ecid) < 0) { error("ERROR: Unable to find device ECID\n"); return -1; } info("Found ECID %llu\n", client->ecid); if (get_shsh_blobs(client, client->ecid, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } } /* verify if we have tss records if required */ if ((tss_enabled) && (client->tss == NULL)) { error("ERROR: Unable to proceed without a TSS record.\n"); plist_free(buildmanifest); return -1; } // Extract filesystem from IPSW and return its name char* filesystem = NULL; if (ipsw_extract_filesystem(client->ipsw, build_identity, &filesystem) < 0) { error("ERROR: Unable to extract filesystem from IPSW\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } // if the device is in normal mode, place device into recovery mode if (client->mode->index == MODE_NORMAL) { info("Entering recovery mode...\n"); if (normal_enter_recovery(client) < 0) { error("ERROR: Unable to place device into recovery mode\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } } // if the device is in DFU mode, place device into recovery mode if (client->mode->index == MODE_DFU) { if (dfu_enter_recovery(client, build_identity) < 0) { error("ERROR: Unable to place device into recovery mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); return -1; } } // if the device is in recovery mode, place device into restore mode if (client->mode->index == MODE_RECOVERY) { if (recovery_enter_restore(client, build_identity) < 0) { error("ERROR: Unable to place device into restore mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); return -1; } } // device is finally in restore mode, let's do this if (client->mode->index == MODE_RESTORE) { info("Restoring device... \n"); if (restore_device(client, build_identity, filesystem) < 0) { error("ERROR: Unable to restore device\n"); return -1; } } info("Cleaning up...\n"); if (filesystem) unlink(filesystem); info("DONE\n"); return 0; }
int main(int argc, const char **argv) { char *errmsg = ""; idevice_t device = NULL; lockdownd_client_t client = NULL; lockdownd_service_descriptor_t service = NULL; house_arrest_client_t hac = NULL; const char *service_name = "com.apple.afc"; const char *appid = NULL; char *device_name = NULL; int result = 0; char* udid = NULL; int cmd = CMD_INTERACTIVE; const char *cmdstr = NULL; int i; cwd = strdup("/"); /* parse cmdline args */ for (i = 1; i < argc; i++) { if (str_is_equal(argv[i], "-d") || str_is_equal(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (str_is_equal(argv[i], "-u") || str_is_equal(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); exit(EXIT_FAILURE); } udid = strdup(argv[i]); continue; } else if (str_is_equal(argv[i], "-2") || str_is_equal(argv[i], "--afc2")) { service_name = "com.apple.afc2"; continue; } else if (str_is_equal(argv[i], "-a") || str_is_equal(argv[i], "--appid")) { if (++i >= argc) { print_usage(argc, argv); exit(EXIT_FAILURE); } appid = argv[i]; } else if (str_is_equal(argv[i], "-h") || str_is_equal(argv[i], "--help")) { print_usage(argc, argv); exit(EXIT_SUCCESS); } else if ((cmd = str_to_cmd(argv[i])) != CMD_UNKNOWN) { cmdstr = argv[i]; i++; break; } } argc -= i; argv += i; /* Connect to device */ if (udid) { result = idevice_new(&device, udid); if (result != IDEVICE_E_SUCCESS) errx(EXIT_FAILURE, "No device found with udid %s, is it plugged in?", udid); } else { result = idevice_new(&device, NULL); if (result != IDEVICE_E_SUCCESS) errx(EXIT_FAILURE, "No device found, is it plugged in?"); idevice_get_udid(device, &udid); } /* Connect to lockdownd */ result = lockdownd_client_new_with_handshake(device, &client, "afccl"); if (result != LOCKDOWN_E_SUCCESS) { asprintf(&errmsg, "ERROR: Connecting to lockdownd service failed!"); goto bail; } result = lockdownd_get_device_name(client, &device_name); if ((result != LOCKDOWN_E_SUCCESS) || !device_name) { asprintf(&errmsg, "ERROR: Could not get device name!"); goto bail; } if (appid) { result = lockdownd_start_service(client, "com.apple.mobile.house_arrest", &service); if (result != LOCKDOWN_E_SUCCESS || !service || !service->port) { asprintf(&errmsg, "error starting house arrest service: (%d) %s", result, afc_strerror(result)); goto bail; } if (client) { lockdownd_client_free(client); client = NULL; } if (house_arrest_client_new(device, service, &hac) != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "could not connect to house_arrest service!\n"); goto bail; } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } result = house_arrest_send_command(hac, "VendDocuments", appid); if (result != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "error %d when trying to get VendDocuments\n", result); goto bail; } plist_t dict = NULL; if (house_arrest_get_result(hac, &dict) != HOUSE_ARREST_E_SUCCESS) { if (house_arrest_get_result(hac, &dict) != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "hmmm....\n"); goto bail; } } plist_t node = plist_dict_get_item(dict, "Error"); if (node) { char *str = NULL; plist_get_string_val(node, &str); asprintf(&errmsg, "Error: %s\n", str); if (str) free(str); plist_free(dict); dict = NULL; goto bail; } node = plist_dict_get_item(dict, "Status"); if (node) { char *str = NULL; plist_get_string_val(node, &str); if (str && (strcmp(str, "Complete") != 0)) { printf("Warning: Status is not 'Complete' but '%s'\n", str); } if (str) free(str); } if (dict) { plist_free(dict); } afc_error_t ae = afc_client_new_from_house_arrest_client(hac, &afc); if (ae != AFC_E_SUCCESS) { printf("afc error %d\n", ae); } } else { result = lockdownd_start_service(client, service_name, &service); if (result != LOCKDOWN_E_SUCCESS || !service || !service->port) { asprintf(&errmsg, "error starting AFC service: (%d) %s", result, afc_strerror(result)); goto bail; } /* Connect to AFC */ result = afc_client_new(device, service, &afc); lockdownd_client_free(client); idevice_free(device); if (result != AFC_E_SUCCESS) { errx(EXIT_FAILURE, "AFC connection failed (%d) %s", result, afc_strerror(result)); } } result = do_cmd(cmd, argc, argv); if (hac) house_arrest_client_free(hac); afc_client_free(afc); exit(result == 0 ? EXIT_SUCCESS : EXIT_FAILURE); bail: if (hac) house_arrest_client_free(hac); if (service) lockdownd_service_descriptor_free(service); if (client) lockdownd_client_free(client); if (device) idevice_free(device); errx(EXIT_FAILURE, "%s", errmsg); }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; idevice_t phone = NULL; idevice_set_debug_level(1); if (IDEVICE_E_SUCCESS != idevice_new(&phone, NULL)) { printf("No device found, is it plugged in?\n"); return -1; } char *udid = NULL; if (IDEVICE_E_SUCCESS == idevice_get_udid(phone, &udid)) { printf("DeviceUniqueID : %s\n", udid); } if (udid) free(udid); if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "lckdclient")) { idevice_free(phone); return -1; } using_history(); int loop = 1; while (loop) { char *cmd = readline("> "); if (cmd) { char **args = get_tokens(cmd); int len = 0; while (args && args[len]) { len++; } if (len > 0) { add_history(cmd); if (!strcmp(*args, "quit")) loop = 0; if (!strcmp(*args, "get") && len >= 2) { plist_t value = NULL; if (LOCKDOWN_E_SUCCESS == lockdownd_get_value(client, len == 3 ? *(args + 1):NULL, len == 3 ? *(args + 2):*(args + 1), &value)) { char *xml = NULL; uint32_t length; plist_to_xml(value, &xml, &length); printf("Success : value = %s\n", xml); free(xml); } else printf("Error\n"); if (value) plist_free(value); } if (!strcmp(*args, "start") && len == 2) { uint16_t port = 0; if(LOCKDOWN_E_SUCCESS == lockdownd_start_service(client, *(args + 1), &port)) { printf("started service %s on port %i\n", *(args + 1), port); } else { printf("failed to start service %s on device.\n", *(args + 1)); } } } strfreev(args); } free(cmd); cmd = NULL; } clear_history(); lockdownd_client_free(client); idevice_free(phone); return 0; }
int main(int argc, char **argv) { idevice_t device = NULL; lockdownd_client_t lckd = NULL; lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR; screenshotr_client_t shotr = NULL; lockdownd_service_descriptor_t service = NULL; int result = -1; int i; const char *udid = NULL; char *filename = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else if (argv[i][0] != '-' && !filename) { filename = strdup(argv[i]); continue; } else { print_usage(argc, argv); return 0; } } if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &lckd, NULL))) { idevice_free(device); printf("ERROR: Could not connect to lockdownd, error code %d\n", ldret); return -1; } lockdownd_start_service(lckd, "com.apple.mobile.screenshotr", &service); lockdownd_client_free(lckd); if (service && service->port > 0) { if (screenshotr_client_new(device, service, &shotr) != SCREENSHOTR_E_SUCCESS) { printf("Could not connect to screenshotr!\n"); } else { char *imgdata = NULL; uint64_t imgsize = 0; if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) { if (!filename) { const char *fileext = NULL; if (memcmp(imgdata, "\x89PNG", 4) == 0) { fileext = ".png"; } else if (memcmp(imgdata, "MM\x00*", 4) == 0) { fileext = ".tiff"; } else { printf("WARNING: screenshot data has unexpected image format.\n"); fileext = ".dat"; } time_t now = time(NULL); filename = (char*)malloc(36); size_t pos = strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S", gmtime(&now)); sprintf(filename+pos, "%s", fileext); } FILE *f = fopen(filename, "wb"); if (f) { if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) { printf("Screenshot saved to %s\n", filename); result = 0; } else { printf("Could not save screenshot to file %s!\n", filename); } fclose(f); } else { printf("Could not open %s for writing: %s\n", filename, strerror(errno)); } } else { printf("Could not get screenshot!\n"); } screenshotr_client_free(shotr); } } else { printf("Could not start screenshotr service! Remember that you have to mount the Developer disk image on your device if you want to use the screenshotr service.\n"); } if (service) lockdownd_service_descriptor_free(service); idevice_free(device); free(filename); return result; }
int main(int argc, char **argv) { idevice_t dev = NULL; lockdownd_client_t client = NULL; house_arrest_client_t hac = NULL; house_arrest_error_t res; int i; char *udid = NULL; const char *appid = NULL; int test_file_io = 0; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = strdup(argv[i]); continue; } else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "--test")) { test_file_io = 1; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { appid = argv[i]; break; } } if (!appid) { print_usage(argc, argv); return 0; } if (idevice_new(&dev, udid) != IDEVICE_E_SUCCESS) { printf("no device connected?!\n"); goto leave_cleanup; } if (lockdownd_client_new_with_handshake(dev, &client, NULL) != LOCKDOWN_E_SUCCESS) { printf("could not connect to lockdownd!\n"); goto leave_cleanup; } uint16_t port = 0; if (lockdownd_start_service(client, "com.apple.mobile.house_arrest", &port) != LOCKDOWN_E_SUCCESS) { printf("could not start house_arrest service!\n"); goto leave_cleanup; } if (client) { lockdownd_client_free(client); client = NULL; } if (house_arrest_client_new(dev, port, &hac) != HOUSE_ARREST_E_SUCCESS) { printf("could not connect to house_arrest service!\n"); goto leave_cleanup; } res = house_arrest_send_command(hac, "VendDocuments", appid); if (res != HOUSE_ARREST_E_SUCCESS) { printf("error %d when trying to get VendDocuments\n", res); goto leave_cleanup; } plist_t dict = NULL; if (house_arrest_get_result(hac, &dict) != HOUSE_ARREST_E_SUCCESS) { if (house_arrest_get_result(hac, &dict) != HOUSE_ARREST_E_SUCCESS) { printf("hmmm....\n"); goto leave_cleanup; } } plist_t node = plist_dict_get_item(dict, "Error"); if (node) { char *str = NULL; plist_get_string_val(node, &str); printf("Error: %s\n", str); if (str) free(str); plist_free(dict); dict = NULL; goto leave_cleanup; } node = plist_dict_get_item(dict, "Status"); if (node) { char *str = NULL; plist_get_string_val(node, &str); if (str && (strcmp(str, "Complete") != 0)) { printf("Warning: Status is not 'Complete' but '%s'\n", str); } if (str) free(str); plist_free(dict); dict = NULL; } if (dict) { plist_free(dict); } afc_client_t afc = NULL; afc_error_t ae = afc_client_new_from_house_arrest_client(hac, &afc); if (ae != AFC_E_SUCCESS) { printf("afc error %d\n", ae); } if (ae == AFC_E_SUCCESS) { char **list = NULL; afc_read_directory(afc, "/", &list); printf("Directory contents:\n"); if (list) { while (list[0]) { if (strcmp(list[0], ".") && strcmp(list[0], "..")) { puts(list[0]); } list++; } } if (test_file_io) { uint64_t tf = 0; printf("\n==== Performing file tests ====\n"); printf("Opening file 'foobar' for writing: "); if (afc_file_open(afc, "/foobar", AFC_FOPEN_RW, &tf) == AFC_E_SUCCESS) { uint32_t wb = 0; printf("OK\n"); printf("Writing to file: "); if (afc_file_write(afc, tf, "test\r\n", 6, &wb) != AFC_E_SUCCESS) { printf("ERROR\n"); } else { printf("OK\n"); } afc_file_close(afc, tf); printf("Deleting file 'foobar': "); if (afc_remove_path(afc, "/foobar") == AFC_E_SUCCESS) { printf("OK\n"); } else { printf("ERROR\n"); } } else { printf("ERROR\n"); } } afc_client_free(afc); } else { printf("failed to connect to afc service, error %d\n", ae); } leave_cleanup: if (hac) { house_arrest_client_free(hac); } if (client) { lockdownd_client_free(client); } if (dev) { idevice_free(dev); } return 0; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; lockdownd_service_descriptor_t service = NULL; idevice_t device = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; int op = -1; const char* udid = NULL; const char* param = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "install")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_INSTALL; continue; } else if (!strcmp(argv[i], "list")) { op = OP_LIST; } else if (!strcmp(argv[i], "copy")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_COPY; continue; } else if (!strcmp(argv[i], "remove")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_REMOVE; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } if ((op == -1) || (op >= NUM_OPS)) { print_usage(argc, argv); return 0; } ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &client, "ideviceprovision")) { idevice_free(device); return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_start_service(client, "com.apple.misagent", &service)) { fprintf(stderr, "Could not start service \"com.apple.misagent\"\n"); lockdownd_client_free(client); idevice_free(device); return -1; } lockdownd_client_free(client); client = NULL; misagent_client_t mis = NULL; if (misagent_client_new(device, service, &mis) != MISAGENT_E_SUCCESS) { fprintf(stderr, "Could not connect to \"com.apple.misagent\" on device\n"); if (service) lockdownd_service_descriptor_free(service); lockdownd_client_free(client); idevice_free(device); return -1; } if (service) lockdownd_service_descriptor_free(service); switch (op) { case OP_INSTALL: { FILE* f = fopen(param, "rb"); if (!f) { fprintf(stderr, "Could not open file '%s'\n", param); break; } fseek(f, 0, SEEK_END); long int size = ftell(f); fseek(f, 0, SEEK_SET); if (size >= 0x1000000) { fprintf(stderr, "The file '%s' is too large for processing.\n", param); fclose(f); break; } char* buf = malloc(size); if (!buf) { fprintf(stderr, "Could not allocate memory...\n"); fclose(f); break; } long int cur = 0; while (cur < size) { ssize_t r = fread(buf+cur, 1, 512, f); if (r <= 0) { break; } cur += r; } fclose(f); if (cur != size) { free(buf); fprintf(stderr, "Could not read in file '%s' (size %ld read %ld)\n", param, size, cur); break; } uint64_t psize = size; plist_t pdata = plist_new_data(buf, psize); if (misagent_install(mis, pdata) == MISAGENT_E_SUCCESS) { printf("Profile '%s' installed successfully.\n", param); } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not install profile '%s', status code: 0x%x\n", param, sc); } free(buf); } break; case OP_LIST: case OP_COPY: { plist_t profiles = NULL; if (misagent_copy(mis, &profiles) == MISAGENT_E_SUCCESS) { uint32_t num_profiles = plist_array_get_size(profiles); printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); uint32_t j; for (j = 0; j < num_profiles; j++) { char* p_name = NULL; char* p_uuid = NULL; plist_t profile = plist_array_get_item(profiles, j); plist_t pl = profile_get_embedded_plist(profile); if (pl && (plist_get_node_type(pl) == PLIST_DICT)) { plist_t node; node = plist_dict_get_item(pl, "Name"); if (node && (plist_get_node_type(node) == PLIST_STRING)) { plist_get_string_val(node, &p_name); } node = plist_dict_get_item(pl, "UUID"); if (node && (plist_get_node_type(node) == PLIST_STRING)) { plist_get_string_val(node, &p_uuid); } } printf("%s - %s\n", (p_uuid) ? p_uuid : "(unknown id)", (p_name) ? p_name : "(no name)"); if (op == OP_COPY) { char pfname[512]; if (p_uuid) { sprintf(pfname, "%s/%s.mobileprovision", param, p_uuid); } else { sprintf(pfname, "%s/profile%d.mobileprovision", param, j); } FILE* f = fopen(pfname, "wb"); if (f) { char* dt = NULL; uint64_t ds = 0; plist_get_data_val(profile, &dt, &ds); fwrite(dt, 1, ds, f); fclose(f); printf(" => %s\n", pfname); } else { fprintf(stderr, "Could not open '%s' for writing\n", pfname); } } if (p_uuid) { free(p_uuid); } if (p_name) { free(p_name); } } } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); } } break; case OP_REMOVE: if (misagent_remove(mis, param) == MISAGENT_E_SUCCESS) { printf("Profile '%s' removed.\n", param); } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not remove profile '%s', status code 0x%x\n", param, sc); } break; default: break; } misagent_client_free(mis); idevice_free(device); return 0; }
int main(int argc, char *argv[]) { int res = -1; idevice_t device = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; instproxy_client_t instproxy_client = NULL; debugserver_client_t debugserver_client = NULL; int i; int debug_level = 0; int cmd = CMD_NONE; const char* udid = NULL; const char* bundle_identifier = NULL; char* path = NULL; char* working_directory = NULL; char **newlist = NULL; char** environment = NULL; int environment_index = 0; int environment_count = 0; char* response = NULL; debugserver_command_t command = NULL; debugserver_error_t dres = DEBUGSERVER_E_UNKNOWN_ERROR; /* map signals */ signal(SIGINT, on_signal); signal(SIGTERM, on_signal); #ifndef WIN32 signal(SIGQUIT, on_signal); signal(SIGPIPE, SIG_IGN); #endif /* parse command line arguments */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { debug_level++; idevice_set_debug_level(debug_level); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); res = 0; goto cleanup; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--env")) { i++; if (!argv[i] || (strlen(argv[i]) <= 1) || strchr(argv[i], '=') == NULL) { print_usage(argc, argv); res = 0; goto cleanup; } /* add environment variable */ if (!newlist) newlist = malloc((environment_count + 1) * sizeof(char*)); else newlist = realloc(environment, (environment_count + 1) * sizeof(char*)); newlist[environment_count++] = strdup(argv[i]); environment = newlist; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); res = 0; goto cleanup; } else if (!strcmp(argv[i], "run")) { cmd = CMD_RUN; i++; if (!argv[i]) { /* make sure at least the bundle identifier was provided */ printf("Please supply the bundle identifier of the app to run.\n"); print_usage(argc, argv); res = 0; goto cleanup; } /* read bundle identifier */ bundle_identifier = argv[i]; break; } else { print_usage(argc, argv); res = 0; goto cleanup; } } if (environment) { newlist = realloc(environment, (environment_count + 1) * sizeof(char*)); newlist[environment_count] = NULL; environment = newlist; } /* verify options */ if (cmd == CMD_NONE) { print_usage(argc, argv); goto cleanup; } /* connect to the device */ ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } goto cleanup; } switch (cmd) { case CMD_RUN: default: /* get the path to the app and it's working directory */ if (instproxy_client_start_service(device, &instproxy_client, "idevicerun") != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not start installation proxy service.\n"); goto cleanup; } plist_t container = NULL; instproxy_client_get_object_by_key_from_info_directionary_for_bundle_identifier(instproxy_client, bundle_identifier, "Container", &container); instproxy_client_get_path_for_bundle_identifier(instproxy_client, bundle_identifier, &path); instproxy_client_free(instproxy_client); instproxy_client = NULL; if (container && (plist_get_node_type(container) == PLIST_STRING)) { plist_get_string_val(container, &working_directory); debug_info("working_directory: %s\n", working_directory); plist_free(container); } else { plist_free(container); fprintf(stderr, "Could not determine container path for bundle identifier %s.\n", bundle_identifier); goto cleanup; } /* start and connect to debugserver */ if (debugserver_client_start_service(device, &debugserver_client, "idevicerun") != DEBUGSERVER_E_SUCCESS) { fprintf(stderr, "Could not start com.apple.debugserver!\n" "Please make sure to mount the developer disk image first:\n" " 1) Get the iOS version from `ideviceinfo -k ProductVersion`.\n" " 2) Find the matching iPhoneOS DeveloperDiskImage.dmg files.\n" " 3) Run `ideviceimagemounter` with the above path.\n"); goto cleanup; } /* enable logging for the session in debug mode */ if (debug_level) { debug_info("Setting logging bitmask..."); debugserver_command_new("QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE|LOG_RNB_PACKETS", 0, NULL, &command); dres = debugserver_client_send_command(debugserver_client, command, &response); debugserver_command_free(command); command = NULL; if (response) { if (strncmp(response, "OK", 2)) { debugserver_client_handle_response(debugserver_client, &response, 0); goto cleanup; } free(response); response = NULL; } } /* set maximum packet size */ debug_info("Setting maximum packet size..."); char* packet_size[2] = {strdup("1024"), NULL}; debugserver_command_new("QSetMaxPacketSize:", 1, packet_size, &command); free(packet_size[0]); dres = debugserver_client_send_command(debugserver_client, command, &response); debugserver_command_free(command); command = NULL; if (response) { if (strncmp(response, "OK", 2)) { debugserver_client_handle_response(debugserver_client, &response, 0); goto cleanup; } free(response); response = NULL; } /* set working directory */ debug_info("Setting working directory..."); char* working_dir[2] = {working_directory, NULL}; debugserver_command_new("QSetWorkingDir:", 1, working_dir, &command); dres = debugserver_client_send_command(debugserver_client, command, &response); debugserver_command_free(command); command = NULL; if (response) { if (strncmp(response, "OK", 2)) { debugserver_client_handle_response(debugserver_client, &response, 0); goto cleanup; } free(response); response = NULL; } /* set environment */ if (environment) { debug_info("Setting environment..."); for (environment_index = 0; environment_index < environment_count; environment_index++) { debug_info("setting environment variable: %s", environment[environment_index]); debugserver_client_set_environment_hex_encoded(debugserver_client, environment[environment_index], NULL); } } /* set arguments and run app */ debug_info("Setting argv..."); i++; /* i is the offset of the bundle identifier, thus skip it */ int app_argc = (argc - i + 2); char **app_argv = (char**)malloc(sizeof(char*) * app_argc); app_argv[0] = path; debug_info("app_argv[%d] = %s", 0, app_argv[0]); app_argc = 1; while (i < argc && argv && argv[i]) { debug_info("app_argv[%d] = %s", app_argc, argv[i]); app_argv[app_argc++] = argv[i]; i++; } app_argv[app_argc] = NULL; debugserver_client_set_argv(debugserver_client, app_argc, app_argv, NULL); free(app_argv); /* check if launch succeeded */ debug_info("Checking if launch succeeded..."); debugserver_command_new("qLaunchSuccess", 0, NULL, &command); dres = debugserver_client_send_command(debugserver_client, command, &response); debugserver_command_free(command); command = NULL; if (response) { if (strncmp(response, "OK", 2)) { debugserver_client_handle_response(debugserver_client, &response, 0); goto cleanup; } free(response); response = NULL; } /* set thread */ debug_info("Setting thread..."); debugserver_command_new("Hc0", 0, NULL, &command); dres = debugserver_client_send_command(debugserver_client, command, &response); debugserver_command_free(command); command = NULL; if (response) { if (strncmp(response, "OK", 2)) { debugserver_client_handle_response(debugserver_client, &response, 0); goto cleanup; } free(response); response = NULL; } /* continue running process */ debug_info("Continue running process..."); debugserver_command_new("c", 0, NULL, &command); dres = debugserver_client_send_command(debugserver_client, command, &response); debugserver_command_free(command); command = NULL; /* main loop which is parsing/handling packets during the run */ debug_info("Entering run loop..."); while (!quit_flag) { if (dres != DEBUGSERVER_E_SUCCESS) { debug_info("failed to receive response"); break; } if (response) { debug_info("response: %s", response); dres = debugserver_client_handle_response(debugserver_client, &response, 1); } sleep(1); } /* kill process after we finished */ debug_info("Killing process..."); debugserver_command_new("k", 0, NULL, &command); dres = debugserver_client_send_command(debugserver_client, command, &response); debugserver_command_free(command); command = NULL; if (response) { if (strncmp(response, "OK", 2)) { debugserver_client_handle_response(debugserver_client, &response, 0); goto cleanup; } free(response); response = NULL; } res = (dres == DEBUGSERVER_E_SUCCESS) ? 0: -1; break; } cleanup: /* cleanup the house */ if (environment) { for (environment_index = 0; environment_index < environment_count; environment_index++) { free(environment[environment_index]); } free(environment); } if (working_directory) free(working_directory); if (path) free(path); if (response) free(response); if (debugserver_client) debugserver_client_free(debugserver_client); if (device) idevice_free(device); return res; }
int main(int argc, char** argv) { int res = -1; char* udid = NULL; int c = 0; int optidx = 0; const struct option longopts[] = { { "udid", required_argument, NULL, 'u' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0} }; while ((c = getopt_long(argc, argv, "du:h", longopts, &optidx)) != -1) { switch (c) { case 'u': udid = strdup(optarg); break; case 'h': print_usage(); return 0; case 'd': idevice_set_debug_level(1); break; default: print_usage(); return -1; } } argc -= optind; argv += optind; if (argc > 1) { print_usage(); return -1; } idevice_t device = NULL; if (idevice_new(&device, udid) != IDEVICE_E_SUCCESS) { fprintf(stderr, "ERROR: Could not connect to device\n"); return -1; } lockdownd_client_t lockdown = NULL; lockdownd_error_t lerr = lockdownd_client_new_with_handshake(device, &lockdown, "idevicename"); if (lerr != LOCKDOWN_E_SUCCESS) { idevice_free(device); fprintf(stderr, "ERROR: lockdown connection failed, lockdown error %d\n", lerr); return -1; } if (argc == 0) { // getting device name char* name = NULL; lerr = lockdownd_get_device_name(lockdown, &name); if (name) { printf("%s\n", name); free(name); res = 0; } else { fprintf(stderr, "ERROR: Could not get device name, lockdown error %d\n", lerr); } } else { // setting device name lerr = lockdownd_set_value(lockdown, NULL, "DeviceName", plist_new_string(argv[0])); if (lerr == LOCKDOWN_E_SUCCESS) { printf("device name set to '%s'\n", argv[0]); res = 0; } else { fprintf(stderr, "ERROR: Could not set device name, lockdown error %d\n", lerr); } } lockdownd_client_free(lockdown); idevice_free(device); if (udid) { free(udid); } return res; }
static void parse_opts(int argc, char **argv) { static struct option longopts[] = { {"help", 0, NULL, 'h'}, {"udid", 1, NULL, 'u'}, {"list-apps", 0, NULL, 'l'}, {"install", 1, NULL, 'i'}, {"uninstall", 1, NULL, 'U'}, {"upgrade", 1, NULL, 'g'}, {"list-archives", 0, NULL, 'L'}, {"archive", 1, NULL, 'a'}, {"restore", 1, NULL, 'r'}, {"remove-archive", 1, NULL, 'R'}, {"options", 1, NULL, 'o'}, {"debug", 0, NULL, 'd'}, {NULL, 0, NULL, 0} }; int c; while (1) { c = getopt_long(argc, argv, "hU:li:u:g:La:r:R:o:d", longopts, (int *) 0); if (c == -1) { break; } /* verify if multiple modes have been supplied */ switch (c) { case 'l': case 'i': case 'g': case 'L': case 'a': case 'r': case 'R': if (cmd != CMD_NONE) { printf("ERROR: A mode has already been supplied. Multiple modes are not supported.\n"); print_usage(argc, argv); exit(2); } break; default: break; } switch (c) { case 'h': print_usage(argc, argv); exit(0); case 'u': if (str_is_udid(optarg) == 0) { udid = strdup(optarg); break; } if (strchr(optarg, '.') != NULL) { fprintf(stderr, "WARNING: Using \"-u\" for \"--uninstall\" is deprecated. Please use \"-U\" instead.\n"); cmd = CMD_UNINSTALL; appid = strdup(optarg); } else { printf("ERROR: Invalid UDID specified\n"); print_usage(argc, argv); exit(2); } break; case 'l': cmd = CMD_LIST_APPS; break; case 'i': cmd = CMD_INSTALL; appid = strdup(optarg); break; case 'U': if (str_is_udid(optarg) == 0) { fprintf(stderr, "WARNING: Using \"-U\" for \"--udid\" is deprecated. Please use \"-u\" instead.\n"); udid = strdup(optarg); break; } cmd = CMD_UNINSTALL; appid = strdup(optarg); break; case 'g': cmd = CMD_UPGRADE; appid = strdup(optarg); break; case 'L': cmd = CMD_LIST_ARCHIVES; break; case 'a': cmd = CMD_ARCHIVE; appid = strdup(optarg); break; case 'r': cmd = CMD_RESTORE; appid = strdup(optarg); break; case 'R': cmd = CMD_REMOVE_ARCHIVE; appid = strdup(optarg); break; case 'o': if (!options) { options = strdup(optarg); } else { char *newopts = malloc(strlen(options) + strlen(optarg) + 2); strcpy(newopts, options); free(options); strcat(newopts, ","); strcat(newopts, optarg); options = newopts; } break; case 'd': idevice_set_debug_level(1); break; default: print_usage(argc, argv); exit(2); } } if (cmd == CMD_NONE) { printf("ERROR: No mode/operation was supplied.\n"); } if (cmd == CMD_NONE || optind <= 1 || (argc - optind > 0)) { print_usage(argc, argv); exit(2); } }