From 9099c5d9e28ca6348fc1b0431f47e2592649ae84 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Thu, 26 Sep 2013 09:45:58 +0200 Subject: Move irecovery to new tools directory --- tools/irecovery.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 tools/irecovery.c (limited to 'tools/irecovery.c') diff --git a/tools/irecovery.c b/tools/irecovery.c new file mode 100644 index 0000000..075ee79 --- /dev/null +++ b/tools/irecovery.c @@ -0,0 +1,400 @@ +/* + * irecovery.c - software frontend for iBoot/iBSS communication for iOS devices + * + * Copyright (c) 2012-2013 Martin Szulecki + * Copyright (c) 2010-2011 Chronic-Dev Team + * Copyright (c) 2010-2011 Joshua Hill + * Copyright (c) 2008-2011 Nicolas Haunold + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public License + * (LGPL) version 2.1 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl-2.1.html + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define FILE_HISTORY_PATH ".irecovery" +#define debug(...) if(verbose) fprintf(stderr, __VA_ARGS__) + +enum { + kResetDevice, kStartShell, kSendCommand, kSendFile, kSendExploit, kSendScript +}; + +static unsigned int quit = 0; +static unsigned int verbose = 0; + +void print_progress_bar(double progress); +int received_cb(irecv_client_t client, const irecv_event_t* event); +int progress_cb(irecv_client_t client, const irecv_event_t* event); +int precommand_cb(irecv_client_t client, const irecv_event_t* event); +int postcommand_cb(irecv_client_t client, const irecv_event_t* event); + +static void shell_usage() { + printf("Usage:\n"); + printf("\t/upload \tSend file to client.\n"); + printf("\t/exploit [file]\tSend usb exploit with optional payload\n"); + printf("\t/deviceinfo\tShow device information (ECID, IMEI, etc.)\n"); + printf("\t/help\t\tShow this help.\n"); + printf("\t/exit\t\tExit interactive shell.\n"); +} + +static void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) { + char* cmd = strdup((char*)command); + char* action = strtok(cmd, " "); + debug("Executing %s\n", action); + if (!strcmp(cmd, "/exit")) { + quit = 1; + } else + + if (!strcmp(cmd, "/help")) { + shell_usage(); + } else + + if (!strcmp(cmd, "/upload")) { + char* filename = strtok(NULL, " "); + debug("Uploading files %s\n", filename); + if (filename != NULL) { + irecv_send_file(client, filename, 0); + } + } else + + if (!strcmp(cmd, "/deviceinfo")) { + int ret; + unsigned int cpid, bdid; + unsigned long long ecid; + char srnm[12], imei[15]; + + ret = irecv_get_cpid(client, &cpid); + if(ret == IRECV_E_SUCCESS) { + printf("CPID: %d\n", cpid); + } + + ret = irecv_get_bdid(client, &bdid); + if(ret == IRECV_E_SUCCESS) { + printf("BDID: %d\n", bdid); + } + + ret = irecv_get_ecid(client, &ecid); + if(ret == IRECV_E_SUCCESS) { + printf("ECID: %lld\n", ecid); + } + + ret = irecv_get_srnm(client, srnm); + if(ret == IRECV_E_SUCCESS) { + printf("SRNM: %s\n", srnm); + } + + ret = irecv_get_imei(client, imei); + if(ret == IRECV_E_SUCCESS) { + printf("IMEI: %s\n", imei); + } + } else + + if (!strcmp(cmd, "/exploit")) { + char* filename = strtok(NULL, " "); + debug("Sending exploit %s\n", filename); + if (filename != NULL) { + irecv_send_file(client, filename, 0); + } + irecv_send_exploit(client); + } else + + if (!strcmp(cmd, "/execute")) { + char* filename = strtok(NULL, " "); + debug("Executing script %s\n", filename); + if (filename != NULL) { + irecv_execute_script(client, filename); + } + } + + + free(action); +} + +static void load_command_history() { + read_history(FILE_HISTORY_PATH); +} + +static void append_command_to_history(char* cmd) { + add_history(cmd); + write_history(FILE_HISTORY_PATH); +} + +static void init_shell(irecv_client_t client) { + irecv_error_t error = 0; + load_command_history(); + irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL); + irecv_event_subscribe(client, IRECV_RECEIVED, &received_cb, NULL); + irecv_event_subscribe(client, IRECV_PRECOMMAND, &precommand_cb, NULL); + irecv_event_subscribe(client, IRECV_POSTCOMMAND, &postcommand_cb, NULL); + while (!quit) { + error = irecv_receive(client); + + if (error != IRECV_E_SUCCESS) { + debug("%s\n", irecv_strerror(error)); + break; + } + + char* cmd = readline("> "); + if (cmd && *cmd) { + error = irecv_send_command(client, cmd); + if (error != IRECV_E_SUCCESS) { + quit = 1; + } + + append_command_to_history(cmd); + free(cmd); + } + } +} + +int received_cb(irecv_client_t client, const irecv_event_t* event) { + if (event->type == IRECV_RECEIVED) { + int i = 0; + int size = event->size; + const char* data = event->data; + for (i = 0; i < size; i++) { + printf("%c", data[i]); + } + } + return 0; +} + +int precommand_cb(irecv_client_t client, const irecv_event_t* event) { + if (event->type == IRECV_PRECOMMAND) { + if (event->data[0] == '/') { + parse_command(client, (unsigned char*)event->data, event->size); + return -1; + } + } + return 0; +} + +int postcommand_cb(irecv_client_t client, const irecv_event_t* event) { + char* value = NULL; + char* action = NULL; + char* command = NULL; + char* argument = NULL; + irecv_error_t error = IRECV_E_SUCCESS; + + if (event->type == IRECV_POSTCOMMAND) { + command = strdup(event->data); + action = strtok(command, " "); + if (!strcmp(action, "getenv")) { + argument = strtok(NULL, " "); + error = irecv_getenv(client, argument, &value); + if (error != IRECV_E_SUCCESS) { + debug("%s\n", irecv_strerror(error)); + free(command); + return error; + } + printf("%s\n", value); + free(value); + } + + if (!strcmp(action, "reboot")) { + quit = 1; + } + } + + if (command) free(command); + return 0; +} + +int progress_cb(irecv_client_t client, const irecv_event_t* event) { + if (event->type == IRECV_PROGRESS) { + print_progress_bar(event->progress); + } + return 0; +} + +void print_progress_bar(double progress) { + int i = 0; + if(progress < 0) { + return; + } + + if(progress > 100) { + progress = 100; + } + + printf("\r["); + for(i = 0; i < 50; i++) { + if(i < progress / 2) { + printf("="); + } else { + printf(" "); + } + } + + printf("] %3.1f%%", progress); + fflush(stdout); + if(progress == 100) { + printf("\n"); + } +} + +static void print_usage() { + printf("iRecovery - iDevice Recovery Utility\n"); + printf("Usage: irecovery [args]\n"); + printf("\t-i \tTarget specific device by its hexadecimal ECID\n"); + printf("\t-v\t\tStart irecovery in verbose mode.\n"); + printf("\t-c \tSend command to client.\n"); + printf("\t-f \tSend file to client.\n"); + printf("\t-k [payload]\tSend usb exploit to client.\n"); + printf("\t-h\t\tShow this help.\n"); + printf("\t-r\t\tReset client.\n"); + printf("\t-s\t\tStart interactive shell.\n"); + printf("\t-e