[HELP] Error Extracting 360.PSAR

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
raing3
Posts: 12
Joined: Sun Nov 09, 2008 1:59 pm
Contact:

[HELP] Error Extracting 360.PSAR

Post by raing3 »

I am currently having trouble extracting the full contents of the 3.60 PSAR created by the 360 dumper included with Time Machine. I am using a modified version of the 5.00 3000 PSAR dumper. The application stops extracting once it gets to the point where it needs to buffer more data and displays the error 'PSAR decode error at 0x008A7826'.

I have tried using just the plain PSAR file and the PSAR packed into an updater EBOOT and this hasn't fixed the issue all official updater EBOOTs appear to extract alright. I have also tried extracting the PSAR with the original 5.00 3000 PSAR dumper and it correctly dumped the files and I have not modified libpsardumper or pspdecrypt. I have also left the PSAR buffer size at 9400000 which is the same as the original PSAR decrypter but I have tried a number of different buffer sizes, although I cannot read the whole file at once due to a lack of available RAM so I cannot increase the buffer to the full PSAR size. Lastly I have also tried disabling that particular check and using a 'less' modified version of the PSAR dumper which decrypts all the files with no success.

Assume the paramaters passed are DumpPSAR(MODE_ENCRYPT, "ms0:/360.PSAR", "ms0:/TM/360M33", "3.60", NULL);

Code: Select all

void DumpPSAR(int extractmode, char *filepath, char *outdir, char *requiredver, char *requiredfiles[])
{
	char message[256];
	int s, res;
	u8 pbp_header[0x28];
	SceUID fd;
	int error = 0;
	int psar_pos = 0, psar_offs;
	int table_mode;

	if &#40;sceKernelDevkitVersion&#40;&#41; < 0x02070110&#41;&#123;
		vlfGuiMessageDialog&#40;"PSAR Extraction requires a 2.71 or higher kernel. If you are in a Custom Firmware please re-execute this application on a higher kernel.", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
	&#125;

	sceKernelVolatileMemLock&#40;0, &#40;void *&#41;&g_dataOut2, &s&#41;;

	SetStatus&#40;0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Loading PSAR..."&#41;;

	if &#40;ReadFile&#40;filepath, 0, pbp_header, sizeof&#40;pbp_header&#41;&#41; != sizeof&#40;pbp_header&#41;&#41;&#123;
		sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;strcat&#40;"Unable to read ", strdup&#40;filepath&#41;&#41;, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
	&#125;

	if&#40;memcmp&#40;pbp_header, "PSAR", 4&#41; == 0&#41;&#123;psar_offs = 0;&#125;
	else&#123;psar_offs = *&#40;u32 *&#41;&pbp_header&#91;0x24&#93;;&#125;

	fd = sceIoOpen&#40;filepath, PSP_O_RDONLY, 0&#41;;
	
	int cbFile = sceIoLseek32&#40;fd, 0, PSP_SEEK_END&#41; - psar_offs;
	sceIoLseek32&#40;fd, psar_offs, PSP_SEEK_SET&#41;;

	SetStatus&#40;0, 1, 240, 160, VLF_ALIGNMENT_CENTER, "Buffering PSAR data..."&#41;;
	if &#40;sceIoRead&#40;fd, g_dataPSAR, PSAR_BUFFER_SIZE&#41; <= 0&#41;&#123;
		sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"Error reading file", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
	&#125;

	if &#40;memcmp&#40;g_dataPSAR, "PSAR", 4&#41; != 0&#41;&#123;
		sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"Invalid PSAR file", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;	
	&#125;
   
	res = pspPSARInit&#40;g_dataPSAR, g_dataOut, g_dataOut2&#41;;
	if &#40;res < 0&#41;&#123;
		sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"pspPSARInit failed", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
	&#125;

	char *ver = GetVersion&#40;&#40;char *&#41;g_dataOut+0x10&#41;;
	if&#40;requiredver != NULL&#41;&#123;
		if&#40;strcmp&#40;ver, requiredver&#41; != 0&#41;&#123;
			sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"Wrong EBOOT.PBP version", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
		&#125;
	&#125;

	if &#40;memcmp&#40;ver, "3.8", 3&#41; == 0 || memcmp&#40;ver, "3.9", 3&#41; == 0&#41;&#123;table_mode = 1;&#125;
	else if &#40;memcmp&#40;ver, "4.0", 3&#41; == 0&#41;&#123;table_mode = 2;&#125;
	else if &#40;memcmp&#40;ver, "5.0", 3&#41; == 0&#41;&#123;table_mode = 3;&#125;
	else&#123;table_mode = 0;&#125;

	SetStatus&#40;0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Table Mode&#58; %d", table_mode&#41;;

	while &#40;1&#41;&#123;
		char name&#91;128&#93;;
		int cbExpanded;
		int pos;
		int signcheck;
		int i = 0,  filerequired = 1;

		int res = pspPSARGetNextFile&#40;g_dataPSAR, cbFile, g_dataOut, g_dataOut2, name, &cbExpanded, &pos, &signcheck&#41;;

		if &#40;res < 0&#41;&#123;
			if &#40;error&#41;&#123;
				sprintf&#40;message, "PSAR decode error at 0x%08X", pos&#41;;
				sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
			&#125;

			int dpos = pos-psar_pos;
			psar_pos = pos;
			
			error = 1;
			memmove&#40;g_dataPSAR, g_dataPSAR+dpos, PSAR_BUFFER_SIZE-dpos&#41;;

			SetStatus&#40;0, 1, 240, 160, VLF_ALIGNMENT_CENTER, "Buffering PSAR data..."&#41;;
			if &#40;sceIoRead&#40;fd, g_dataPSAR+&#40;PSAR_BUFFER_SIZE-dpos&#41;, dpos&#41; <= 0&#41;&#123;
				sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"Unable to read file", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
			&#125;

			pspPSARSetBufferPosition&#40;psar_pos&#41;;

			continue;
		&#125;
		else if &#40;res == 0&#41;&#123; /* no more files */
			break;
		&#125;

		if &#40;is5Dnum&#40;name&#41;&#41;&#123;
			if &#40;strcmp&#40;name, "00001"&#41; != 0 && strcmp&#40;name, "00002"&#41; != 0 && strcmp&#40;name, "00003"&#41; != 0&#41;&#123;
				int found = 0;
				
				if &#40;_1gtable_size > 0&#41;&#123;found = FindTablePath&#40;_1g_table, _1gtable_size, name, name&#41;;&#125;

				if &#40;!found && _2gtable_size > 0&#41;&#123;found = FindTablePath&#40;_2g_table, _2gtable_size, name, name&#41;;&#125;
				if &#40;!found && _3gtable_size > 0&#41;&#123;found = FindTablePath&#40;_3g_table, _3gtable_size, name, name&#41;;&#125;
				if &#40;!found&#41;&#123;
					SetStatus&#40;0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Warning&#58; cannot find path of %s", name&#41;;
					error = 0;
					continue;
				&#125;
			&#125;
		&#125;
		else if &#40;!strncmp&#40;name, "com&#58;", 4&#41; && comtable_size > 0&#41;&#123;
			if &#40;!FindTablePath&#40;com_table, comtable_size, name+4, name&#41;&#41;&#123;
				SetStatus&#40;0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Warning&#58; cannot find path of %s", name&#41;;
				error = 0;
				continue;
			&#125;
		&#125;

		else if &#40;!strncmp&#40;name, "01g&#58;", 4&#41; && _1gtable_size > 0&#41;&#123;
			if &#40;!FindTablePath&#40;_1g_table, _1gtable_size, name+4, name&#41;&#41;&#123;
				sprintf&#40;message, "Cannot find path of %s", name&#41;;
				sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
			&#125;
		&#125;

		else if &#40;!strncmp&#40;name, "02g&#58;", 4&#41; && _2gtable_size > 0&#41;&#123;
			if &#40;!FindTablePath&#40;_2g_table, _2gtable_size, name+4, name&#41;&#41;&#123;
				sprintf&#40;message, "Cannot find path of %s", name&#41;;
				sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
			&#125;
		&#125;

		if&#40;requiredfiles == NULL&#41;&#123;filerequired = 1;&#125;
		else&#123;
			filerequired = 0;
			i = 0;
			while&#40;i != -1&#41;&#123;
				if&#40;strcmp&#40;name, requiredfiles&#91;i&#93;&#41; == 0&#41;&#123;filerequired = 1;i = -2;&#125;
				i++;
				if&#40;strcmp&#40;requiredfiles&#91;i&#93;, "0"&#41; == 0&#41;&#123;i = -1;&#125;
			&#125;
		&#125;
		if&#40;filerequired == 1&#41;&#123;SetStatus&#40;0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "%s", name&#41;;&#125;

		char* szFileBase = strrchr&#40;name, '/'&#41;;
		
		if &#40;szFileBase != NULL&#41;
			szFileBase++;  // after slash
		else
			szFileBase = "err.err";

		if &#40;cbExpanded > 0&#41;&#123;
			char szDataPath&#91;128&#93;;
			
			if &#40;!strncmp&#40;name, "flash0&#58;/", 8&#41;&#41;&#123;sprintf&#40;szDataPath, "%s/%s", outdir, name+8&#41;;&#125;
			else if &#40;!strncmp&#40;name, "flash1&#58;/", 8&#41;&#41;&#123;sprintf&#40;szDataPath, "%s/%s", outdir, name+8&#41;;&#125;
			else if &#40;!strcmp&#40;name, "com&#58;00000"&#41;&#41;&#123;
				comtable_size = pspDecryptTable&#40;g_dataOut2, g_dataOut, cbExpanded, table_mode&#41;;
							
				if &#40;comtable_size <= 0&#41;&#123;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"Cannot decrypt common table", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
				&#125;

				if &#40;comtable_size > sizeof&#40;com_table&#41;&#41;&#123;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"COM table buffer is too small", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
				&#125;

				memcpy&#40;com_table, g_dataOut2, comtable_size&#41;;
				continue;
			&#125;	
			else if &#40;!strcmp&#40;name, "01g&#58;00000"&#41; || !strcmp&#40;name, "00001"&#41;&#41;&#123;
				_1gtable_size = pspDecryptTable&#40;g_dataOut2, g_dataOut, cbExpanded, table_mode&#41;;
							
				if &#40;_1gtable_size <= 0&#41;&#123;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"Cannot decrypt 1g table", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
				&#125;

				if &#40;_1gtable_size > sizeof&#40;_1g_table&#41;&#41;&#123;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"1g table buffer is too small", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
				&#125;

				memcpy&#40;_1g_table, g_dataOut2, _1gtable_size&#41;;
				continue;
			&#125;	
			else if &#40;!strcmp&#40;name, "02g&#58;00000"&#41; || !strcmp&#40;name, "00002"&#41;&#41;&#123;
				_2gtable_size = pspDecryptTable&#40;g_dataOut2, g_dataOut, cbExpanded, table_mode&#41;;
							
				if &#40;_2gtable_size <= 0&#41;&#123;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"Cannot decrypt 2g table", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
				&#125;

				if &#40;_2gtable_size > sizeof&#40;_2g_table&#41;&#41;&#123;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"2g table buffer is too small", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
				&#125;

				memcpy&#40;_2g_table, g_dataOut2, _2gtable_size&#41;;
				continue;
			&#125;
			else if &#40;!strcmp&#40;name, "00003"&#41;&#41;&#123;
				_3gtable_size = pspDecryptTable&#40;g_dataOut2, g_dataOut, cbExpanded, table_mode&#41;;
							
				if &#40;_3gtable_size <= 0&#41;&#123;
					// We don't have yet the keys for table of 3000, they are only in mesg_led03g.prx
					SetStatus&#40;0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Cannot decrypt 3g table"&#41;;
					error = 0;
					continue;
				&#125;

				if &#40;_3gtable_size > sizeof&#40;_3g_table&#41;&#41;&#123;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"3g table buffer is too small", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
				&#125;

				memcpy&#40;_3g_table, g_dataOut2, _3gtable_size&#41;;
				continue;
			&#125;
			else&#123;continue;&#125;

			if &#40;signcheck && extractmode == MODE_ENCRYPT_SIGCHECK && &#40;strcmp&#40;name, "flash0&#58;/kd/loadexec.prx"&#41; != 0&#41; && &#40;strcmp&#40;name, "flash0&#58;/kd/loadexec_01g.prx"&#41; != 0&#41; && &#40;strcmp&#40;name, "flash0&#58;/kd/loadexec_02g.prx"&#41; != 0&#41;&#41;&#123;
				pspSignCheck&#40;g_dataOut2&#41;;
			&#125;

			if &#40;&#40;extractmode != MODE_DECRYPT&#41; || &#40;memcmp&#40;g_dataOut2, "~PSP", 4&#41; != 0&#41;&#41;&#123;				
				if &#40;WriteFile&#40;szDataPath, g_dataOut2, cbExpanded&#41; != cbExpanded&#41;&#123;
					sprintf&#40;message, "Cannot write %s", szDataPath&#41;;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
					break;
				&#125;
			&#125;

			if &#40;&#40;memcmp&#40;g_dataOut2, "~PSP", 4&#41; == 0&#41; &&	&#40;extractmode == MODE_DECRYPT&#41;&#41;&#123;
				int cbDecrypted = pspDecryptPRX&#40;g_dataOut2, g_dataOut, cbExpanded&#41;;

				// output goes back to main buffer
				// trashed 'g_dataOut2'
				if &#40;cbDecrypted > 0&#41;&#123;
					u8* pbToSave = g_dataOut;
					int cbToSave = cbDecrypted;
                            
					if &#40;&#40;g_dataOut&#91;0&#93; == 0x1F && g_dataOut&#91;1&#93; == 0x8B&#41; || memcmp&#40;g_dataOut, "2RLZ", 4&#41; == 0 || memcmp&#40;g_dataOut, "KL4E", 4&#41; == 0&#41;&#123;
						int cbExp = pspDecompress&#40;g_dataOut, g_dataOut2, sizeof&#40;g_dataOut&#41;&#41;;
						
						if &#40;cbExp > 0&#41;&#123;
							pbToSave = g_dataOut2;
							cbToSave = cbExp;
						&#125;
						else&#123;
							SetStatus&#40;0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Decompress error 0x%08X\n\nFile will be written compressed", cbExp&#41;;
						&#125;
					&#125;
        			
					if &#40;WriteFile&#40;szDataPath, pbToSave, cbToSave&#41; != cbToSave&#41;&#123;
						sprintf&#40;message, "Cannot write %s", szDataPath&#41;;
						sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
					&#125;
				&#125;
				else
				&#123;
					sceKernelVolatileMemUnlock&#40;0&#41;;vlfGuiMessageDialog&#40;"Unable to decrypt file", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE&#41;;OnBackToMainMenu&#40;0&#41;;return;
				&#125;
			&#125;
		&#125;

		error = 0;
		scePowerTick&#40;0&#41;;	
	&#125;

	sceIoClose&#40;fd&#41;;

    scePowerTick&#40;0&#41;;	
	SetStatus&#40;1, 0, 240, 120, VLF_ALIGNMENT_CENTER, "PSAR file has been extracted to %s", outdir&#41;;

    return 0;
&#125;
I am also having an issue when I extract the 4.01 PSAR the 'dmacman.prx' module is being created but by the time the whole PSAR is extracted the file has been deleted. I think what is causing this issue is that the directories are created just before the file is created because this is not an issue when I create the folders manually at the start of the PSAR extraction. I have not tested any other updater EBOOTs but the only file which is deleted is 'dmacman.prx' and I know this file is being created.

Code: Select all

int WriteFile&#40;char *file, void *buf, int size&#41;
&#123;
	SceUID fd;	
	int i;
	int pathlen = 0;
	char filepath&#91;128&#93;;

	for&#40;i=1; i<&#40;strlen&#40;file&#41;&#41;; i++&#41;&#123;
		if&#40;strncmp&#40;file+i-1, "/", 1&#41; == 0&#41;&#123;
			pathlen=i-1;
			strncpy&#40;filepath, file, pathlen&#41;;
			filepath&#91;pathlen&#93; = 0;

			sceIoMkdir&#40;filepath, 0777&#41;;
		&#125;
	&#125;
	

	fd = sceIoOpen&#40;file, PSP_O_WRONLY|PSP_O_CREAT|PSP_O_TRUNC, 0777&#41;;
	if&#40;fd < 0&#41;&#123;return fd;&#125;

	int written = sceIoWrite&#40;fd, buf, size&#41;;

	sceIoClose&#40;fd&#41;;
	return written;
&#125;
The full project can be downloaded from http://ifile.it/o2aztsy. Keep in mind that I'm still trying to fix other issues and a number of features do not work also their are a number of other minor issues with the PSAR extraction which I have encountered which are caused if I do PSAR extraction multiple times without restarting and if I do not call sceKernelVolatileMemUnlock(0); the VLF messages and other stuff doesn't work. Any help in fixing the issues would be greatly appreciated I've spent so many hours trying to figure out what is wrong and I'm sure some of you pros will be able to find out what the problem is in a couple of minutes.
Post Reply