I've written a quick and dirty PSP Header Parser thats rougly based on Gorims SFO parser:
Update:
Fixed infinty loop bug under linux - thanks to fireether for pointing it out
Code: Select all
// PSPParse.cpp : Defines the entry point for the console
application.
//
#include "stdafx.h"
/*
* PSP File Parser v 0.1, based on Gorims SFO parser
*
* This source is licensed under the terms of the Academic Free License
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRBUFSZ 512
// Some data type definitions for Intel Doze platforms, 2005/05/06
typedef unsigned int u_int32_t;
typedef unsigned short int u_int16_t ;
typedef unsigned char u_int8_t;
/* Change endianess*/
u_int32_t le32(int i)
{
unsigned char b1, b2, b3, b4;
b1 = i & 255;
b2 = ( i >> 8 ) & 255;
b3 = ( i>>16 ) & 255;
b4 = ( i>>24 ) & 255;
return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4;
}
u_int16_t le16(short s )
{
unsigned char b1, b2;
b1 = s & 255;
b2 = (s >> 8) & 255;
return (b1 << 8) + b2;
}
struct PSPHdr
{
u_int8_t type[4];
u_int32_t version;
u_int16_t sect1;
u_int8_t title[28];
u_int16_t sect2;
u_int32_t size[2];
u_int32_t unkwn_ptr[3];
u_int32_t sect3;
u_int32_t nulls[40];
};
char pspMagic[] = "~PSP";
char DefaultFile[] = "DATA.PSP";
int main(int argc, char *argv[])
{
FILE *PSPFile;
char *Filename;
struct PSPHdr *header;
u_int8_t *psp;
int fsize, i, nc;
Filename = (argc != 2) ? DefaultFile : argv[1];
if (!(PSPFile = fopen(Filename, "r+b")))
{
perror("File cannot be opened.");
exit(1);
}
fseek(PSPFile, 0, SEEK_END);
fsize = ftell(PSPFile);
psp = (u_int8_t*)malloc(fsize);
rewind(PSPFile);
fread(psp, fsize, 1, PSPFile);
fclose(PSPFile);
if (memcmp(pspMagic, psp, 4))
{
printf("WARNING: %s is not a PSP file !\n", Filename);
}
header = (struct PSPHdr*)psp;
printf("=============================================================================\n");
printf("PlayStation Portable PSP File Data\n");
printf("=============================================================================\n");
printf("\nFilename: %s\n", Filename);
//\tFilesize : %i\n", fsize
printf("Exe-Type : %c%c%c%c\t\tFile Type : %08x\n\n"
,header->type[0],header->type[1],header->type[2],header->type[3], le32(header->version));
printf("Title : %s\n", header->title);
printf("Section1 : %04x\t\tSection2 : %04x\n", le16(header->sect1), le16(header->sect2));
// printf("Section : %04x\n", le16(header->sect2));
printf("Size (unenc.) : %i\tEnc-to-Unenc Diff : %i\n", header->size[0], abs(header->size[1] - header->size[0]));
if(int(header->size[1]) == int(fsize)){
printf("Size (enc.) : %i\tequals Filesize : yes\n\n", header->size[1]);
}
else{
printf("Size (enc.) : %i\tEquals Filesize : NO!!!!\n\n", header->size[1]);
}
nc = 0;
for (i = 0; i <= 2; i ++){
printf("Unkown Pointer%i : %08x\tValue: %i\n",i+1, le32(header->unkwn_ptr[i]), header->unkwn_ptr[i]);
}
printf("Section3 : %08x\n\n", le32(header->sect3));
printf("2 x usual NULLs : %08x %08x, followed by %08x\n",le32(header->nulls[0]), le32(header->nulls[1]), le32(header->nulls[2]));
printf("2 x usual NULLs : %08x %08x, followed by %08x (last 3 bytes !?)\n",le32(header->nulls[3]), le32(header->nulls[4]), le32(header->nulls[5]));
printf("Unkown Data : %08x\t Value: %i\n\n", le32(header->nulls[6]), header->nulls[6]);
printf("8 x usual NULLs : %08x %08x %08x %08x\n %08x %08x %08x %08x\n",
le32(header->nulls[7]), le32(header->nulls[8]), le32(header->nulls[9]), le32(header->nulls[10]),
le32(header->nulls[11]), le32(header->nulls[12]), le32(header->nulls[13]), le32(header->nulls[14]));
printf("Unkown Data : %08x\t Value: %i\n\n", le32(header->nulls[15]), header->nulls[15]);
printf("Key/MD5/Encrypted Start Sequence ??\n");
for (i = 16; i < 28; i ++){
printf("%08x ",le32(header->nulls[i]));
if ((i+1)%4==0){
printf("\n");
}
}
if (int(header->nulls[28]) == int(header->size[0])){
printf("\nUnkown Data : %08x\t Value: %i matches Size (unenc.): yes\n", le32(header->nulls[28]), header->nulls[28]);
}
else{
printf("\nUnkown Data : %08x\t Value: %i matches Size (unenc.): NO!\n", le32(header->nulls[28]), header->nulls[28]);
printf(" Size (unenc.): %08x\t Value: %i\n", le32(header->size[0]), header->size[0]);
printf(" Size (enc.) : %08x\t Value: %i\n\n", le32(header->size[1]), header->size[1]);
}
printf("Unkown Data : %08x\t Value: %i hint to %ibit AES ?\n", le32(header->nulls[29]), header->nulls[29], header->nulls[29]);
printf("6 Values (normally NULL) %i, %i, %i, %i, %i, %i followed by 0x%08x\n",header->nulls[30],header->nulls[31], header->nulls[32],header->nulls[33], header->nulls[34], header->nulls[35], le32(header->nulls[36]));
printf("=============================================================================\n");
return 0;
}
Here's the output of the latest Firmware 1.51
=============================================================================
PlayStation Portable PSP File Data
=============================================================================
Filename: firmware\1.51\content\DATA.PSP
Exe-Type : ~PSP File Type : 00080000
Title : updater
Section1 : 0101 Section2 : 0102
Size (unenc.) : 3703968 Enc-to-Unenc Diff : 336
Size (enc.) : 3704304 equals Filesize : yes
Unkown Pointer1 : 18300000 Value: 12312
Unkown Pointer2 : 68430f00 Value: 1000296
Unkown Pointer3 : b45f0300 Value: 221108
Section3 : 40004000
2 x usual NULLs : 00000000 00000000, followed by 004a1000
2 x usual NULLs : 00000000 00000000, followed by 004a1000 (last 3 bytes !?)
Unkown Data : 40702600 Value: 2519104
8 x usual NULLs : 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
Unkown Data : 0c000000 Value: 12
Key/MD5/Encrypted Start Sequence ??
7dd213c7 858fa3b3 0e728038 5f7dd546
a0eb88a2 9ff70b7a 77c9199c cd8a8efb
fc389e7b fec3b73b aa11d9db 28acabbd
Unkown Data : a0843800 Value: 3703968 matches Size (unenc.): yes
Unkown Data : 80000000 Value: 128 hint to 128bit AES ?
6 Values (normally NULL) 0, 0, 0, 0, 0, 0 followed by 0x0000000b
=============================================================================