From 30fd56859f50dea5712492807a1b9784da9fec11 Mon Sep 17 00:00:00 2001 From: Joshua Hill Date: Sun, 30 May 2010 03:33:03 -0400 Subject: Implemented a few more events, got rid of the old ones and cleaned up a little --- include/libirecovery.h | 12 ++--- src/irecovery.c | 106 +++++++++++++++++++++----------------- src/libirecovery.c | 136 +++++++++++-------------------------------------- 3 files changed, 94 insertions(+), 160 deletions(-) diff --git a/include/libirecovery.h b/include/libirecovery.h index ab43663..a501c0f 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h @@ -43,7 +43,7 @@ typedef enum { } irecv_error_t; typedef enum { - IRECV_DATA_RECV = 1, + IRECV_RECEIVED = 1, IRECV_PRECOMMAND = 2, IRECV_POSTCOMMAND = 3, IRECV_CONNECTED = 4, @@ -52,16 +52,13 @@ typedef enum { } irecv_event_type; typedef struct { + int size; char* data; irecv_event_type type; } irecv_event_t; struct irecv_client; typedef struct irecv_client* irecv_client_t; - -typedef int(*irecv_send_callback)(irecv_client_t client, unsigned char* data, int size); -typedef int(*irecv_receive_callback)(irecv_client_t client, unsigned char* data, int size); - typedef int(*irecv_event_cb_t)(irecv_client_t client, const irecv_event_t* event); struct irecv_client { @@ -72,8 +69,7 @@ struct irecv_client { unsigned short mode; libusb_context* context; libusb_device_handle* handle; - irecv_send_callback send_callback; - irecv_receive_callback receive_callback; + irecv_event_cb_t received_callback; irecv_event_cb_t precommand_callback; irecv_event_cb_t postcommand_callback; }; @@ -92,8 +88,6 @@ irecv_error_t irecv_send(irecv_client_t client, unsigned char* command); irecv_error_t irecv_send_file(irecv_client_t client, const char* filename); irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command); irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration); -irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback); -irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback); irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface); irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length); const char* irecv_strerror(irecv_error_t error); diff --git a/src/irecovery.c b/src/irecovery.c index d53cf9b..a763272 100644 --- a/src/irecovery.c +++ b/src/irecovery.c @@ -33,25 +33,28 @@ enum { static unsigned int quit = 0; static unsigned int verbose = 0; +int received_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); -void print_shell_usage() { +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/help\t\tShow this help.\n"); printf("\t/exit\t\tExit interactive shell.\n"); } void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) { - char* cmd = strtok(strdup(command), " "); - debug("Executing %s %s\n", cmd, command); + char* cmd = strdup(command); + char* action = strtok(cmd, " "); + debug("Executing %s\n", action); if (!strcmp(cmd, "/exit")) { quit = 1; } else if (!strcmp(cmd, "/help")) { - print_shell_usage(); + shell_usage(); } else if (!strcmp(cmd, "/upload")) { @@ -60,22 +63,18 @@ void parse_command(irecv_client_t client, unsigned char* command, unsigned int s if (filename != NULL) { irecv_send_file(client, filename); } - } - free(cmd); -} + } else -int recv_callback(irecv_client_t client, unsigned char* data, int size) { - int i = 0; - for (i = 0; i < size; i++) { - printf("%c", data[i]); + if (!strcmp(cmd, "/exploit")) { + char* filename = strtok(NULL, " "); + debug("Sending %s\n", filename); + if (filename != NULL) { + irecv_send_file(client, filename); + } + irecv_send_exploit(client); } - return size; -} -int send_callback(irecv_client_t client, unsigned char* command, int size) { - - - return size; + free(action); } void load_command_history() { @@ -90,7 +89,7 @@ void append_command_to_history(char* cmd) { void init_shell(irecv_client_t client) { irecv_error_t error = 0; load_command_history(); - irecv_set_receiver(client, &recv_callback); + 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) { @@ -113,49 +112,64 @@ void init_shell(irecv_client_t client) { } } -void print_usage() { - printf("iRecovery - iDevice Recovery Utility\n"); - printf("Usage: ./irecovery [args]\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 [exploit]\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"); - exit(1); +int received_cb(irecv_client_t client, const irecv_event_t* event) { + if (event->type == IRECV_RECEIVED) { + int i = 0; + int size = event->size; + 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) { - irecv_error_t error = 0; - if (event->data[0] == '/') { - parse_command(client, event->data, strlen(event->data)); - return -1; + if (event->type == IRECV_PRECOMMAND) { + irecv_error_t error = 0; + if (event->data[0] == '/') { + parse_command(client, event->data, event->size); + return -1; + } } return 0; } int postcommand_cb(irecv_client_t client, const irecv_event_t* event) { - irecv_error_t error = 0; - if (strstr(event->data, "getenv") != NULL) { - unsigned char* value = NULL; - error = irecv_getenv(client, &value); - if (error != IRECV_E_SUCCESS) { - debug("%s\n", irecv_strerror(error)); - return error; + unsigned char* value = NULL; + if (event->type == IRECV_POSTCOMMAND) { + irecv_error_t error = 0; + if (strstr(event->data, "getenv") != NULL) { + error = irecv_getenv(client, &value); + if (error != IRECV_E_SUCCESS) { + debug("%s\n", irecv_strerror(error)); + return error; + } + printf("%s\n", value); } - printf("%s\n", value); - free(value); - } - - if (!strcmp(event->data, "reboot")) { - quit = 1; + if (!strcmp(event->data, "reboot")) { + quit = 1; + } } + if (value != NULL) free(value); return 0; } +void print_usage() { + printf("iRecovery - iDevice Recovery Utility\n"); + printf("Usage: ./irecovery [args]\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"); + exit(1); +} + int main(int argc, char** argv) { int i = 0; int opt = 0; diff --git a/src/libirecovery.c b/src/libirecovery.c index 8f029ed..a641562 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -27,9 +27,6 @@ #define BUFFER_SIZE 0x1000 #define debug(...) if(client->debug) fprintf(stderr, __VA_ARGS__) -int irecv_default_sender(irecv_client_t client, unsigned char* data, int size); -int irecv_default_receiver(irecv_client_t client, unsigned char* data, int size); - irecv_error_t irecv_open(irecv_client_t* pclient) { int i = 0; char serial[256]; @@ -41,7 +38,6 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { *pclient = NULL; libusb_init(&usb_context); - //libusb_init(NULL); irecv_error_t error = IRECV_E_SUCCESS; int usb_device_count = libusb_get_device_list(usb_context, &usb_device_list); for (i = 0; i < usb_device_count; i++) { @@ -49,10 +45,11 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { libusb_get_device_descriptor(usb_device, &usb_descriptor); if (usb_descriptor.idVendor == APPLE_VENDOR_ID) { /* verify this device is in a mode we understand */ - if (usb_descriptor.idProduct == kRecoveryMode1 || usb_descriptor.idProduct - == kRecoveryMode2 || usb_descriptor.idProduct == kRecoveryMode3 - || usb_descriptor.idProduct == kRecoveryMode4 || usb_descriptor.idProduct - == kDfuMode) { + if (usb_descriptor.idProduct == kRecoveryMode1 || + usb_descriptor.idProduct == kRecoveryMode2 || + usb_descriptor.idProduct == kRecoveryMode3 || + usb_descriptor.idProduct == kRecoveryMode4 || + usb_descriptor.idProduct == kDfuMode) { libusb_open(usb_device, &usb_handle); if (usb_handle == NULL) { @@ -61,8 +58,6 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { libusb_exit(usb_context); return IRECV_E_UNABLE_TO_CONNECT; } - libusb_set_debug(usb_context, 3); - libusb_free_device_list(usb_device_list, 1); irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client)); @@ -71,6 +66,7 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { libusb_exit(usb_context); return IRECV_E_OUT_OF_MEMORY; } + memset(client, '\0', sizeof(struct irecv_client)); client->interface = 0; client->handle = usb_handle; @@ -150,6 +146,10 @@ irecv_error_t irecv_reset(irecv_client_t client) { irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type, irecv_event_cb_t callback, void* user_data) { switch(type) { + case IRECV_RECEIVED: + client->received_callback = callback; + break; + case IRECV_PRECOMMAND: client->precommand_callback = callback; break; @@ -167,6 +167,10 @@ irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type) { switch(type) { + case IRECV_RECEIVED: + client->received_callback = NULL; + break; + case IRECV_PRECOMMAND: client->precommand_callback = NULL; break; @@ -185,7 +189,7 @@ irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type ty irecv_error_t irecv_close(irecv_client_t client) { if (client != NULL) { if (client->handle != NULL) { - libusb_release_interface(client->handle, 1); + libusb_release_interface(client->handle, client->interface); libusb_close(client->handle); client->handle = NULL; } @@ -212,39 +216,11 @@ irecv_error_t irecv_set_debug(irecv_client_t client, int level) { return IRECV_E_SUCCESS; } -irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) { - if (client == NULL || client->handle == NULL) { - return IRECV_E_NO_DEVICE; - } - - unsigned int length = strlen(command); - if (length >= 0x100) { - length = 0xFF; - } - - if (client->send_callback != NULL) { - // Call our user defined callback first, this must return a number of bytes to send - // or zero to abort send. - length = client->send_callback(client, command, length); - } - - if (length > 0) { - irecv_send_command(client, command); - } - - return IRECV_E_SUCCESS; -} - irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) { if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } - /* - irecv_error_t error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - */ + unsigned int length = strlen(command); if (length >= 0x100) { length = 0xFF; @@ -252,6 +228,7 @@ irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) irecv_event_t event; if(client->precommand_callback != NULL) { + event.size = length; event.data = command; event.type = IRECV_PRECOMMAND; if(client->precommand_callback(client, &event)) { @@ -264,6 +241,7 @@ irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) } if(client->postcommand_callback != NULL) { + event.size = length; event.data = command; event.type = IRECV_POSTCOMMAND; if(client->postcommand_callback(client, &event)) { @@ -312,12 +290,7 @@ irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) { *status = 0; return IRECV_E_NO_DEVICE; } - /* - irecv_error_t error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - */ + unsigned char buffer[6]; memset(buffer, '\0', 6); if (libusb_control_transfer(client->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) { @@ -335,12 +308,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } - /* - error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - */ + int last = length % 0x800; int packets = length / 0x800; if (last != 0) { @@ -387,54 +355,22 @@ irecv_error_t irecv_receive(irecv_client_t client) { if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } - /* - irecv_error_t error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - */ + int bytes = 0; while (libusb_bulk_transfer(client->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) { if (bytes > 0) { - if (client->receive_callback != NULL) { - if (client->receive_callback(client, buffer, bytes) != bytes) { - return IRECV_E_UNKNOWN_ERROR; + if (client->received_callback != NULL) { + irecv_event_t event; + event.size = bytes; + event.data = buffer; + event.type = IRECV_RECEIVED; + if (client->received_callback(client, &event) != 0) { + return IRECV_E_SUCCESS; } } - } else - break; - } - - return IRECV_E_SUCCESS; -} - -int irecv_default_sender(irecv_client_t client, unsigned char* data, int size) { - return size; -} - -int irecv_default_receiver(irecv_client_t client, unsigned char* data, int size) { - int i = 0; - for (i = 0; i < size; i++) { - printf("%c", data[i]); - } - return size; -} - -irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback) { - if (client == NULL) { - return IRECV_E_NO_DEVICE; - } - - client->receive_callback = callback; - return IRECV_E_SUCCESS; -} - -irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback) { - if (client == NULL) { - return IRECV_E_NO_DEVICE; + } else break; } - client->send_callback = callback; return IRECV_E_SUCCESS; } @@ -442,12 +378,7 @@ irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) { if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } - /* - irecv_error_t error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - */ + unsigned char* value = (unsigned char*) malloc(256); if (value == NULL) { return IRECV_E_OUT_OF_MEMORY; @@ -488,12 +419,7 @@ irecv_error_t irecv_send_exploit(irecv_client_t client) { if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } - /* - irecv_error_t error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - */ + libusb_control_transfer(client->handle, 0x21, 2, 0, 0, NULL, 0, 100); return IRECV_E_SUCCESS; } -- cgit v1.1-32-gdbae