Created
April 17, 2025 05:06
-
-
Save lincoln-lm/aa09cd89ff338ac5ee0404942d528154 to your computer and use it in GitHub Desktop.
Xenoblade Chronicles X Definitive Edition save file encryption used for files in sts/game (gamedata{:02d}, socialdata, systemdata, avatarmakedata)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import random | |
| CRC_TABLE = [ | |
| 0x46D1E192, | |
| 0x66EDF9AA, | |
| 0x927FC9E5, | |
| 0xA53BAACC, | |
| 0x29B47658, | |
| 0x5A411A01, | |
| 0x0E66D5BD, | |
| 0x0DD5B1DB, | |
| 0xCB38340E, | |
| 0x04D4EBB6, | |
| 0x98BC4F54, | |
| 0x36F20F2C, | |
| 0x4A3047ED, | |
| 0x1EC1E0EB, | |
| 0x568C0C1F, | |
| 0x6A731432, | |
| 0x81367FC6, | |
| 0xE3E25237, | |
| 0xE7F64884, | |
| 0x0FA59F64, | |
| 0x4F3109DE, | |
| 0xF02D61F5, | |
| 0x5DAEC03B, | |
| 0x7F740E83, | |
| 0x056FF2D8, | |
| 0x2026CC0A, | |
| 0x7AC2112D, | |
| 0x82C55605, | |
| 0xB0911EF2, | |
| 0xA7B88E4C, | |
| 0x89DCA282, | |
| 0x4B254D27, | |
| 0x7694A6D3, | |
| 0xD229EADD, | |
| 0x8E8F3738, | |
| 0x5BEE7A55, | |
| 0x012EB6AB, | |
| 0x08DD28C8, | |
| 0xB5ABC274, | |
| 0xBC7931F0, | |
| 0xF2396ED5, | |
| 0xE4E43D97, | |
| 0x943F4B7F, | |
| 0x85D0293D, | |
| 0xAED83A88, | |
| 0xC8F932FC, | |
| 0xC5496F20, | |
| 0xE9228173, | |
| 0x9B465B7D, | |
| 0xFDA26680, | |
| 0x1DDEAB35, | |
| 0x0C4F25CB, | |
| 0x86E32FAF, | |
| 0xE59FA13A, | |
| 0xE192E2C4, | |
| 0xF147DA1A, | |
| 0x67620A8D, | |
| 0x5C9A24C5, | |
| 0xFE6AFDE2, | |
| 0xACAD0250, | |
| 0xD359730B, | |
| 0xF35203B3, | |
| 0x96A4B44D, | |
| 0xFBCACEA6, | |
| 0x41A165EC, | |
| 0xD71E53AC, | |
| 0x835F39BF, | |
| 0x6B6BDE7E, | |
| 0xD07085BA, | |
| 0x79064E07, | |
| 0xEE5B20C3, | |
| 0x3B90BD65, | |
| 0x5827AEF4, | |
| 0x4D12D31C, | |
| 0x9143496E, | |
| 0x6C485976, | |
| 0xD9552733, | |
| 0x220F6895, | |
| 0xE69DEF19, | |
| 0xEB89CD70, | |
| 0xC9BB9644, | |
| 0x93EC7E0D, | |
| 0x2ACE3842, | |
| 0x2B6158DA, | |
| 0x039E9178, | |
| 0xBB5367D7, | |
| 0x55682285, | |
| 0x4315D891, | |
| 0x19FD8906, | |
| 0x7D8D4448, | |
| 0xB4168A03, | |
| 0x40B56A53, | |
| 0xAA3E69E0, | |
| 0xA25182FE, | |
| 0xAD34D16C, | |
| 0x720C4171, | |
| 0x9DC3B961, | |
| 0x321DB563, | |
| 0x8B801B9E, | |
| 0xF5971893, | |
| 0x14CC1251, | |
| 0x8F4AE962, | |
| 0xF65AFF1E, | |
| 0x13BD9DEE, | |
| 0x5E7C78C7, | |
| 0xDDB61731, | |
| 0x73832C15, | |
| 0xEFEBDD5B, | |
| 0x1F959ACA, | |
| 0xE801FB22, | |
| 0xA89826CE, | |
| 0x30B7165D, | |
| 0x458A4077, | |
| 0x24FEC52A, | |
| 0x849B065F, | |
| 0x3C6930CD, | |
| 0xA199A81D, | |
| 0xDB768F30, | |
| 0x2E45C64A, | |
| 0xFF2F0D94, | |
| 0x4EA97917, | |
| 0x6F572ACF, | |
| 0x653A195C, | |
| 0x17A88C5A, | |
| 0x27E11FB5, | |
| 0x3F09C4C1, | |
| 0x2F87E71B, | |
| 0xEA1493E4, | |
| 0xD4B3A55E, | |
| 0xBE6090BE, | |
| 0xAF6CD9D9, | |
| 0xDA58CA00, | |
| 0x612B7034, | |
| 0x31711DAD, | |
| 0x6D7DB041, | |
| 0x8CA786B7, | |
| 0x09E8BF7A, | |
| 0xC3C4D7EA, | |
| 0xA3CD77A8, | |
| 0x7700F608, | |
| 0xDF3DE559, | |
| 0x71C9353F, | |
| 0x9FD236FB, | |
| 0x1675D43E, | |
| 0x390D9E9A, | |
| 0x21BA4C6B, | |
| 0xBD1371E8, | |
| 0x90338440, | |
| 0xD5F163D2, | |
| 0xB140FEF9, | |
| 0x52F50B57, | |
| 0x3710CF67, | |
| 0x4C11A79C, | |
| 0xC6D6624E, | |
| 0x3DC7AFA9, | |
| 0x34A69969, | |
| 0x70544A26, | |
| 0xF7D9EC98, | |
| 0x7C027496, | |
| 0x1BFB3BA3, | |
| 0xB3B1DC8F, | |
| 0x9A241039, | |
| 0xF993F5A4, | |
| 0x15786B99, | |
| 0x26E704F7, | |
| 0x51503C04, | |
| 0x028BB3B8, | |
| 0xEDE5600C, | |
| 0x9CB22B29, | |
| 0xB6FF339B, | |
| 0x7E771C43, | |
| 0xC71C05F1, | |
| 0x604CA924, | |
| 0x695EED60, | |
| 0x688ED0BC, | |
| 0x3E0B232F, | |
| 0xF8A39C11, | |
| 0xBAE6E67C, | |
| 0xB8CF75E1, | |
| 0x970321A7, | |
| 0x5328922B, | |
| 0xDEF3DF2E, | |
| 0x8D0443B0, | |
| 0x2885E3AE, | |
| 0x6435EED1, | |
| 0xCC375E81, | |
| 0xA98495F6, | |
| 0xE0BFF114, | |
| 0xB2DA3E4F, | |
| 0xC01B5ADF, | |
| 0x507E0721, | |
| 0x6267A36A, | |
| 0x181A6DF8, | |
| 0x7BAFF0C0, | |
| 0xFA6D6C13, | |
| 0x427250B2, | |
| 0xE2F742D6, | |
| 0xCD5CC723, | |
| 0x2D218BE7, | |
| 0xB91FBBB1, | |
| 0x9EB946D0, | |
| 0x1C180810, | |
| 0xFC81D602, | |
| 0x0B9C3F52, | |
| 0xC2EA456F, | |
| 0x1165B2C9, | |
| 0xABF4AD75, | |
| 0x0A56FC8C, | |
| 0x12E0F818, | |
| 0xCADBCBA1, | |
| 0x2586BE56, | |
| 0x952C9B46, | |
| 0x07C6A43C, | |
| 0x78967DF3, | |
| 0x477B2E49, | |
| 0x2C5D7B6D, | |
| 0x8A637272, | |
| 0x59ACBCB4, | |
| 0x74A0E447, | |
| 0xC1F8800F, | |
| 0x35C015DC, | |
| 0x230794C2, | |
| 0x4405F328, | |
| 0xEC2ADBA5, | |
| 0xD832B845, | |
| 0x6E4ED287, | |
| 0x48E9F7A2, | |
| 0xA44BE89F, | |
| 0x38CBB725, | |
| 0xBF6EF4E6, | |
| 0xDC0E83FA, | |
| 0x54238D12, | |
| 0xF4F0C1E3, | |
| 0xA60857FD, | |
| 0xC43C64B9, | |
| 0x00C851EF, | |
| 0x33D75F36, | |
| 0x5FD39866, | |
| 0xD1EFA08A, | |
| 0xA0640089, | |
| 0x877A978B, | |
| 0x99175D86, | |
| 0x57DFACBB, | |
| 0xCEB02DE9, | |
| 0xCF4D5C09, | |
| 0x3A8813D4, | |
| 0xB7448816, | |
| 0x63FA5568, | |
| 0x06BE014B, | |
| 0xD642FA7B, | |
| 0x10AA7C90, | |
| 0x8082C88E, | |
| 0x1AFCBA79, | |
| 0x7519549D, | |
| 0x490A87FF, | |
| 0x8820C3A0, | |
| ] | |
| XOR_KEY = b'@\x81\x000A\x81\x010B\x81\x020C\x81\x0c\xffD\x81\x0e\xffE\x81\xfb0F\x81\x1a\xffG\x81\x1b\xffH\x81\x1f\xffI\x81\x01\xffJ\x81\x9b0K\x81\x9c0L\x81\xb4\x00M\x81@\xffN\x81\xa8\x00O\x81>\xffP\x81\xe3\xffQ\x81?\xffR\x81\xfd0S\x81\xfe0T\x81\x9d0U\x81\x9e0V\x81\x030W\x81\xddNX\x81\x050Y\x81\x060Z\x81\x070[\x81\xfc0\\\x81\x15 ]\x81\x10 ^\x81\x0f\xff_\x81\\\x00`\x81\x1c0a\x81\x16 b\x81\\\xffc\x81& d\x81% e\x81\x18 f\x81\x19 g\x81\x1c h\x81\x1d i\x81\x08\xffj\x81\t\xffk\x81\x140l\x81\x150m\x81;\xffn\x81=\xffo\x81[\xffp\x81]\xffq\x81\x080r\x81\t0s\x81\n0t\x81\x0b0u\x81\x0c0v\x81\r0w\x81\x0e0x\x81\x0f0y\x81\x100z\x81\x110{\x81\x0b\xff|\x81\x12"}\x81\xb1\x00~\x81\xd7\x00\x80\x81\xf7\x00\x81\x81\x1d\xff\x82\x81`"\x83\x81\x1c\xff\x84\x81\x1e\xff\x85\x81f"\x86\x81g"\x87\x81\x1e"\x88\x814"\x89\x81B&\x8a\x81@&\x8b\x81\xb0\x00\x8c\x812 \x8d\x813 \x8e\x81\x03!\x8f\x81\xe5\xff\x90\x81\x04\xff\x91\x81\xa2\x00\x92\x81\xa3\x00\x93\x81\x05\xff\x94\x81\x03\xff\x95\x81\x06\xff\x96\x81\n\xff\x97\x81 \xff\x98\x81\xa7\x00\x99\x81\x06&\x9a\x81\x05&\x9b\x81\xcb%\x9c\x81\xcf%\x9d\x81\xce%\x9e\x81\xc7%\x9f\x81\xc6%\xa0\x81\xa1%\xa1\x81\xa0%\xa2\x81\xb3%\xa3\x81\xb2%\xa4\x81\xbd%\xa5\x81\xbc%\xa6\x81; \xa7\x81\x120\xa8\x81\x92!\xa9\x81\x90!\xaa\x81\x91!\xab\x81\x93!\xac\x81\x130\xb8\x81\x08"\xb9\x81\x0b"\xba\x81\x86"\xbb\x81\x87"\xbc\x81\x82"\xbd\x81\x83"\xbe\x81*"\xbf\x81)"\xc8\x81\'"\xc9\x81("\xca\x81\xac\x00\xcb\x81\xd2!\xcc\x81\xd4!\xcd\x81\x00"\xce\x81\x03"\xda\x81 "\xdb\x81\xa5"\xdc\x81\x12#\xdd\x81\x02"\xde\x81\x07"' | |
| def crc32(data: bytes) -> int: | |
| hash_ = len(data) | |
| for byte in data: | |
| hash_ = CRC_TABLE[(hash_ ^ byte) & 0xFF] ^ (hash_ >> 8) | |
| return hash_ | |
| def decrypt(data: bytearray, encryption_index: int) -> bytearray: | |
| for data_index in range(0, len(data) - 4): | |
| data[data_index + 4] ^= data_index & 0xFF | |
| data[data_index + 4] ^= XOR_KEY[encryption_index] ^ 0xFF | |
| encryption_index += 1 | |
| encryption_index &= 0x1FF | |
| def encrypt(data: bytearray, encryption_index: int) -> bytearray: | |
| for data_index in range(0, len(data) - 4): | |
| data[data_index + 4] ^= XOR_KEY[encryption_index] ^ 0xFF | |
| data[data_index + 4] ^= data_index & 0xFF | |
| encryption_index += 1 | |
| encryption_index &= 0x1FF | |
| file_path = input("Filepath: ") | |
| with open(file_path, "rb") as f: | |
| data = bytearray(f.read()) | |
| encryption_index = int.from_bytes(data[0:4], "little") & 0x1FF | |
| print(f"{encryption_index=}") | |
| decrypt(data, encryption_index) | |
| assert len(data[16:]) == int.from_bytes(data[12:16], "little") | |
| assert crc32(data[16:]) == int.from_bytes(data[8:12], "little") | |
| assert int.from_bytes(data[4:8], "little") == 1 | |
| with open(f"{file_path}_decrypted", "wb") as f: | |
| f.write(data) | |
| # ... modify data | |
| # Mersenne Twister 32-bit random number | |
| # seemingly never actually read | |
| random_value = int.from_bytes(random.randbytes(4), "little") | |
| # frames since game boot & 0x1FF | |
| encryption_index = random.randint(0, 0x1FF) | |
| first_value = (random_value & 0xFFFFFE00) | (encryption_index & 0x1FF) | |
| data[0:4] = first_value.to_bytes(4, "little") | |
| data[4:8] = (1).to_bytes(4, "little") | |
| data[8:12] = crc32(data[16:]).to_bytes(4, "little") | |
| data[12:16] = len(data[16:]).to_bytes(4, "little") | |
| encrypt(data, encryption_index) | |
| with open(f"{file_path}_modified", "wb") as f: | |
| f.write(data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment