Ejemplo n.º 1
0
int copyAcrossVolumes(Volume* volume1, Volume* volume2, char* path1, char* path2) {
	void* buffer;
	size_t bufferSize;
	AbstractFile* tmpFile;
	int ret;
	
	buffer = malloc(1);
	bufferSize = 0;
	tmpFile = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize);
	
	if(!silence)
	{
		printf("retrieving... "); fflush(stdout);
	}

	get_hfs(volume1, path1, tmpFile);
	tmpFile->seek(tmpFile, 0);

	if(!silence)
	{
		printf("writing (%ld)... ", (long) tmpFile->getLength(tmpFile)); fflush(stdout);
	}

	ret = add_hfs(volume2, tmpFile, path2);

	if(!silence)
	{
		printf("done\n");
	}
	
	free(buffer);
	
	return ret;
}
Ejemplo n.º 2
0
int xpwntool_enc_dec(char* srcName, char* destName, char* templateFileName, char* ivStr, char* keyStr)
{
	char* inData;
	size_t inDataSize;

	AbstractFile* templateFile = NULL;
	unsigned int* key = NULL;
	unsigned int* iv = NULL;
	int hasKey = TRUE;
	int hasIV = TRUE;

	if (templateFileName != NULL && strlen(templateFileName) != 0) {
		templateFile = createAbstractFileFromFile(fopen(templateFileName, "rb"));
		if(!templateFile) {
			fprintf(stderr, "error: cannot open template\n");
			return 1;
		}
	}

	size_t bytes;
	hexToInts(keyStr, &key, &bytes);
	if (bytes == 0) {
		free(key);
		key = NULL;
	} else {
		hexToInts(ivStr, &iv, &bytes);
	}

	AbstractFile* inFile;
	inFile = openAbstractFile2(createAbstractFileFromFile(fopen(srcName, "rb")), key, iv);
	if(!inFile) {
		fprintf(stderr, "error: cannot open infile\n");
		return 2;
	}

	AbstractFile* outFile = createAbstractFileFromFile(fopen(destName, "wb"));
	if(!outFile) {
		fprintf(stderr, "error: cannot open outfile\n");
		return 3;
	}


	AbstractFile* newFile;

	if(templateFile) {
		newFile = duplicateAbstractFile2(templateFile, outFile, key, iv, NULL);
		if(!newFile) {
			fprintf(stderr, "error: cannot duplicate file from provided template\n");
			return 4;
		}
	} else {
		newFile = outFile;
	}
	 
	if(newFile->type == AbstractFileTypeImg3) {
		AbstractFile2* abstractFile2 = (AbstractFile2*) newFile;
		if (key != NULL) {
			abstractFile2->setKey(abstractFile2, key, iv);
		}
	}

	inDataSize = (size_t) inFile->getLength(inFile);
	inData = (char*) malloc(inDataSize);
	inFile->read(inFile, inData, inDataSize);
	inFile->close(inFile);

	newFile->write(newFile, inData, inDataSize);
	newFile->close(newFile);

	free(inData);

	if(key)
		free(key);

	if(iv)
		free(iv);

	return 0;
}
Ejemplo n.º 3
0
int doDecrypt(StringValue* decryptValue, StringValue* fileValue, const char* bundlePath, OutputState** state, unsigned int* key, unsigned int* iv, int useMemory) {
	size_t bufferSize;
	void* buffer;
	
	AbstractFile* file;
	AbstractFile* out;
	AbstractFile* outRaw;

	char* tmpFileName;

	if(useMemory) {
		bufferSize = 0;
		buffer = malloc(1);
		outRaw = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize);
	} else {
		tmpFileName = createTempFile();
		outRaw = createAbstractFileFromFile(fopen(tmpFileName, "wb"));
	}

	out = duplicateAbstractFile(getFileFromOutputState(state, fileValue->value), outRaw);
	file = openAbstractFile3(getFileFromOutputState(state, fileValue->value), key, iv, 0);
	
	if(!file || !out) {
		XLOG(0, "file error\n");
		exit(0);
	}

	char *buf = malloc(1024 * 1024);
	off_t inDataSize = file->getLength(file);
	while (inDataSize > 0) {
		off_t avail, chunk = 1024 * 1024;
		if (chunk > inDataSize) {
			chunk = inDataSize;
		}
		if (chunk < 0) {
			XLOG(0, "decrypt failed\n");
			exit(0);
		}
		avail = file->read(file, buf, chunk);
		out->write(out, buf, avail);
		if (avail < chunk) {
			break;
		}
		inDataSize -= chunk;
	}
	out->close(out);
	file->close(file);
	free(buf);

	XLOG(0, "writing... "); fflush(stdout);
	
	if (decryptValue) {
		fileValue = decryptValue;
	}
	if(useMemory) {
		addToOutput(state, fileValue->value, buffer, bufferSize);
	} else {
		outRaw = createAbstractFileFromFile(fopen(tmpFileName, "rb"));
		size_t length = outRaw->getLength(outRaw);
		outRaw->close(outRaw);
		addToOutput2(state, fileValue->value, NULL, length, tmpFileName);
	}

	XLOG(0, "success\n"); fflush(stdout);

	return 0;
}
Ejemplo n.º 4
0
int doPatch(StringValue* patchValue, StringValue* fileValue, const char* bundlePath, OutputState** state, unsigned int* key, unsigned int* iv, int useMemory, int isPlain) {
	char* patchPath;
	size_t bufferSize;
	void* buffer;
	
	AbstractFile* patchFile;
	AbstractFile* file;
	AbstractFile* out;
	AbstractFile* outRaw;

	char* tmpFileName;

	if(useMemory) {
		bufferSize = 0;
		buffer = malloc(1);
		outRaw = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize);
	} else {
		tmpFileName = createTempFile();
		outRaw = createAbstractFileFromFile(fopen(tmpFileName, "wb"));
	}
			
	patchPath = malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2));
	strcpy(patchPath, bundlePath);
	strcat(patchPath, "/");
	strcat(patchPath, patchValue->value);
	
	XLOG(0, "%s (%s)... ", fileValue->value, patchPath); fflush(stdout);
	
	patchFile = createAbstractFileFromFile(fopen(patchPath, "rb"));

	if (isPlain) {
		out = outRaw;
		file = getFileFromOutputState(state, fileValue->value);
	} else {
		if(key != NULL) {
			XLOG(0, "encrypted input... ");
			out = duplicateAbstractFile2(getFileFromOutputState(state, fileValue->value), outRaw, key, iv, NULL);
		} else {
			out = duplicateAbstractFile(getFileFromOutputState(state, fileValue->value), outRaw);
		}

		if(key != NULL) {
			XLOG(0, "encrypted output... ");
			file = openAbstractFile2(getFileFromOutputState(state, fileValue->value), key, iv);
		} else {
			file = openAbstractFile(getFileFromOutputState(state, fileValue->value));
		}
	}
	
	if(!patchFile || !file || !out) {
		XLOG(0, "file error\n");
		exit(0);
	}

	if(patch(file, out, patchFile) != 0) {
		XLOG(0, "patch failed\n");
		exit(0);
	}

	if(strstr(fileValue->value, "WTF.s5l8900xall.RELEASE")) {
		XLOG(0, "Exploiting 8900 vulnerability... ;)\n");
		AbstractFile* exploited;
		if(useMemory) {
			exploited = createAbstractFileFrom8900(createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize));
		} else {
			exploited = createAbstractFileFrom8900(createAbstractFileFromFile(fopen(tmpFileName, "r+b")));
		}
		exploit8900(exploited);
		exploited->close(exploited);
	}
	
	XLOG(0, "writing... "); fflush(stdout);
	
	if(useMemory) {
		addToOutput(state, fileValue->value, buffer, bufferSize);
	} else {
		outRaw = createAbstractFileFromFile(fopen(tmpFileName, "rb"));
		size_t length = outRaw->getLength(outRaw);
		outRaw->close(outRaw);
		addToOutput2(state, fileValue->value, NULL, length, tmpFileName);
	}

	XLOG(0, "success\n"); fflush(stdout);

	free(patchPath);

	return 0;
}
Ejemplo n.º 5
0
Dictionary* parseIPSW2(const char* inputIPSW, const char* bundleRoot, char** bundlePath, OutputState** state, int useMemory) {
	Dictionary* info;
	char* infoPath;

	AbstractFile* plistFile;
	char* plist;
	FILE* inputIPSWFile;

	SHA_CTX sha1_ctx;
	char* buffer;
	int read;
	unsigned char hash[20];

	DIR* dir;
	struct dirent* ent;
	StringValue* plistSHA1String;
	unsigned int plistHash[20];
	int i;

	*bundlePath = NULL;

	inputIPSWFile = fopen(inputIPSW, "rb");
	if(!inputIPSWFile) {
		return NULL;
	}

	XLOG(0, "Hashing IPSW...\n");

	buffer = malloc(BUFFERSIZE);
	SHA1_Init(&sha1_ctx);
	while(!feof(inputIPSWFile)) {
		read = fread(buffer, 1, BUFFERSIZE, inputIPSWFile);
		SHA1_Update(&sha1_ctx, buffer, read);
	}
	SHA1_Final(hash, &sha1_ctx);
	free(buffer);

	fclose(inputIPSWFile);

	XLOG(0, "Matching IPSW in %s... (%02x%02x%02x%02x...)\n", bundleRoot, (int) hash[0], (int) hash[1], (int) hash[2], (int) hash[3]);

	dir = opendir(bundleRoot);
	if(dir == NULL) {
		XLOG(1, "Bundles directory not found\n");
		return NULL;
	}

	while((ent = readdir(dir)) != NULL) {
		if(ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) {
			continue;
		}

		infoPath = (char*) malloc(sizeof(char) * (strlen(bundleRoot) + sizeof(PATH_SEPARATOR) + strlen(ent->d_name) + sizeof(PATH_SEPARATOR "Info.plist")));
		sprintf(infoPath, "%s" PATH_SEPARATOR "%s" PATH_SEPARATOR "Info.plist", bundleRoot, ent->d_name);
		XLOG(0, "checking: %s\n", infoPath);

		if((plistFile = createAbstractFileFromFile(fopen(infoPath, "rb"))) != NULL) {
			plist = (char*) malloc(plistFile->getLength(plistFile));
			plistFile->read(plistFile, plist, plistFile->getLength(plistFile));
			plistFile->close(plistFile);
			info = createRoot(plist);
			free(plist);

			plistSHA1String = (StringValue*)getValueByKey(info, "SHA1");
			if(plistSHA1String) {
				sscanf(plistSHA1String->value, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
					&plistHash[0], &plistHash[1], &plistHash[2], &plistHash[3], &plistHash[4],
					&plistHash[5], &plistHash[6], &plistHash[7], &plistHash[8], &plistHash[9],
					&plistHash[10], &plistHash[11], &plistHash[12], &plistHash[13], &plistHash[14],
					&plistHash[15], &plistHash[16], &plistHash[17], &plistHash[18], &plistHash[19]);

				for(i = 0; i < 20; i++) {
					if(plistHash[i] != hash[i]) {
						break;
					}
				}

				if(i == 20) {
					*bundlePath = (char*) malloc(sizeof(char) * (strlen(bundleRoot) + sizeof(PATH_SEPARATOR) + strlen(ent->d_name)));
					sprintf(*bundlePath, "%s" PATH_SEPARATOR "%s", bundleRoot, ent->d_name);

					free(infoPath);
					break;
				}
			}

			releaseDictionary(info);
		}

		free(infoPath);
	}

	closedir(dir);

	if(*bundlePath == NULL) {
		return NULL;
	}

	*state = loadZip2(inputIPSW, useMemory);

	return info;
}
Ejemplo n.º 6
0
int convertToPNG(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, const char* png) {
	AbstractFile* imageFile;

	FILE *fp = fopen(png, "wb");
	if(!fp)
		return -1;

	if(key != NULL) {
		imageFile = openAbstractFile2(imageWrapper, key, iv);
	} else {	
		imageFile = openAbstractFile(imageWrapper);
	}
	InfoIBootIM* info = (InfoIBootIM*) (imageFile->data);

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn);
	if (!png_ptr) {
		return -1;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return -1;
	}

	png_init_io(png_ptr, fp);

	int color_type;
	int bytes_per_pixel;

	if(info->header.format == IBOOTIM_ARGB) {
		XLOG(3, "ARGB");
		color_type = PNG_COLOR_TYPE_RGB_ALPHA;
		bytes_per_pixel = 4;
	} else if(info->header.format == IBOOTIM_GREY) {
		XLOG(3, "Grayscale");
		color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
		bytes_per_pixel = 2;
	} else {
		XLOG(3, "Unknown color type!");
	}

	png_set_IHDR(png_ptr, info_ptr, info->header.width, info->header.height,
		     8, color_type, PNG_INTERLACE_NONE,
		     PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	png_set_bgr(png_ptr);
	png_set_invert_alpha(png_ptr);

	png_write_info(png_ptr, info_ptr);


	void* imageBuffer = malloc(imageFile->getLength(imageFile));
	imageFile->read(imageFile, imageBuffer, imageFile->getLength(imageFile));

	png_bytepp row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * info->header.height);
	int i;
	for(i = 0; i < png_get_image_height(png_ptr, info_ptr); i++) {
		row_pointers[i] = imageBuffer + (info->header.width * bytes_per_pixel * i);
	}

	png_write_image(png_ptr, row_pointers);

	png_write_end(png_ptr, NULL);

	free(imageBuffer);

	return 0;
}
Ejemplo n.º 7
0
int main(int argc, char* argv[])
{
	struct stat st;

	init_libxpwn(&argc, argv);
	libxpwn_log(logCB);
	libxpwn_loglevel(2);

	printf("---------------------------PLEASE READ THIS---------------------------\n");
	printf("Please make certain that all iTunes related processes are not running\n");
	printf("at this time (use Task Manager, etc. to end them).\n");
	printf("---------------------------PLEASE READ THIS---------------------------\n\n\n");

	if(argc < 3) {
		printf("usage: %s <custom.ipsw> <n82ap|m68ap|n45ap> [loglevel]\n", argv[0]);
		printf("n82ap = 3G iPhone, m68ap = First-generation iPhone, n45ap = iPod touch\n");
		return 0;
	}

	if(argc >= 4) {
		int logLevel;
		sscanf(argv[3], "%d", &logLevel);
		libxpwn_loglevel(logLevel);
	}

	if(stat("restore.img3", &st) < 0) {
		fprintf(stderr, "missing restore.img3\n");
		return 1;
	}

	Stage = 0;
	Status = Disconnected;

	char ibssName[100];
	char wtfName[100];
	sprintf(ibssName, "Firmware/dfu/iBSS.%s.RELEASE.dfu", argv[2]);
	sprintf(wtfName, "Firmware/dfu/WTF.%s.RELEASE.dfu", argv[2]);

	data = NULL;
	loadZipFile(argv[1], &data, "Firmware/dfu/WTF.s5l8900xall.RELEASE.dfu");
	loadZipFile(argv[1], &data, ibssName);
	loadZipFile(argv[1], &data, wtfName);
	loadZipFile(argv[1], &data, "Restore.plist");

	AbstractFile* xallFile = getFileFromOutputState(&data, "Firmware/dfu/WTF.s5l8900xall.RELEASE.dfu");
	AbstractFile* wtfFile = getFileFromOutputState(&data, wtfName);
	AbstractFile* ibssFile = getFileFromOutputState(&data, ibssName);
	AbstractFile* restoreFile = getFileFromOutputState(&data, "Restore.plist");

	GetTempPath(MAX_PATH, tmpFilePath);

	strcat(tmpFilePath, "/restore");
	if(stat(tmpFilePath, &st) < 0) {
		mkdir(tmpFilePath, 0755);
	}

	strcpy(tmpFirmwarePath, tmpFilePath);
	strcat(tmpFirmwarePath, "/Firmware");
	if(stat(tmpFirmwarePath, &st) < 0) {
		mkdir(tmpFirmwarePath, 0755);
	}

	strcpy(tmpDFUPath, tmpFirmwarePath);
	strcat(tmpDFUPath, "/dfu");
	if(stat(tmpDFUPath, &st) < 0) {
		mkdir(tmpDFUPath, 0755);
	}

	strcpy(tmpXALLPath, tmpFilePath);
	strcat(tmpXALLPath, "/");
	strcat(tmpXALLPath, "Firmware/dfu/WTF.s5l8900xall.RELEASE.dfu");

	strcpy(tmpWTFPath, tmpFilePath);
	strcat(tmpWTFPath, "/");
	strcat(tmpWTFPath, wtfName);

	strcpy(tmpIBSSPath, tmpFilePath);
	strcat(tmpIBSSPath, "/");
	strcat(tmpIBSSPath, ibssName);

	strcpy(tmpRestorePath, tmpFilePath);
	strcat(tmpRestorePath, "/");
	strcat(tmpRestorePath, "Restore.plist");

	FILE* file;
	void* buffer;
	size_t length;

	length = xallFile->getLength(xallFile);
	buffer = malloc(length);
	xallFile->read(xallFile, buffer, length);
       	file = fopen(tmpXALLPath, "wb");
	fwrite(buffer, 1, length, file);
	fclose(file);
	free(buffer);
	xallFile->close(xallFile);

	length = wtfFile->getLength(wtfFile);
	buffer = malloc(length);
	wtfFile->read(wtfFile, buffer, length);
       	file = fopen(tmpWTFPath, "wb");
	fwrite(buffer, 1, length, file);
	fclose(file);
	free(buffer);
	wtfFile->close(wtfFile);

	length = ibssFile->getLength(ibssFile);
	buffer = malloc(length);
	ibssFile->read(ibssFile, buffer, length);
       	file = fopen(tmpIBSSPath, "wb");
	fwrite(buffer, 1, length, file);
	fclose(file);
	free(buffer);
	ibssFile->close(ibssFile);

	extractedIPSWPath = argv[1];
	length = restoreFile->getLength(restoreFile);
	buffer = malloc(length);
	restoreFile->read(restoreFile, buffer, length);
       	file = fopen(tmpRestorePath, "wb");
	fwrite(buffer, 1, length, file);
	fclose(file);
	free(buffer);
	restoreFile->close(restoreFile);

	extractedIPSWPath = tmpFilePath;
	bootImagePath = "restore.img3";

	fprintf(stdout, "\nGetting iPhone/iPod status...\n");
	fflush(stdout);

	if(LoadWindowsDLL() < 0) {
		printf("Failed to load iTunes Mobile Device driver!\n");
		cleanup_and_exit();
	}
	
	mach_error_t ret;
	struct am_device_notification *notif; 
	
	ret = AMDeviceNotificationSubscribe(notification, 0, 0, 0, &notif);
	if(ret < 0) {
		printf("Failed to subscribe for device notifications!\n");
		cleanup_and_exit();
	}
	
	ret = AMRestoreRegisterForDeviceNotifications(
						dfu_connect_callback,
						recovery_connect_callback,
						dfu_disconnect_callback,
						recovery_disconnect_callback,
						0,
						NULL);
						
	if(ret < 0) {
		printf("Failed to subscribe for device restore notifications!\n");
		cleanup_and_exit();
	}


	sleep(2);

	char responseBuffer[10];
	int countdown;

	if(Status == Disconnected) {
connectDevice:
		fprintf(stdout, "Is your iPhone/iPod connected to your computer via USB?\n");
		fprintf(stdout, "Please answer (y/n): ");
		fflush(stdout);
		fgets(responseBuffer, 10, stdin);
		if(responseBuffer[0] == 'y' || responseBuffer[0] == 'Y') {
			goto isPoweringOn;
		} else if(responseBuffer[0] == 'n' || responseBuffer[0] == 'N') {
			fprintf(stdout, "Please connect your iPhone/iPod to your computer\n");
			fprintf(stdout, "Press enter when you have connected your iPhone/iPod... ");
			fflush(stdout);
			fgets(responseBuffer, 10, stdin);
			sleep(2);
			if(Status != Disconnected) {
				goto turnOffDevice;
			} else {
isPoweringOn:
				fprintf(stdout, "Is your iPhone currently powering on?\n");
				fprintf(stdout, "Please answer (y/n): ");
				fflush(stdout);
				fgets(responseBuffer, 10, stdin);
				if(responseBuffer[0] == 'y' || responseBuffer[0] == 'Y') {
					fprintf(stdout, "Waiting for iPhone/iPod to power on...\n");
					fflush(stdout);
					while(Status == Disconnected) {
						sleep(1);
					}
					goto turnOffDevice;
				} else if(responseBuffer[0] == 'n' || responseBuffer[0] == 'N') {
					goto beginDFU;
				} else {
					goto isPoweringOn;
				}
			}
		} else {
			goto connectDevice;
		}
	} else {
turnOffDevice:
		fprintf(stdout, "Please turn off your iPhone/iPod without disconnecting the cable connecting it to the computer\n");
		fprintf(stdout, "Press enter when you have turned off your iPhone/iPod... ");
		fflush(stdout);
		fgets(responseBuffer, 10, stdin);

		fprintf(stdout, "Waiting for iPhone/iPod to power off...\n");
		fflush(stdout);
		while(Status != Disconnected) {
			sleep(1);
		}
	}

beginDFU:
	fprintf(stdout, "\n!!! Your device should now be off. If it is not, please make sure it is before proceeding !!!\n\n");

	fprintf(stdout, "Timing is crucial for the following tasks. I will ask you to do the following (DON'T START YET):\n");
	fprintf(stdout, "\t1. Press and hold down the power button for five seconds\n");
	fprintf(stdout, "\t2. Without letting go of the power button, press and hold down the power AND home buttons for ten seconds\n");
	fprintf(stdout, "\t3. Without letting go of the home button, release the power button\n");
	fprintf(stdout, "\t4. Wait 30 seconds while holding down the home button\n");
	fprintf(stdout, "\nTry to get the timing as correct as possible, but don't fret if you miss it by a few seconds. It might still work, and if it doesn't, you can always try again. If you fail, you can always just turn the phone completely off by holding power and home for ten seconds, then pushing power to turn it back on.\n");
	fprintf(stdout, "\nAre you ready to begin?\n");
	fprintf(stdout, "Please answer (y/n): ");
	fflush(stdout);
	fgets(responseBuffer, 10, stdin);
	if(responseBuffer[0] != 'y' && responseBuffer[0] != 'Y')
		goto beginDFU;

	for(countdown = 5; countdown > 0; countdown--) {
		fprintf(stdout, "Beginning process in %d seconds...\n", countdown);
		fflush(stdout);
		sleep(1);
	}

	fprintf(stdout, "\nPress and hold down the POWER button (you should now be just holding the power button)... ");
	fflush(stdout);

	for(countdown = 5; countdown > 0; countdown--) {
		fprintf(stdout, "%d... ", countdown);
		fflush(stdout);
		sleep(1);
	}


	fprintf(stdout, "\n\nPress and hold down the HOME button, DO NOT LET GO OF THE POWER BUTTON (you should now be just holding both the power and home buttons)... ");
	fflush(stdout);

	for(countdown = 10; countdown > 0; countdown--) {
		fprintf(stdout, "%d... ", countdown);
		fflush(stdout);
		sleep(1);
	}

	fprintf(stdout, "\n\nRelease the POWER button, DO NOT LET GO OF THE HOME BUTTON (you should now be just holding the home button)... ");
	fflush(stdout);

	Stage = 2;

	for(countdown = 30; countdown > 0; countdown--) {
		if(Status != Disconnected)
			goto waitForFinish;

		fprintf(stdout, "%d... ", countdown);
		fflush(stdout);
		sleep(1);
	}

	fprintf(stdout, "\n\nEither you did not follow instructions correctly or your USB hardware is malfunctioning. Please use another USB port to connect your iPhone/iPod (NOT through a USB hub) and consider restarting your computer before trying again.\n");
	fflush(stdout);
	cleanup_and_exit();

waitForFinish:
	while(1) {
		msleep(1);
	}
}
Ejemplo n.º 8
0
void writeOutput(OutputState** state, char* ipsw) {
	OutputState* curFile;
	OutputState* next;
	zip_fileinfo info;
	struct tm* filedate;
	time_t tm_t;

	zipFile zip;

	tm_t = time(NULL);
	filedate = localtime(&tm_t);
	info.tmz_date.tm_sec  = filedate->tm_sec;
	info.tmz_date.tm_min  = filedate->tm_min;
	info.tmz_date.tm_hour = filedate->tm_hour;
	info.tmz_date.tm_mday = filedate->tm_mday;
	info.tmz_date.tm_mon  = filedate->tm_mon ;
	info.tmz_date.tm_year = filedate->tm_year;
	info.dosDate = 0;
	info.internal_fa = 0;
	info.external_fa = 0;
	
	ASSERT(zip = zipOpen(ipsw,  APPEND_STATUS_CREATE), "Cannot open output zip file");

	next = *state;

	while(next != NULL) {
		curFile = next;
		next = next->next;
		printf("packing: %s (%ld)\n", curFile->fileName, (long) curFile->bufferSize); fflush(stdout);
		
		if(curFile->bufferSize > 0) {
			ASSERT(zipOpenNewFileInZip(zip, curFile->fileName, &info, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) == 0, "error adding to zip");
			if(curFile->tmpFileName == NULL) {
				ASSERT(zipWriteInFileInZip(zip, curFile->buffer, curFile->bufferSize) == 0, "error writing to zip");
			} else {
				AbstractFile* tmpFile = createAbstractFileFromFile(fopen(curFile->tmpFileName, "rb"));
				char* buffer = malloc(DEFAULT_BUFFER_SIZE);
				size_t left = tmpFile->getLength(tmpFile);
				while(left > 0) {
					size_t toRead;
					if(left > DEFAULT_BUFFER_SIZE)
						toRead = DEFAULT_BUFFER_SIZE;
					else
						toRead = left;
					ASSERT(tmpFile->read(tmpFile, buffer, toRead) == toRead, "error reading data");
					ASSERT(zipWriteInFileInZip(zip, buffer, toRead) == 0, "error writing to zip");
					left -= toRead;
				}
				tmpFile->close(tmpFile);
				free(buffer);
			}
		} else {
			ASSERT(zipOpenNewFileInZip(zip, curFile->fileName, &info, NULL, 0, NULL, 0, NULL, 0, 0) == 0, "error adding to zip");
		}
		ASSERT(zipCloseFileInZip(zip) == 0, "error closing file in zip");
		if(curFile->tmpFileName) {
			unlink(curFile->tmpFileName);
			free(curFile->tmpFileName);
		}
		free(curFile->fileName);

		if(curFile->buffer) {
			free(curFile->buffer);
		}

		free(curFile);
	}

	zipClose(zip, NULL);
}
Ejemplo n.º 9
0
int main(int argc, char* argv[]) {
	init_libxpwn(&argc, argv);

	OutputState *outputState;
	size_t fileLength;

	AbstractFile *signFile;
	Dictionary *signDict = NULL;
	DataValue *ticket;
	Dictionary *dict;

	AbstractFile *manifestFile;
	Dictionary* manifest;
	struct component_t *array;

	char *plist;
	int i, j, n;
	int rv, error = 0;

	X509 *x0, *y1, *y2;
	uint64_t savecid = 0;
	const unsigned char *p;

	int verbose = FALSE;
	int fromzip = FALSE;

	if (argc < 3) {
		XLOG(0, "usage %s file.shsh BuildManifest.plist [-v] [-z]\n", argv[0]);
		return 0;
	}

	for (i = 3; i < argc; i++) {
		if (!strcmp(argv[i], "-v")) {
			verbose = TRUE;
			continue;
		}

		if (!strcmp(argv[i], "-z")) {
			fromzip = TRUE;
			continue;
		}
	}

	// XXX handle gzip/bplist files
	signFile = createAbstractFileFromFile(fopen(argv[1], "rb"));
	if (!signFile) {
		XLOG(0, "FATAL: cannot open %s\n", argv[1]);
		exit(1);
	}

	fileLength = signFile->getLength(signFile);
	plist = malloc(fileLength);
	signFile->read(signFile, plist, fileLength);
	signFile->close(signFile);
	signDict = createRoot(plist);
	free(plist);

	if (!signDict) {
		XLOG(0, "FATAL: cannot parse %s\n", argv[1]);
		exit(1);
	}

	MaxLoadZipSize = 128 * 1024;
	if (fromzip) {
		outputState = loadZip2(argv[2], TRUE); // XXX ASSERT
		manifestFile = getFileFromOutputState(&outputState, "BuildManifest.plist");
	} else {
		outputState = NULL;
		manifestFile = createAbstractFileFromFile(fopen(argv[2], "rb"));
	}
	if (!manifestFile) {
		XLOG(0, "FATAL: cannot open %s\n", argv[2]);
		exit(1);
	}

	fileLength = manifestFile->getLength(manifestFile);
	plist = malloc(fileLength);
	manifestFile->read(manifestFile, plist, fileLength);
	manifestFile->close(manifestFile);
	manifest = createRoot(plist);
	free(plist);

	if (!manifest) {
		XLOG(0, "FATAL: cannot parse %s\n", argv[2]);
		exit(1);
	}

	releaseOutput(&outputState);

	array = parseManifest(manifest, &n);
	if (!array) {
		XLOG(0, "FATAL: cannot parse manifest\n");
		exit(1);
	}

	OPENSSL_add_all_algorithms_noconf();
	p = cerb;
	x0 = d2i_X509(NULL, &p, cerb_len);
	if (!x0) {
		XLOG(0, "FATAL: cannot load root CA\n");
		exit(1);
	}

	ticket = (DataValue *)getValueByKey(signDict, "APTicket");
	if (ticket) {
		p = ticket->value;
		rv = asn1_parse2(&p, ticket->len, 0, 0);
		if (!rv || !apcert.value || !rsasig.value || !theset.value) {
			XLOG(0, "FATAL: cannot parse ticket\n");
			exit(1);
		}
		if (clen > 0 && contarray->len == 8) {
			savecid = getECID(contarray->value);
		}
		if (!savecid) {
			printf("ERROR: bad, bad ECID\n");
			error = 1;
		}

		rv = extract2Certs(apcert.value, apcert.len, &y1, &y2);
		if (rv == 0) {
			rv = cryptoMagic(x0, y1, y2, theset.value, theset.len, (unsigned char *)rsasig.value, rsasig.len, NULL);
			X509_free(y1);
			X509_free(y2);
		}
		if (rv) {
			printf("ERROR: APTicket failed crypto\n");
			error = 1;
		}
	} else {
		VERBOSE("WARNING: cannot find ticket in %s\n", argv[1]);
	}

	dict = (Dictionary *)signDict->values;
	while (dict) {
		DataValue *blob = NULL;
		DataValue *partialDigest = NULL;
		if (dict->dValue.type == DictionaryType) {
			blob = (DataValue *)getValueByKey(dict, "Blob");
			partialDigest = (DataValue *)getValueByKey(dict, "PartialDigest");
		}
		if (blob && partialDigest) {
			const char *diag = checkBlob(x0, blob, partialDigest, &savecid);
			if (diag) {
				printf("ERROR: Blob for %s is invalid (%s)\n", dict->dValue.key, diag);
				error = 1;
			} else {
				for (i = 0; i < n; i++) {
					struct component_t *centry = array + i;
					if (centry->partial &&
					    partialDigest->len == centry->partial->len &&
					    !memcmp(partialDigest->value, centry->partial->value, partialDigest->len)) {
						array[i].blob = blob;
					}
				}
			}
		}
		dict = (Dictionary *)dict->dValue.next;
	}

	if (!ticket && !savecid) {
		printf("ERROR: bad, bad ECID\n");
		error = 1;
	}

	for (i = 0; i < n; i++) {
		struct component_t *centry = array + i;
		int found = FALSE;
		for (j = 0; j < clen; j++) {
			struct tuple_t *tentry = contarray + j;
			if (tentry->len == centry->digest->len && !memcmp(tentry->value, centry->digest->value, tentry->len)) {
				found = TRUE;
			}
		}
		if (!found) {
			if (centry->blob) {
				VERBOSE("WARNING: no digest for %s (%s), but it has blob\n", centry->key, centry->path);
			} else if (!centry->required) {
				VERBOSE("WARNING: no digest for %s (%s), but it is not critical\n", centry->key, centry->path);
			} else {
				printf("ERROR: no digest for %s (%s) and no blob found\n", centry->key, centry->path);
				error = 1;
			}
		} else {
			VERBOSE("INFO: %s (%s) is signed by APTicket%s\n", centry->key, centry->path, centry->blob ? " and blob" : "");
		}
	}
	free(array);
	free(contarray);

	releaseDictionary(manifest);
	releaseDictionary(signDict);

	if (error) {
		printf("%s is BROKEN\n", argv[1]);
	} else {
		printf("%s seems usable for ECID 0x%016llX\n", argv[1], savecid);
	}

	X509_free(x0);

	EVP_cleanup();
	ERR_remove_state(0);
	CRYPTO_cleanup_all_ex_data();
	return error;
}
Ejemplo n.º 10
0
int main(int argc, char *argv[]) 
{
	const char* bundleRoot = "FirmwareBundles/";
	const char *pResponse = NULL;
	CIBootConn conn;
	ERR_CODE code;
	OutputState* ipswContents;
	char* bundlePath;
	Dictionary* info;
	StringValue* kernelValue;
	AbstractFile* ramdisk;

	AbstractFile* applelogo = NULL;
	AbstractFile* recoverymode = NULL;
	AbstractFile* iboot = NULL;
	int i;

	TestByteOrder();

	applelogo = NULL;
	recoverymode = NULL;

	if(argc < 2) {
		cout << "usage: " << argv[0] << " <input ipsw> [-b <bootimage.png>] [-r <recoveryimage.png>]" << endl;
		return 1;
	}

	for(i = 2; i < argc; i++) {	
		if(strcmp(argv[i], "-b") == 0) {
			applelogo = createAbstractFileFromFile(fopen(argv[i + 1], "rb"));
			if(!applelogo) {
				cout << "cannot open " << argv[i + 1] << endl;
				return 1;
			}
			i++;
			continue;
		}

		if(strcmp(argv[i], "-r") == 0) {
			recoverymode = createAbstractFileFromFile(fopen(argv[i + 1], "rb"));
			if(!recoverymode) {
				cout << "cannot open " << argv[i + 1] << endl;
				return 1;
			}
			i++;
			continue;
		}
		if(strcmp(argv[i], "-i") == 0) {
			iboot = createAbstractFileFromFile(fopen(argv[i + 1], "rb"));
			if(!iboot) {
				cout << "cannot open " << argv[i + 1] << endl;
				return 1;
			}
			i++;
			continue;
		}
	}

	cout << " ... Connecting" << endl;
	if ((code = conn.Connect()) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		return 1;
	}

	cout << " ... Loading IPSW" << endl;
	info = parseIPSW(argv[1], bundleRoot, &bundlePath, &ipswContents);

	if(!info) {
		printf("error: cannot load IPSW file\n");
		exit(1);
	}

	cout << " ... Opening ramdisk" << endl;
	AbstractFile* ramdiskSrc = createAbstractFileFromFile(fopen("ramdisk.dmg", "rb"));
	if(!ramdiskSrc) {
		cout << "error: cannot find ramdisk.dmg!" << endl;
		exit(1);
	}

	size_t bufferSize = ramdiskSrc->getLength(ramdiskSrc);
	void* buffer = (void*) malloc(bufferSize);
	cout << " ... Reading ramdisk" << endl;
	ramdiskSrc->read(ramdiskSrc, buffer, bufferSize);
	io_func* myRamdisk = IOFuncFromAbstractFile(createAbstractFileFromMemoryFile(&buffer, &bufferSize));
	Volume* ramdiskVolume = openVolume(myRamdisk);

	Dictionary* ibootDict = (Dictionary*)getValueByKey((Dictionary*)getValueByKey(info, "FirmwarePatches"), "iBoot");
	if(!ibootDict) {
		cout << "Error reading iBoot info" << endl;
		exit(1);
	}

	if(!iboot) {
		add_hfs(ramdiskVolume, getFileFromOutputState(&ipswContents, ((StringValue*)getValueByKey(ibootDict, "File"))->value), "/ipwner/iboot.img2");
		StringValue* patchValue = (StringValue*) getValueByKey(ibootDict, "Patch");
		char* patchPath = (char*) malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2));
		strcpy(patchPath, bundlePath);
		strcat(patchPath, "/");
		strcat(patchPath, patchValue->value);
		printf("patching /ipwner/iboot.img2 (%s)... ", patchPath);
		doPatchInPlace(ramdiskVolume, "/ipwner/iboot.img2", patchPath);
		free(patchPath);
	} else {
		cout << "adding custom iboot" << endl;
		add_hfs(ramdiskVolume, iboot, "/ipwner/iboot.img2");
	}

	if(applelogo || recoverymode) {
		cout << " ... Adding boot logos" << endl;

		StringValue* fileValue;
		void* imageBuffer;
		size_t imageSize;

		if(applelogo) {
			fileValue = (StringValue*) getValueByKey((Dictionary*)getValueByKey((Dictionary*)getValueByKey(info, "FirmwarePatches"), "AppleLogo"), "File");
			printf("replacing %s\n", fileValue->value); fflush(stdout);
			ASSERT((imageBuffer = replaceBootImage(getFileFromOutputState(&ipswContents, fileValue->value), NULL, NULL, applelogo, &imageSize)) != NULL, "failed to use new image");
			add_hfs(ramdiskVolume, createAbstractFileFromMemory(&imageBuffer, imageSize), "/ipwner/logo.img2");
		}

		if(recoverymode) {
			fileValue = (StringValue*) getValueByKey((Dictionary*)getValueByKey((Dictionary*)getValueByKey(info, "FirmwarePatches"), "RecoveryMode"), "File");
			printf("replacing %s\n", fileValue->value); fflush(stdout);
			ASSERT((imageBuffer = replaceBootImage(getFileFromOutputState(&ipswContents, fileValue->value), NULL, NULL, recoverymode, &imageSize)) != NULL, "failed to use new image");
			add_hfs(ramdiskVolume, createAbstractFileFromMemory(&imageBuffer, imageSize), "/ipwner/recovery.img2");			
		}

	}

	cout << " ... Finalizing ramdisk" << endl;
	closeVolume(ramdiskVolume);
	CLOSE(myRamdisk);

	ramdisk = createAbstractFileFromMemoryFile(&buffer, &bufferSize);

	kernelValue = (StringValue*) getValueByKey((Dictionary*)getValueByKey((Dictionary*)getValueByKey(info, "FirmwarePatches"), "KernelCache"), "File");
	if(!kernelValue) {
		cout << "Unable to determine kernel cache file name from bundle plist!";
		return 1;
	}
	
	cout << " ... Will send kernel at: " << kernelValue->value << endl;

	cout << " ... Sending ramdisk" << endl;
	if ((code = conn.SendFile(ramdisk, 0x09400000)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	if ((code = conn.GetResponse(pResponse)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	cout << "Response: " << pResponse << endl;

	cout << " ... Sending kernelcache" << endl;
	if ((code = conn.SendFile(getFileFromOutputState(&ipswContents, kernelValue->value), 0x09000000)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	if ((code = conn.GetResponse(pResponse)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	cout << "Response: " << pResponse << endl;

	cout << " ... Clearing boot arguments" << endl;
	if ((code = conn.SendCommand("setenv boot-args \"\"\n")) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	if ((code = conn.GetResponse(pResponse)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}
	cout << "Response: " << pResponse << endl;

	cout << " ... Setting auto-reboot" << endl;
	if ((code = conn.SendCommand("setenv auto-boot true\n")) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	if ((code = conn.GetResponse(pResponse)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	cout << "Response: " << pResponse << endl;

	cout << " ... Saving environment" << endl;
	if ((code = conn.SendCommand("saveenv\n")) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	if ((code = conn.GetResponse(pResponse)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	cout << "Response: " << pResponse << endl;

	cout << " ... Setting up ramdisk" << endl;
	char bootArgsBuf[1024];
	sprintf(bootArgsBuf, "setenv boot-args \"-v pmd0=0x09400000.0x%x pmd1=0x8000000.0x8000000 rd=md0\"\n", bufferSize);
	if ((code = conn.SendCommand(bootArgsBuf)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	if ((code = conn.GetResponse(pResponse)) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	cout << "Response: " << pResponse << endl;

	cout << " ... Booting" << endl;
	if ((code = conn.SendCommand("bootx\n")) != IB_SUCCESS)
	{
		cout << errcode_to_str(code) << endl;
		conn.Disconnect();
		return 1;
	}

	if ((code = conn.GetResponse(pResponse)) == IB_SUCCESS)
	{
		conn.Disconnect();
		cout << "Response: " << pResponse << endl;
		cout << "Booting did not appear to be successful." << endl;
	} else {

		conn.Disconnect();
		cout << "Disconnected. Please wait patiently until it has rebooted to the SpringBoard." << endl;
		cout << "If you get repeating 'bsd root' messages, it means the ramdisk somehow got corrupted in memory before it could be loaded. Just reboot into recovery mode and try again." << endl;
	}

	releaseOutput(&ipswContents);
	releaseDictionary(info);
	free(bundlePath);

	return 0;
}