diff options
| author | 2010-05-30 03:33:03 -0400 | |
|---|---|---|
| committer | 2010-05-30 03:33:03 -0400 | |
| commit | 30fd56859f50dea5712492807a1b9784da9fec11 (patch) | |
| tree | 66b3c2569616315cbfa843f23a5c192b38255be5 | |
| parent | 1e4d65033781cd44876b7b2634976259e4bef7c5 (diff) | |
| download | libirecovery-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.h | 12 | ||||
| -rw-r--r-- | src/irecovery.c | 106 | ||||
| -rw-r--r-- | 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 <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;  } | 
