Editing PARAM.PFD
Jump to navigation
Jump to search
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
[[Category:Software]] | |||
[[ | |||
==Description== | ==Description== | ||
This files are responsible to prevent tampering of other files of the same folder, the only purpose is the security of the folder contents. Contains the cryptographic signatures of other files of the same folder (not all, but the ones that developers decided to be important enought to be secured). | |||
Its used in several paths of the PS3, usually to secure data related with the user profile e.g: | Its used in several paths of the PS3, usually to secure data related with the user profile e.g: | ||
/dev_hdd0/home/0000000*/savedata/SAVEDATA_DIRECTORY/PARAM.PFD <---- in all save game folders | /dev_hdd0/home/0000000*/savedata/SAVEDATA_DIRECTORY/PARAM.PFD <---- in all save game folders | ||
/dev_hdd0/home/0000000*/trophy/NPCOMMID/PARAM.PFD <--- in all | /dev_hdd0/home/0000000*/trophy/NPCOMMID/PARAM.PFD <--- in all trohpy folders | ||
/dev_hdd0/home/0000000*/trophy/_TROPSYS_/PARAM.PFD <---- in the "user trophy index" folder | /dev_hdd0/home/0000000*/trophy/_TROPSYS_/PARAM.PFD <---- in the "user trophy index" folder | ||
Line 26: | Line 22: | ||
==Structure== | ==Structure== | ||
''' | '''Header''' (120 bytes) | ||
'''X table''' (456 bytes) | '''X table''' (456 bytes) | ||
'''Protected files table'''(31008 bytes) | '''Protected files table'''(31008 bytes) | ||
Line 33: | Line 28: | ||
'''Padding''' (44 bytes) | '''Padding''' (44 bytes) | ||
Total file size = | Total file size = 120+456+31008+1140+44 = 32768 bytes (0x8000) | ||
The size of the file is fixed because the number of entries in both '''X table''' & '''Y table''' is 57 (when the entry is not used his position is marked as "not-used"). In the same way... the '''Protected files table''' has an area reserved for a maximun of 114 entries (not used entries are filled with zeroes). As result the file contains the maximun number of possible entries | |||
The size of the file is fixed because the number of entries in both '''X table''' & '''Y table''' is 57 (when the entry is not used | |||
*Useful game saves used in this page as examples | *Useful game saves used in this page as examples | ||
**http://www.gamefaqs.com/ps3/941950-mirrors-edge/saves ( | **http://www.gamefaqs.com/ps3/941950-mirrors-edge/saves (the first one region North America). Mirror: http://www.multiupload.nl/SWJ4Y4H7ER | ||
**http://www.gamefaqs.com/ps3/933123-heavy-rain/saves | **http://www.gamefaqs.com/ps3/933123-heavy-rain/saves | ||
The structure of the PARAM.PFD used in Mirror's edge game save can be considered "rare", this wiki page uses this file for explaining the structure because is perfect to understand how it works, the structure contains all the "problems" not present in "standard" files that can be considered unknown... there are other game saves that can be used (MotoGP10, Heavy rain)... but the list of protected files in heavy rain contains more than 100 files (use heavy rain if you are coding an app as a "stress test") | The structure of the PARAM.PFD used in Mirror's edge game save can be considered "rare", this wiki page uses this file for explaining the structure because is perfect to understand how it works, the structure contains all the "problems" not present in "standard" files that can be considered unknown... there are other game saves that can be used (MotoGP10, Heavy rain)... but the list of protected files in heavy rain contains more than 100 files (use heavy rain if you are coding an app as a "stress test") | ||
=== | ===Header=== | ||
From | From 0x0 to 0x78 | ||
Size = | Size = 120 bytes | ||
The end of the header is not clear at first sight, but it can be deduced by counting the number of entries in '''X table''' & '''Y table''' and comparing the positions used in both. e.g: look for one used entry in the "Y table" and count his position in this table... then look for other used entry in the "X" (both tables matches in the used entries). Then count towards behind to find the first entry (the start of the first entry is the start of the '''X table'''). So the start of the '''X table''' is the end offset of the header | |||
*Mirror's edge game save '''Header''' | |||
0000 00 00 00 00 50 46 44 42 00 00 00 00 00 00 00 03 |....PFDB........| | |||
*Mirror's edge game save ''' | 0010 69 15 2C 97 81 2B 25 C5 2A D4 FA 18 E4 B8 16 A8 |i.,..+%.*.......| | ||
0020 7C 1F 5C 28 A7 EE 4D 39 22 AD C8 28 E6 CD 78 88 ||.\(..M9"..(..x.| | |||
0030 98 0F 33 B6 23 94 EE E9 97 06 77 4E 71 91 24 13 |..3.#.....wNq.$.| | |||
0040 A7 CF DB E5 E3 8E 8D 0C 5B CF 88 07 FC B7 B5 9C |........[.......| | |||
0050 4C 5A 3D 98 39 04 B6 CE ED E2 71 52 AA 9C 2F 85 |LZ=.9.....qR../.| | |||
0060 00 00 00 00 00 00 00 39 00 00 00 00 00 00 00 72 |.......9.......r| | |||
0070 00 00 00 00 00 00 00 21 |.......! | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Value !! Description !! Notes | |||
|- | |- | ||
| 0x00 || 0x08 bytes || PFDB || Magic value || in ASCII | |||
|- | |- | ||
| 0x08 || 0x08 | | 0x08 || 0x08 bytes || 00000000 00000003 || '''constant''' || | ||
|- | |- | ||
| 0x10 || 0x10 | | 0x10 || 0x10 bytes || 69152C97 812B25C5 2AD4FA18 E4B816A8 || random bytes ??? || Key to en/decrypt | ||
|- | |- | ||
| 0x20 || 0x14 bytes || 7C1F5C28 A7EE4D39 22ADC828 E6CD7888 980F33B6 || '''hmac sha1''' || Encrypted, decrypted by vtrm | |||
|- | |- | ||
| 0x34 || 0x14 | | 0x34 || 0x14 bytes || 2394EEE9 9706774E 71912413 A7CFDBE5 E38E8D0C || '''hmac sha1''' || Encrypted, decrypted by vtrm | ||
|- | |- | ||
| 0x48 || 0x14 | | 0x48 || 0x14 bytes || 5BCF8807 FCB7B59C 4C5A3D98 3904B6CE EDE27152 || '''hmac sha1'''. Encrypted, decrypted by vtrm | ||
|- | |- | ||
| 0x5C || 0x04 | | 0x5C || 0x04 bytes || AA9C2F85 || '''padding''' || encrypted by vtrm | ||
|- | |- | ||
| 0x60 || 0x08 bytes || 0000000000000039 || Number of reserved entries in the '''X table''' & '''Y table''' (57 in decimal) || ??? seems correct in all the examples found, but is speculation | |||
| 0x60 || 0x08 bytes || 0000000000000039 || '''X | |||
|- | |- | ||
| 0x68 || 0x08 bytes || 0000000000000072 || '''Protected files table | | 0x68 || 0x08 bytes || 0000000000000072 || Number of reserved entries in the '''Protected files table''' (114 in decimal) || ??? seems correct in all the examples found, but is speculation | ||
|- | |- | ||
| 0x70 || 0x08 bytes || 0000000000000021 || '''Protected files table | | 0x70 || 0x08 bytes || 0000000000000021 || Number of used entries in the '''Protected files table''' (33 in decimal) || Can vary, from 1 to 114 in decimal (or from 0x00 to 0x71) | ||
|- | |- | ||
|} | |} | ||
===X | *Note: The last 3 entries (from 0x60 to 0x78) probably are not part of the file header... probably must be considered the "header of the next table" (X table), but by now is more simple to explain the structure this way, and is not a big problem to fix later | ||
===X table=== | |||
From 0x78 to 0x240 | From 0x78 to 0x240 | ||
Size = 456 bytes | Size = 456 bytes | ||
Entry | Entry lenght = 8 bytes | ||
Number of entries = 57 | Number of entries = 57 | ||
Each entry can contain a "file index" | Each entry can contain a "file index" that points to the '''Protected files table''' from 0x00 to 0x71 (from 1 to 114 in decimal) | ||
If the "file index" is 72 | If the "file index" is 72 it means that is pointing out of the '''Protected files table''' (not used) | ||
The first | The table does not fills with entries from top to bottom, usually the first entries are not used (marked as 72) followed by entries with whatever number from 0 to 71, and mixed with more 72's entries | ||
Used entries has a number asigned by his position in the table e.g: | |||
Used entries has a number | |||
*Mirror's edge game save '''X table''' | *Mirror's edge game save '''X table''' | ||
Line 193: | Line 102: | ||
0090 00 00 00 00 00 00 00 '''0C''' 00 00 00 00 00 00 00 72 |...............r| | 0090 00 00 00 00 00 00 00 '''0C''' 00 00 00 00 00 00 00 72 |...............r| | ||
00a0 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00 '''1F''' |.......r........| | 00a0 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00 '''1F''' |.......r........| | ||
00b0 00 00 00 00 00 00 00 '''10''' | 00b0 00 00 00 00 00 00 00 '''10''' 00 00 00 00 00 00 00 '''1B''' |................| | ||
00c0 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00 '''14''' |.......r........| | 00c0 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00 '''14''' |.......r........| | ||
00d0 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00 72 |.......r.......r| | 00d0 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00 72 |.......r.......r| | ||
Line 239: | Line 148: | ||
|- | |- | ||
| 8 || 0x10 | | 8 || 0x10 | ||
|- | |- | ||
| 9 || 0x1B | | 9 || 0x1B | ||
|- | |- | ||
Line 359: | Line 268: | ||
From 0x240 to 0x7B60 | From 0x240 to 0x7B60 | ||
Size = 31008 bytes | Size = 31008 bytes | ||
Entry | Entry lenght = 272 bytes | ||
Number of | Number of entries = variable from 1 to 114 | ||
Each entry can store the signature of one of the files in the folder, there is always an entry used to store the signature of [[PARAM.SFO]], this gives a maximun number of protected files generated by the game of 113 | |||
Used entries fills the table from top to bottom, not-used entries are placed at the end of the table filled with zeroes | |||
The first 8 bytes of each entry (file index) works in the same way than the entries in the '''X table''', usually not used (72) and when used are randmonly placed asigning an "file index" to the entry | |||
This "file index" does not matches with the position of the entry in the '''Protected files table''' itself... so seems that this "indexes files" are ???virtually reordered??? | |||
In fact, for a theoricall file with alll entries used, half of the "file index" numbers will be spreaded between the '''X table''' (can only contain 57) ant the first 8 bytes of some entries in the '''Protected files table''' | |||
*Mirror's edge game save '''Protected Files Table''' | *Mirror's edge game save '''Protected Files Table''' | ||
8 entries used in this table | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 447: | Line 340: | ||
|- | |- | ||
| 27 || {{No}} || SAV35.BIN || 00568CD8 || || 00008E2E | | 27 || {{No}} || SAV35.BIN || 00568CD8 || || 00008E2E | ||
|- | |- | ||
| 28 || 0x00 || SAVTOC1.BIN || 00568CD8 || || 00000108 | | 28 || 0x00 || SAVTOC1.BIN || 00568CD8 || || 00000108 | ||
|- | |- | ||
Line 464: | Line 357: | ||
|} | |} | ||
===Y | *Each entry has this structure | ||
{| class="wikitable" | |||
|- | |||
! Size !! Value !! Description | |||
|- | |||
| 008 bytes || 00000000000000** || File index (value 72 = Not indexed) | |||
|- | |||
| 064 bytes || EXAMPLE.WTF || Name of the file included the point and the extension in ASCII (Null-terminated) | |||
|- | |||
| 008 bytes || :Wtf-o0- || In ASCII, Usually zeroed (crysis2 savedata contains the string "CELL" and heavenly sword contains "s:Music") ???Unknown??? | |||
|- | |||
| 188 bytes || ????????... || Certificate for the file. When the file is PARAM.SFO then the certificate is bigger in size and uses imput data from the attribute "PARAMS" and/or "ACCOUNT_ID" inside PARAM.SFO. Method unknown (Null-terminated) | |||
|- | |||
| 004 bytes || 1A2B3C4D|| Size of the file in bytes | |||
|- | |||
|} | |||
===Y table=== | |||
From 0x7B60 to 0x7FD4 | From 0x7B60 to 0x7FD4 | ||
Size = 1140 bytes | Size = 1140 bytes | ||
Entry | Entry lenght = 20 bytes (some kind of sha-1 hash??) | ||
Number of entries = 57 | Number of entries = 57 | ||
Is directly related with the '''X table''', both matches in the total number of entries (57) and | Is directly related with the '''X table''', both matches in the total number of entries (57) and wich ones are used (e.g. when the '''X table''' has a entry in position 12... the '''Y table''' has position 12 used) | ||
All the entries contains the same "20 bytes string", only the used entries contains a different "20 bytes string" (in a theoricall PARAM.PFD with no files listed, the "Y table" would have all his 57 entries with the same string) | |||
The '''Y table''' has a repeating pattern so an entry for each potential file with the blank entry (I.E. no file) being represented by the repeating byte pattern. | The '''Y table''' has a repeating pattern so an entry for each potential file with the blank entry (I.E. no file) being represented by the repeating byte pattern. | ||
Line 498: | Line 408: | ||
|- | |- | ||
| 8 || 6B88527E002E78DB1D915573DD44951F0CBE6A3C | | 8 || 6B88527E002E78DB1D915573DD44951F0CBE6A3C | ||
|- | |- | ||
| 9 || 703F1A6F0A576A8D85E8EB35B30FE5DAB7689988 | | 9 || 703F1A6F0A576A8D85E8EB35B30FE5DAB7689988 | ||
|- | |- | ||
Line 605: | Line 515: | ||
Not much to say about this padding, is an area filled with zeroes to increase the size of the file to 32768 bytes (0x8000) | Not much to say about this padding, is an area filled with zeroes to increase the size of the file to 32768 bytes (0x8000) | ||
==Cryptography and Speculation== | |||
===The "virtual index"=== | ===The "virtual index"=== | ||
Mirror's edge has a total of 33 "protected files" (listed in the protected files table)... this number matches with the 33 "indexed" numbers that are spreading between "X table" and "protected files table" itself... if we place all the entries from all tables together we can reorder all by using | Mirror's edge has a total of 33 "protected files" (listed in the protected files table)... this number matches with the 33 "indexed" numbers that are spreading between "X table" and "protected files table" itself... if we place all the entries from all tables together we can reorder all by using his ID number in a "virtual index" | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Index ID !! | ! Virtual Index ID !! X Table position !! Y table hash ? (same position than X table) !! Protected Files Table (position) !! Protected Files Table (File Name) | ||
|- | |- | ||
| 0x00 || {{no}} || {{no}} || 28 || SAVTOC1.BIN | |||
|- | |- | ||
| 0x01 | | 0x01 || 2 || 83C16E92F5F5FAAF19A00810186E82A9313AADAD || {{no}} || {{No}} | ||
|- | |- | ||
| 0x02 | | 0x02 || {{no}} || {{no}} || 22 || SAV18.BIN | ||
|- | |- | ||
| 0x03 | | 0x03 || 47 || D5097670CAF4186E89009EF031FD721FE3C3E083 || {{No}} || {{no}} | ||
|- | |- | ||
| 0x04 | | 0x04 || 36 || E81D24D0EF67CDC849260668B2A99F982C545929 || {{No}} || {{no}} | ||
|- | |- | ||
| 0x05 | | 0x05 || {{no}} || {{no}} || 24 || SAV1.BIN | ||
|- | |- | ||
| 0x06 | | 0x06 || {{no}} || {{no}} || 14 || SAV0.BIN | ||
|- | |- | ||
| 0x07 | | 0x07 || 40 || 4CB48133E388EDBCF0E0AD0DB6CD55020CB03342|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x08 | | 0x08 || {{no}} || {{no}} || 30 || SAV26.BIN | ||
|- | |- | ||
| 0x09 | | 0x09 || {{no}} || {{no}} || 31 || SAV27.BIN | ||
|- | |- | ||
| 0x0A | | 0x0A || {{no}} || {{no}} || 32 || SAV28.BIN | ||
|- | |- | ||
| 0x0B | | 0x0B || 14 || C45F773837AE76FAF3D662974438CE7FD620D2D0 || {{No}} || {{no}} | ||
|- | |- | ||
| 0x0C | | 0x0C || 4 || 28458FC13B00ED44EF5FA5BED55D016E94066099|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x0D | | 0x0D || 15 || 6BE399A6B97F6158C6194ED6C8CC6A1B2AD6ADDB || {{No}} || {{no}} | ||
|- | |- | ||
| 0x0E | | 0x0E || 25 || 41534126B047CE6AADC6606C24766246C4F712D7 || {{No}} || {{no}} | ||
|- | |- | ||
| 0x0F | | 0x0F || 54 || E40D4A3ABB1EEB92A1BEF55B7730AB6BB5CDDB2D|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x10 | | 0x10 || 8 || 6B88527E002E78DB1D915573DD44951F0CBE6A3C|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x11 | | 0x11 || 26 || 08F26808FB5A47B4E35E71DDAA3167CD5CD08D75|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x12 | | 0x12 || 33 || B08D1FAB5A5FA370B5FF2930024CE7CAC9F08234|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x13 | | 0x13 || 21 || 1B9491E3F006528C387F4A8FAD75455E9780EF0D|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x14 | | 0x14 || 11 || EFAF21CD389AC84662601AC5B449AE12CCF739F9|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x15 | | 0x15 || 18 || 933E85E3651EC32C05929CAD2CD23081BC975E9C|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x16 | | 0x16 || {{no}} || {{no}} || 25 || SAV23.BIN | ||
|- | |- | ||
| 0x17 | | 0x17 || 22 || A69EC11F680BCDC8260CDF38FA47C3FCD1D16495|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x18 | | 0x18 || 29 || 71A20B8F36D2853E4E84AB998AD201A0AC8C629C|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x19 | | 0x19 || 19 || 323A62857BAD6BD1D3B1ED8584723CC36C4D915D|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x1A | | 0x1A || 32 || 18BA71B3CEC1CCCDAD3395323C4259D72B1EF5E0|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x1B | | 0x1B || 9 || 703F1A6F0A576A8D85E8EB35B30FE5DAB7689988|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x1C | | 0x1C || 39 || 6347B31E98FA9A58195AB5D9ED1548A46CFE6FCE|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x1D | | 0x1D || 50 || 49481F76A9C591E03CA1B115D0FC9737A48837A3|| {{No}} || {{no}} | ||
|- | |- | ||
| 0x1E | | 0x1E || 57 || C1CE8AF37CA63059B835B2D6CD64E506B2E55397 || {{No}} || {{no}} | ||
|- | |- | ||
| 0x1F | | 0x1F || 7 || 42CBF8134469B91F541DCF76CC4934E9F6CDEDC6 || {{No}} || {{no}} | ||
|- | |- | ||
| 0x20 | | 0x20 || 53 || 389ED925282AFEC432D2A1F042E0043D0E91F785|| {{No}} || {{no}} | ||
|- | |- | ||
|} | |} | ||
===More brainstorming=== | ===More brainstorming=== | ||
Entries in the '''Protected files table''' (114) is exactly the double than the entries in '''X table''' (57) & '''Y table''' (57) | |||
Unknown by now, but some questions rises... | |||
Why the files are listed in this order and not in other in the "files table" ? | |||
Because are not listed alphabetically, neither by size | |||
Indexes files (in the '''X table''') seems to have different number for every one, never repeats, but there is not direct relationship between the number of entries in '''X table''' & '''Y table''' (both are fixed to 57) and the numer of files listed in the '''Protected files table''' (114)... the most logicall explain if that this 114 files can be linked to | |||
both tables (57 each)... but in fact the only table that stores crypto is the '''Y table''' (limited to 57)... so what trick they used ? hmmmm | |||
What are this index in the '''X table''' and in the '''Protected files table''' itself?, his positions seems to be random, seems like an old school "lucas arts games" anticheat card where you pick 2 values and by mixing them you get the unlock code :D | |||
But here what is random is the positions, and index numbers of the entries in the '''X table''', and the indexed files in the '''Protected files table''' ??? 2 index ??? | |||
Discussion thread ---> http://www.ps3hax.net/showthread.php?p=392684#post392684 | |||