summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-05-30 03:33:03 -0400
committerGravatar Joshua Hill2010-05-30 03:33:03 -0400
commit30fd56859f50dea5712492807a1b9784da9fec11 (patch)
tree66b3c2569616315cbfa843f23a5c192b38255be5
parent1e4d65033781cd44876b7b2634976259e4bef7c5 (diff)
downloadlibirecovery-30fd56859f50dea5712492807a1b9784da9fec11.tar.gz
libirecovery-30fd56859f50dea5712492807a1b9784da9fec11.tar.bz2
Implemented a few more events, got rid of the old ones and cleaned up a little
-rw-r--r--include/libirecovery.h12
-rw-r--r--src/irecovery.c106
-rw-r--r--src/libirecovery.c136
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 <file>\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 <cmd>\tSend command to client.\n");
- printf("\t-f <file>\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 <cmd>\tSend command to client.\n");
+ printf("\t-f <file>\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;
}