Guest User

remote play pup decrypter

a guest
Apr 12th, 2025
633
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.91 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. import struct
  4. import sys
  5. from Crypto.Cipher import AES
  6. from Crypto.Hash import SHA256
  7. from Crypto.PublicKey import ECC
  8. from Crypto.Signature import DSS
  9.  
  10. update_file = sys.argv[1]
  11. VALIDATE_SIG = True
  12.  
  13. PSP_KEY = bytes.fromhex("3515a88f33557df133fbf208d63b0aaf")
  14.  
  15. OTA_PKG_PUB_PEM = """
  16. -----BEGIN PUBLIC KEY-----
  17. MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElbdJ1xORLXvkIske+h4rUAM/3TKq
  18. KO3PpS/CmHKqICHlGyd2LGnPf/A2+2E+zKdfw1shWsoN5Le/oIbyL0coGQ==
  19. -----END PUBLIC KEY-----
  20. """.strip()
  21.  
  22. ota_pkg_pub = ECC.import_key(OTA_PKG_PUB_PEM)
  23.  
  24. # Get PUP file
  25. with open(update_file, "rb") as fin:
  26.     pupdata = fin.read()
  27.  
  28. # Validate file checksum
  29. pupdata, file_checksum = pupdata[:-32], pupdata[-32:]
  30. h = SHA256.new(pupdata)
  31. assert h.digest() == file_checksum
  32.  
  33. # Parse plaintext header
  34. header_to_verify = pupdata[:64]
  35. magic, pupdata = pupdata[:4], pupdata[4:]
  36. assert magic == b"DWCP"
  37.  
  38. header, pupdata = pupdata[: 4 + 8 + 8 + 4 + 4], pupdata[4 + 8 + 8 + 4 + 4 :]
  39. header_version, file_size, body_size, attribute, reserved = struct.unpack(
  40.     ">IQQII", header
  41. )
  42. print(
  43.     f"header_version={header_version}, file_size={file_size:#x}, body_size={body_size:#x}, attribute={attribute}, reserved={reserved}"
  44. )
  45. header2, pupdata = pupdata[:16], pupdata[16:]
  46. v_major, v_minor, v_patch, v_null = struct.unpack(">IIII", header2)
  47. assert v_null == 0
  48. print(f"version: v{v_major}.{v_minor}.{v_patch}")
  49. iv, pupdata = pupdata[:16], pupdata[16:]
  50.  
  51. # Validate sizes
  52. header_size = file_size - body_size
  53. assert header_size >= 208
  54. assert (header_size - 128 - 32) % 48 == 0
  55.  
  56. # Decrypt metadata block
  57. aes = AES.new(key=PSP_KEY, mode=AES.MODE_CBC, iv=iv)
  58. encrypted_metadata, pupdata = (
  59.     pupdata[: header_size - 64 - 32 - 64],
  60.     pupdata[header_size - 64 - 32 - 64 :],
  61. )
  62. metadata_block = aes.decrypt(encrypted_metadata)
  63.  
  64. # Parse metadata block
  65. assert len(metadata_block) % 48 == 0
  66. metadata = []
  67. while len(metadata_block) > 0:
  68.     key, iv, tag, metadata_block = (
  69.         metadata_block[0:16],
  70.         metadata_block[16:32],
  71.         metadata_block[32:48],
  72.         metadata_block[48:],
  73.     )
  74.     metadata.append((key, iv, tag))
  75. print(f"File pages: {len(metadata)}")
  76.  
  77. # Validate header signature
  78. verifier = DSS.new(ota_pkg_pub, mode="fips-186-3")
  79. h = SHA256.new(header_to_verify + encrypted_metadata)
  80. header_signature, pupdata = pupdata[:64], pupdata[64:]
  81. try:
  82.     verifier.verify(h, header_signature)
  83. except ValueError as e:
  84.     if VALIDATE_SIG:
  85.         raise e
  86.     else:
  87.         print("Warning: Header signature invalid")
  88.  
  89. # Decrypt and verify data
  90. enc_data = pupdata
  91. decdata = b""
  92. for idx, (key, iv, tag) in enumerate(metadata):
  93.     page = enc_data[idx * 0x100000 : (idx + 1) * 0x100000]
  94.     aes = AES.new(key=key, nonce=iv, mode=AES.MODE_GCM)
  95.  
  96.     m = aes.decrypt_and_verify(page, tag)
  97.     decdata += m
  98.  
  99. # Save decrypted file
  100. with open(f"{update_file}.jar", "wb") as fout:
  101.     fout.write(decdata)
  102.  
Advertisement
Add Comment
Please, Sign In to add comment