This file, which I'll call DecryptionControl, is responsible for
decrypting the assets the game uses like music, sprites, etc. The game
uses aes encryption to encrypt the assets, and this file is responsible
for decrypting them. The decryption is done using the RijndaelManaged
class in C#.
The password that the game uses for encryption is "u8DurGE2" and the
salt is "6BBGizHE".
Here is the code the game uses to load and decrypt the assets:
public byte[] load(string in_path)
{
byte[] array = File.ReadAllBytes(in_path);
RijndaelManaged rijndaelManaged = new RijndaelManaged();
rijndaelManaged.KeySize = 128;
rijndaelManaged.BlockSize = 128;
string text = "u8DurGE2";
string text2 = "6BBGizHE";
byte[] bytes = Encoding.UTF8.GetBytes(text2);
Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(text, bytes);
rfc2898DeriveBytes.IterationCount = 1000;
rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);
rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8);
ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor();
byte[] array2 = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
cryptoTransform.Dispose();
return array2;
}
Here's a breakdown of the code:
This function, `load`, takes a file path as an argument and returns a
decrypted byte array.
public byte[] load(string in_path)
It reads all bytes from the file and stores them in a byte array.
byte[] array = File.ReadAllBytes(in_path);
An instance of `RijndaelManaged` is created for AES encryption, with key
and block sizes set to 128 bits.
RijndaelManaged rijndaelManaged = new RijndaelManaged();
rijndaelManaged.KeySize = 128;
rijndaelManaged.BlockSize = 128;
The password and salt are defined, and the salt is converted to a byte
array.
string text = "u8DurGE2";
string text2 = "6BBGizHE";
byte[] bytes = Encoding.UTF8.GetBytes(text2);
A `Rfc2898DeriveBytes` instance is created with the password and salt, and
the iteration count is set to 1000. This generates the key and
initialization vector (IV) for the `RijndaelManaged` instance.
Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(text, bytes);
rfc2898DeriveBytes.IterationCount = 1000;
rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);
rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8);
A decryptor is created, which decrypts the data and stores it in a new
byte array. The decryptor is then disposed of.
ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor();
byte[] array2 = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
cryptoTransform.Dispose();
Finally, the decrypted data is returned.
return array2;
import os
import traceback
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Util.Padding import unpad
import base64
def decrypt_file(file_path, password, salt, key_size=128, block_size=128, iterations=1000):
# Read the encrypted file
with open(file_path, 'rb') as file:
encrypted_data = file.read()
# Derive the key and IV
key_iv = PBKDF2(password, salt.encode(), dkLen=key_size//8 + block_size//8, count=iterations)
key = key_iv[:key_size//8]
iv = key_iv[key_size//8:]
# Create the cipher object and decrypt the data
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_data = unpad(cipher.decrypt(encrypted_data), block_size//8)
return decrypted_data
# Usage
encrypted_folder = '[REPLACE WITH PATH TO FOLDER]'
decrypted_folder = '[REPLACE WITH PATH TO FOLDER]'
password = 'u8DurGE2' # The password used for encryption
salt = '6BBGizHE' # The salt used for encryption
# Lists to keep track of successful and unsuccessful decryptions
successful_decryptions = []
unsuccessful_decryptions = []
# Check if the encrypted folder exists
if not os.path.exists(encrypted_folder):
print(f"Encrypted folder does not exist: {encrypted_folder}")
else:
print(f"Encrypted folder exists: {encrypted_folder}")
# Check if there are any files in the encrypted folder
if not any(os.scandir(encrypted_folder)):
print(f"No files found in encrypted folder: {encrypted_folder}")
else:
print(f"Files found in encrypted folder: {encrypted_folder}")
# Decrypt all files in the encrypted folder and its subfolders
for root, dirs, files in os.walk(encrypted_folder):
for file_name in files:
file_path = os.path.join(root, file_name)
# Create the same subdirectory structure in the decrypted folder
relative_path = os.path.relpath(root, encrypted_folder)
decrypted_root = os.path.join(decrypted_folder, relative_path)
os.makedirs(decrypted_root, exist_ok=True)
# Save the decrypted data to a file in the decrypted folder
decrypted_file_path = os.path.join(decrypted_root, file_name)
# Check if the decrypted file already exists
if os.path.exists(decrypted_file_path):
print(f"File {decrypted_file_path} already exists. Skipping.")
continue
try:
print(f"Decrypting file: {file_path}") # Print the file being decrypted
decrypted_data = decrypt_file(file_path, password, salt)
print(f"Saving decrypted file to: {decrypted_file_path}") # Print the output file path
with open(decrypted_file_path, 'wb') as file:
file.write(decrypted_data)
successful_decryptions.append(file_path)
except Exception as e:
print(f"An error occurred during decryption of file: {file_path}")
print(traceback.format_exc()) # Print the full traceback of the exception
unsuccessful_decryptions.append(file_path)
# Print the successful and unsuccessful decryptions
print(f"Successful decryptions: {len(successful_decryptions)}")
for file_path in successful_decryptions:
print(f"Successfully decrypted: {file_path}")
print(f"Unsuccessful decryptions: {len(unsuccessful_decryptions)}")
for file_path in unsuccessful_decryptions:
print(f"Failed to decrypt: {file_path}")