Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PS3 decrypt key #1

Open
bucanero opened this issue Jan 5, 2024 · 7 comments
Open

PS3 decrypt key #1

bucanero opened this issue Jan 5, 2024 · 7 comments

Comments

@bucanero
Copy link

bucanero commented Jan 5, 2024

Just in case you want to add support for it, I was recently working on MGS5 saves on PS3 / PS4, and reversed the key for PS3: 0x1FBAB234 (532329012)
This key is for the ps3 digital US version NPUB31594, other ps3 versions could require other keys.

I was also doing some bruteforcing to find keys, this is the python script I made:
https://github.com/bucanero/save-decrypters/blob/master/mgs5-tpp-decrypter/samples/findxor.py

my bruteforce solution was to try to find the init value so I could XOR the 4 bytes at offset 0x10 and get the value SVCS.

@mi5hmash
Copy link
Owner

mi5hmash commented Jan 5, 2024

Hello @bucanero, thanks for sharing this news with me.
TBH, I have never felt strong enough to reverse engineer EBOOTs on PS3.
You've given me a reason to dust off my PS3, collect some MGSV SaveData files, and examine them. I am going to use your apollo-ps3 to get rid of the first layer of encryption. BTW, I'm a big fan of this tool and the one for PS4. ;)
After I'm done, I will create a new Profile for my tool and give you credit for finding a key, but this may take a while as I wrote this code over a year ago and I need to stretch my bones. :)
To find the keys for PC and PS4 I took the same approach as you, but I was comparing the result against SVCS or SVAR in the case of MGS5 and gzwi in the case of Ground Zeroes.

@mi5hmash
Copy link
Owner

mi5hmash commented Jan 5, 2024

Also, feel free to use the keys that I found, in your projects:
https://raw.githubusercontent.com/mi5hmash/MGSV_SaveTranslator/main/MGSVProfiles.json

@bucanero
Copy link
Author

bucanero commented Jan 5, 2024

hi @mi5hmash , oh happy to hear that you like my Apollo tools! 😄
I'll be adding your PS4 keys to Apollo-ps4 so users can decrypt/encrypt more MGS5 saves. I'll also add the GZ ones.

When I have a chance, I'll try to help and source some PS3 saves from other regions and check if the key is the same or not. Worst case it's not the same and I'll try the bruteforce-way. Also GZ ps3 keys could be hacked, as I missed those and didn't check at all. Now with your info about offset 0x10 = gzwi that could be fixed too.

btw, about your keys, which region is [PS4] MGSVTPPSaveDataCK ? is that JP/Asian saves?

@mi5hmash
Copy link
Owner

mi5hmash commented Jan 5, 2024

@bucanero
Unfortunately, I no longer have sample files to confirm it, but I'm 99% sure that MGSVTPPSaveDataCK stands for the Asian region.
CK, EU, and NA were the only types I found on PlayerSquared and NGU forums.
I should copycat a good practice from you and store the samples I use in my repos.

After I wrote my bruteforce function, I realized that the key is calculated from the filename without the suffix number.

C#

var fileName = "MGSVTPPSaveDataCK";
var checksum = md5.ComputeHash(Encoding.ASCII.GetBytes(fileName));
var key = (uint)( checksum[0] | checksum[1] << 8 | checksum[2] << 16 | checksum[3] << 24);

Python (translated with ChatGPT)

import hashlib
fileName = "MGSVTPPSaveDataCK"
checksum = hashlib.md5(fileName.encode('ascii')).digest()
key = (checksum[0] | (checksum[1] << 8) | (checksum[2] << 16) | (checksum[3] << 24)) & 0xFFFFFFFF
print("MD5 Checksum:", checksum.hex())
print("32-bit Key:", key)

It worked in my tool for PS4 and PC saves, but not for the ones from PS3.

I have tried to decrypt your samples with your key (as little and big endian) in my tool and did not succeed so my method could be different from yours and my keys could not work with your solution too. I'll try to find out why.

@bucanero
Copy link
Author

bucanero commented Jan 6, 2024

Thanks for the details about the key seed. I checked that it's also valid for the PS3, using the save folder name:

game NPUB31594, save folder NPUB31594_MGS_TPP, md5 = 1fbab23458cc07e2edf6851a953e5938 --> key = 0x1fbab234

Assuming the same for other regions, the ps3 EU digital should be:
md5(NPEB02140_MGS_TPP) = 7b0ed589d6acf657030830fba5b74b34 --> 0x7b0ed589
(I need to decrypt some EU saves to confirm, but I suspect it will be the right key)

Regarding the algorithm, I confirm it's the same for PS3 and PS4, the only issue is that PS3 is a big-endian platform, so you need to endian-swap the values while doing the shifts and XOR operations on a little-endian platform like a PC.
See this C code for reference:

#define ES32(_val) \
	((u32)(((((u32)_val) & 0xff000000) >> 24) | \
	       ((((u32)_val) & 0x00ff0000) >> 8 ) | \
	       ((((u32)_val) & 0x0000ff00) << 8 ) | \
	       ((((u32)_val) & 0x000000ff) << 24)))

void EncData(u32* source, int length)
{
	uint32_t key = 0x1FBAB234;

	for (int i = 0; i < length >> 2; i++)
	{
		key ^= (key << 13);
		key ^= (key >> 7);
		key ^= (key << 5);

		source[i] = ES32(ES32(source[i]) ^ key); // on little-endian saves it would be:  (source[i] ^ key);
	}
}

@mi5hmash
Copy link
Owner

mi5hmash commented Jan 6, 2024

Thank you very much for the tip. I will implement the endian-swap method for the PS3 save files.
Here are the EU PS3 save files:
00000001.zip

@bucanero
Copy link
Author

bucanero commented Jan 6, 2024

Tested and decrypted correctly, key for NPEB02140 is 0x7b0ed589

Game PS3 title ID key
TPP NPUB31594 0x1FBAB234
TPP NPEB02140 0x7b0ed589
TPP NPJB00673 0xe8910fb1
TPP BLES02102 0xdd0dcf0e
TPP BLUS31491 0x22f9710b
TPP BLJM61247 0x4099e562
GZ BLES01971 0xe13943c4
GZ BLUS31369 0x9a25f3f5
GZ BLJM61135 0xd297d9d6
GZ BLAS50697 0x951e18dc
GZ NPEB01889 0xae88976a
GZ NPUB31318 0xc6a8b93d
GZ NPJB00396 0x42bdc79c
#define MGSV_TPP_PS3KEY_BLES02102		0xdd0dcf0e		// md5('BLES02102_MGS_TPP')
#define MGSV_TPP_PS3KEY_BLUS31491		0x22f9710b		// md5('BLUS31491_MGS_TPP')
#define MGSV_TPP_PS3KEY_BLJM61247		0x4099e562		// md5('BLJM61247_MGS_TPP')
#define MGSV_TPP_PS3KEY_NPEB02140		0x7b0ed589		// md5('NPEB02140_MGS_TPP')
#define MGSV_TPP_PS3KEY_NPUB31594		0x1FBAB234		// md5('NPUB31594_MGS_TPP')
#define MGSV_TPP_PS3KEY_NPJB00673		0xe8910fb1		// md5('NPJB00673_MGS_TPP')

#define MGSV_GZ_PS3KEY_BLES01971		0xe13943c4		// md5('BLES01971_MGS_GZ')
#define MGSV_GZ_PS3KEY_BLUS31369		0x9a25f3f5		// md5('BLUS31369_MGS_GZ')
#define MGSV_GZ_PS3KEY_BLJM61135		0xd297d9d6		// md5('BLJM61135_MGS_GZ')
#define MGSV_GZ_PS3KEY_BLAS50697		0x951e18dc		// md5('BLAS50697_MGS_GZ')
#define MGSV_GZ_PS3KEY_NPEB01889		0xae88976a		// md5('NPEB01889_MGS_GZ')
#define MGSV_GZ_PS3KEY_NPUB31318		0xc6a8b93d		// md5('NPUB31318_MGS_GZ')
#define MGSV_GZ_PS3KEY_NPJB00396		0x42bdc79c		// md5('NPJB00396_MGS_GZ')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants