Skip to content

Instantly share code, notes, and snippets.

@OlivierLaflamme
Created August 12, 2026 21:40
Show Gist options
  • Select an option

  • Save OlivierLaflamme/23d376cf57b389cd8f899e8532fb45ca to your computer and use it in GitHub Desktop.

Select an option

Save OlivierLaflamme/23d376cf57b389cd8f899e8532fb45ca to your computer and use it in GitHub Desktop.
decrypt_upk.py
#!/usr/bin/env python3
import struct, hashlib, sys
TEA_DELTA = 0x9e3779b9
TEA_ROUNDS = 16
TEA_MAGIC = b'TEA\x00'
KEY_CONST_1 = 0x6e35ba0c
KEY_CONST_2 = 0x9a8b7c6e
def derive_key(seed):
t = seed & 0xFFFFFFFF
out = []
for i in range(16):
t = (i + (t ^ KEY_CONST_2)) & 0xFFFFFFFF
t = (t + KEY_CONST_1) & 0xFFFFFFFF
out.append(t & 0xFF)
return bytes(out)
def tea_decrypt(v0, v1, key):
k0, k1, k2, k3 = struct.unpack('<4I', key)
s = (TEA_DELTA * TEA_ROUNDS) & 0xFFFFFFFF
for _ in range(TEA_ROUNDS):
v1 = (v1 - (((v0 << 4) + k2) ^ (v0 + s) ^ ((v0 >> 5) + k3))) & 0xFFFFFFFF
v0 = (v0 - (((v1 << 4) + k0) ^ (v1 + s) ^ ((v1 >> 5) + k1))) & 0xFFFFFFFF
s = (s - TEA_DELTA) & 0xFFFFFFFF
return v0, v1
def main():
if len(sys.argv) < 2:
print(f"usage: {sys.argv[0]} <file.upk> [out.tar]")
sys.exit(1)
data = open(sys.argv[1], 'rb').read()
# offsets from bin4ry uniteabag.
assert data[:4] == b'UTPK'
name = data[48:112].split(b'\x00')[0].decode()
seed = data[28:32]
sign1 = data[32:40]
sign2 = data[40:48]
pl_sz = struct.unpack('<Q', data[16:24])[0]
ftype = data[24]
key = derive_key(int.from_bytes(seed, 'little'))
print(f"package : {name}")
print(f"seed : {seed.hex()}")
print(f"key : {key.hex()}")
print(f"size : {pl_sz} bytes (type={ftype})")
payload = data[112:112 + pl_sz]
md5 = hashlib.md5(payload).digest()
if md5 == sign1 + sign2:
print("md5 : ok")
else:
print(f"md5 : FAIL (expected {sign1.hex()}{sign2.hex()}, got {md5.hex()})")
assert payload[:4] == TEA_MAGIC
encrypted = payload[4:]
out = bytearray()
for i in range(0, len(encrypted), 8):
v0, v1 = struct.unpack_from('<II', encrypted, i)
d0, d1 = tea_decrypt(v0, v1, key)
out.extend(struct.pack('<II', d0, d1))
# lol
if out[257:262] == b'ustar':
print("format : tar (ustar)")
else:
print(f"format : unknown (starts with {bytes(out[:32]).hex()})")
output = sys.argv[2] if len(sys.argv) > 2 else sys.argv[1].replace('.upk', '.tar')
open(output, 'wb').write(bytes(out))
print(f"saved : {output} ({len(out)} bytes)")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment