Last active
May 31, 2024 12:46
-
-
Save khang06/dde2c333614b21ac6350f38c50662c45 to your computer and use it in GitHub Desktop.
PublicProfile.save encryption/decryption tool for Bloons TD Battles 2 1.0.4
This file contains 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 binascii | |
import sys | |
import string | |
import os | |
# the checksum algorithm operates on signed integers | |
def arsh32(n, b): | |
n = n & 0xFFFFFFFFF | |
n = (n ^ 0x80000000) - 0x80000000 | |
return (n >> b) & 0xFFFFFFFF | |
def checksum(data): | |
ret = 0 | |
for i in range(len(data)): | |
temp = (ret ^ data[i]) & 0xFF | |
if (temp & 1) != 0: | |
temp = arsh32(temp ^ 0xDB710641, 1) | |
else: | |
temp = arsh32(temp, 1) | |
for j in range(7): | |
if j != 0: | |
temp = arsh32(temp, 1) | |
if (temp & 1) != 0: | |
temp ^= 0xDB710641 | |
ret = arsh32(temp, 1) ^ arsh32(ret, 8) & 0xFFFFFF | |
return ret | |
# no scanf in python | |
def scan_hex(file): | |
out = "" | |
while True: | |
try: | |
char = file.read(1).decode("utf-8") | |
if char in string.hexdigits: | |
out += char | |
else: | |
break | |
except UnicodeDecodeError: | |
break | |
file.seek(-1, os.SEEK_CUR) | |
return int(out, 16) | |
def stephen_encrypt(data): | |
for i in range(len(data)): | |
data[i] += i % 6 + 21 | |
def stephen_decrypt(data): | |
for i in range(len(data)): | |
data[i] += 6 * (i // 6) - i - 21 | |
def decrypt_save(in_file, out_file): | |
with open(in_file, "rb") as save: | |
magic = save.read(6) | |
if magic != b"DGDATA": | |
print("wrong magic") | |
return | |
stored_crc = scan_hex(save) | |
print(f"stored checksum: {hex(stored_crc)}") | |
data = bytearray(save.read()) | |
stephen_decrypt(data) | |
calced_crc = checksum(data) | |
if stored_crc == calced_crc: | |
print(f"checksum OK") | |
else: | |
print(f"checksum mismatch! (calculated: {hex(calced_crc)})") | |
with open(out_file, "wb") as dec: | |
dec.write(data) | |
def encrypt_save(in_file, out_file): | |
with open(in_file, "rb") as dec: | |
data = bytearray(dec.read()) | |
calced_crc = checksum(data) | |
stephen_encrypt(data) | |
data = bytearray(f"DGDATA{calced_crc:08x}", encoding="utf8") + data | |
with open(out_file, "wb") as save: | |
save.write(data) | |
if __name__ == "__main__": | |
if len(sys.argv) != 4: | |
print(f"usage: {sys.argv[0]} [decrypt/encrypt] [in] [out]") | |
sys.exit(1) | |
if sys.argv[1] == "decrypt": | |
decrypt_save(sys.argv[2], sys.argv[3]) | |
elif sys.argv[1] == "encrypt": | |
encrypt_save(sys.argv[2], sys.argv[3]) | |
else: | |
print("invalid mode!") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ok