Перейти к содержимому
Zone of Games Forum
SerGEAnt

Сообщение добавлено пользователем SerGEAnt

Рекомендованные сообщения

3 часа назад, KetsuNeko сказал:

... и главное - интерес к проекту...

... но как по мне - игра не стоит потраченного времени которого у меня и так нет….

Хм… 

Поделиться сообщением


Ссылка на сообщение
2 часа назад, parabelum сказал:

Хм… 

слова из контекста вырывать не нужно. ты же понял о чём я. если нет то поясню — нет времени искать ключи к зашифрованному тексту, так как это очень сложно и долго.  

Поделиться сообщением


Ссылка на сообщение
2 часа назад, KetsuNeko сказал:

слова из контекста вырывать не нужно. ты же понял о чём я. если нет то поясню — нет времени искать ключи к зашифрованному тексту, так как это очень сложно и долго.  

Дружище, я больше на это обратил внимание “игра не стоит потраченного времени”.

Просто если мне проект не нравиться, я за него не берусь.

Поделиться сообщением


Ссылка на сообщение

Да что там искать то.
Алгоритм: Rijndael (AES) с BlockSize=256
Режим: CBC
1. Base64 decode
2. AES decrypt

Ключи:
 

// PROJECT_KEY (32 байта):
{ 219, 213, 3, 55, 151, 160, 65, 59, 242, 96,
  31, 17, 243, 131, 158, 221, 122, 115, 147, 122,
  205, 191, 88, 227, 80, 100, 140, 248, 78, 102,
  60, 234 }

// PROJECT_IV (32 байта):
{ 81, 195, 46, 43, 97, 91, 5, 227, 111, 244,
  215, 186, 50, 37, 107, 101, 5, 187, 155, 119,
  95, 250, 46, 209, 20, 35, 193, 244, 114, 104,
  6, 95 }

 

// SAVE_KEY

{    27, 117, 138, 231, 251, 254, 7, 22, 50, 123,
    121, 215, 107, 234, 218, 206, 77, 83, 236, 75,
    219, 54, 229, 6, 7, 199, 128, 40, 77, 148,
    57, 55
])

// SAVE_IV

{    206, 175, 60, 42, 180, 134, 58, 221, 48, 202,
    108, 66, 58, 244, 162, 215, 25, 216, 205, 207,
    94, 228, 62, 10, 246, 178, 148, 101, 106, 226,
    146, 157
])

Я конечно не знаю в каких файлах тексты, может в других шифрованиях если есть. Но xmldata этим декодируется.

uu5hC3o.png

Набрасал вейбкодинг:

Скрытый текст

#!/usr/bin/env python3
"""
ORK Framework XML Data Decryptor
Decrypts encrypted xmlData from ORK Framework games (like Marchen Forest)

Algorithm: Rijndael (AES variant) with 256-bit block size, CBC mode
"""

import base64
import argparse
import sys
from pathlib import Path

# Скрипт не требует внешних зависимостей - используется встроенная реализация Rijndael256

# Ключи для данных проекта (xmlData)
PROJECT_KEY = bytes([
    219, 213, 3, 55, 151, 160, 65, 59, 242, 96,
    31, 17, 243, 131, 158, 221, 122, 115, 147, 122,
    205, 191, 88, 227, 80, 100, 140, 248, 78, 102,
    60, 234
])

PROJECT_IV = bytes([
    81, 195, 46, 43, 97, 91, 5, 227, 111, 244,
    215, 186, 50, 37, 107, 101, 5, 187, 155, 119,
    95, 250, 46, 209, 20, 35, 193, 244, 114, 104,
    6, 95
])

# Ключи для сохранений игры (savegame)
SAVE_KEY = bytes([
    27, 117, 138, 231, 251, 254, 7, 22, 50, 123,
    121, 215, 107, 234, 218, 206, 77, 83, 236, 75,
    219, 54, 229, 6, 7, 199, 128, 40, 77, 148,
    57, 55
])

SAVE_IV = bytes([
    206, 175, 60, 42, 180, 134, 58, 221, 48, 202,
    108, 66, 58, 244, 162, 215, 25, 216, 205, 207,
    94, 228, 62, 10, 246, 178, 148, 101, 106, 226,
    146, 157
])


def decrypt_rijndael_256(encrypted_base64: str, key: bytes, iv: bytes) -> str:
    """
    Расшифровывает данные, зашифрованные Rijndael с BlockSize=256.
    Используется встроенная реализация Rijndael256.
    """
    # Декодируем Base64
    encrypted_data = base64.b64decode(encrypted_base64)
    
    # Используем встроенную реализацию Rijndael-256
    decrypted = rijndael_cbc_decrypt(encrypted_data, key, iv)
    
    # Убираем padding (PaddingMode.Zeros)
    decrypted = decrypted.rstrip(b'\x00')
    
    # Декодируем в строку
    text = decrypted.decode('utf-8', errors='replace')
    
    # Извлекаем содержимое между { и }
    return get_enclosed(text, '{', '}')


def get_enclosed(text: str, begin: str, end: str) -> str:
    """Извлекает содержимое между begin и end маркерами."""
    start_idx = text.find(begin)
    if start_idx == -1:
        return text
    
    start_idx += len(begin)
    end_idx = text.rfind(end)
    
    if end_idx == -1 or end_idx <= start_idx:
        return text
    
    return text[start_idx:end_idx]


# ============ Rijndael-256 Implementation ============

def rijndael_cbc_decrypt(data: bytes, key: bytes, iv: bytes, block_size: int = 32) -> bytes:
    """
    Расшифровывает данные с использованием Rijndael CBC с BlockSize=256 бит (32 байта).
    """
    cipher = Rijndael256(key)
    
    result = bytearray()
    prev_block = iv
    
    for i in range(0, len(data), block_size):
        block = data[i:i + block_size]
        decrypted_block = cipher.decrypt_block(block)
        
        # XOR с предыдущим блоком (CBC)
        xored = bytes(a ^ b for a, b in zip(decrypted_block, prev_block))
        result.extend(xored)
        prev_block = block
    
    return bytes(result)


class Rijndael256:
    """
    Минимальная реализация Rijndael с BlockSize=256 бит.
    """
    
    # S-box для Rijndael
    SBOX = [
        0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
        0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
        0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
        0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
        0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
        0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
        0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
        0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
        0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
        0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
        0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
        0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
        0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
        0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
        0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
    ]
    
    # Inverse S-box
    SBOX_INV = [
        0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
        0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
        0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
        0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
        0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
        0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
        0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
        0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
        0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
        0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
        0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
        0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
        0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
        0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
        0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
        0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
    ]
    
    # Round constants
    RCON = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a]
    
    def __init__(self, key: bytes):
        self.Nb = 8  # BlockSize / 32 = 256 / 32 = 8
        self.Nk = len(key) // 4  # KeySize / 32
        self.Nr = max(self.Nb, self.Nk) + 6  # Number of rounds
        self.round_keys = self._key_expansion(key)
    
    def _xtime(self, a):
        return ((a << 1) ^ 0x11b) & 0xff if a & 0x80 else a << 1
    
    def _multiply(self, a, b):
        result = 0
        for i in range(8):
            if b & 1:
                result ^= a
            a = self._xtime(a)
            b >>= 1
        return result
    
    def _key_expansion(self, key: bytes) -> list:
        """Расширение ключа для Rijndael-256."""
        w = []
        
        # Копируем начальный ключ
        for i in range(self.Nk):
            w.append(list(key[4*i:4*i+4]))
        
        # Расширяем ключ
        for i in range(self.Nk, self.Nb * (self.Nr + 1)):
            temp = w[i - 1][:]
            
            if i % self.Nk == 0:
                # RotWord + SubWord + Rcon
                temp = temp[1:] + temp[:1]
                temp = [self.SBOX[b] for b in temp]
                temp[0] ^= self.RCON[i // self.Nk - 1]
            elif self.Nk > 6 and i % self.Nk == 4:
                temp = [self.SBOX[b] for b in temp]
            
            w.append([w[i - self.Nk][j] ^ temp[j] for j in range(4)])
        
        return w
    
    def _add_round_key(self, state: list, round_num: int):
        for c in range(self.Nb):
            for r in range(4):
                state[r][c] ^= self.round_keys[round_num * self.Nb + c][r]
    
    def _inv_sub_bytes(self, state: list):
        for r in range(4):
            for c in range(self.Nb):
                state[r][c] = self.SBOX_INV[state[r][c]]
    
    def _inv_shift_rows(self, state: list):
        # Для Nb=8, сдвиги: [0, 1, 3, 4]
        shifts = [0, 1, 3, 4]
        for r in range(1, 4):
            state[r] = state[r][-shifts[r]:] + state[r][:-shifts[r]]
    
    def _inv_mix_columns(self, state: list):
        for c in range(self.Nb):
            s0 = state[0][c]
            s1 = state[1][c]
            s2 = state[2][c]
            s3 = state[3][c]
            
            state[0][c] = self._multiply(0x0e, s0) ^ self._multiply(0x0b, s1) ^ self._multiply(0x0d, s2) ^ self._multiply(0x09, s3)
            state[1][c] = self._multiply(0x09, s0) ^ self._multiply(0x0e, s1) ^ self._multiply(0x0b, s2) ^ self._multiply(0x0d, s3)
            state[2][c] = self._multiply(0x0d, s0) ^ self._multiply(0x09, s1) ^ self._multiply(0x0e, s2) ^ self._multiply(0x0b, s3)
            state[3][c] = self._multiply(0x0b, s0) ^ self._multiply(0x0d, s1) ^ self._multiply(0x09, s2) ^ self._multiply(0x0e, s3)
    
    def decrypt_block(self, block: bytes) -> bytes:
        """Расшифровывает один блок (32 байта)."""
        # Создаём state matrix (4 rows x Nb columns)
        state = [[0] * self.Nb for _ in range(4)]
        for c in range(self.Nb):
            for r in range(4):
                state[r][c] = block[c * 4 + r]
        
        # Initial round
        self._add_round_key(state, self.Nr)
        
        # Main rounds
        for round_num in range(self.Nr - 1, 0, -1):
            self._inv_shift_rows(state)
            self._inv_sub_bytes(state)
            self._add_round_key(state, round_num)
            self._inv_mix_columns(state)
        
        # Final round
        self._inv_shift_rows(state)
        self._inv_sub_bytes(state)
        self._add_round_key(state, 0)
        
        # Convert state to bytes
        result = bytearray(self.Nb * 4)
        for c in range(self.Nb):
            for r in range(4):
                result[c * 4 + r] = state[r][c]
        
        return bytes(result)


def decrypt_project_data(encrypted_base64: str) -> str:
    """Расшифровывает xmlData проекта."""
    return decrypt_rijndael_256(encrypted_base64, PROJECT_KEY, PROJECT_IV)


def decrypt_save_data(encrypted_base64: str) -> str:
    """Расшифровывает данные сохранения."""
    # Проверяем, не является ли это незашифрованным сохранением
    if encrypted_base64.startswith('<savegame'):
        return encrypted_base64
    return decrypt_rijndael_256(encrypted_base64, SAVE_KEY, SAVE_IV)


def encrypt_rijndael_256(plaintext: str, key: bytes, iv: bytes) -> str:
    """Зашифровывает данные с использованием Rijndael с BlockSize=256."""
    cipher = Rijndael256(key)
    
    # Оборачиваем текст в { }
    text = '{' + plaintext + '}'
    data = text.encode('utf-8')
    
    # Добавляем padding до кратности 32
    block_size = 32
    padding_len = block_size - (len(data) % block_size)
    if padding_len != block_size:
        data += b'\x00' * padding_len
    
    # CBC encryption
    result = bytearray()
    prev_block = iv
    
    for i in range(0, len(data), block_size):
        block = data[i:i + block_size]
        # XOR с предыдущим блоком
        xored = bytes(a ^ b for a, b in zip(block, prev_block))
        encrypted_block = cipher.encrypt_block(xored)
        result.extend(encrypted_block)
        prev_block = encrypted_block
    
    return base64.b64encode(bytes(result)).decode('ascii')


# Добавляем метод шифрования в класс Rijndael256
def _encrypt_block(self, block: bytes) -> bytes:
    """Шифрует один блок (32 байта)."""
    state = [[0] * self.Nb for _ in range(4)]
    for c in range(self.Nb):
        for r in range(4):
            state[r][c] = block[c * 4 + r]
    
    self._add_round_key(state, 0)
    
    for round_num in range(1, self.Nr):
        self._sub_bytes(state)
        self._shift_rows(state)
        self._mix_columns(state)
        self._add_round_key(state, round_num)
    
    self._sub_bytes(state)
    self._shift_rows(state)
    self._add_round_key(state, self.Nr)
    
    result = bytearray(self.Nb * 4)
    for c in range(self.Nb):
        for r in range(4):
            result[c * 4 + r] = state[r][c]
    
    return bytes(result)

def _sub_bytes(self, state: list):
    for r in range(4):
        for c in range(self.Nb):
            state[r][c] = self.SBOX[state[r][c]]

def _shift_rows(self, state: list):
    shifts = [0, 1, 3, 4]
    for r in range(1, 4):
        state[r] = state[r][shifts[r]:] + state[r][:shifts[r]]

def _mix_columns(self, state: list):
    for c in range(self.Nb):
        s0 = state[0][c]
        s1 = state[1][c]
        s2 = state[2][c]
        s3 = state[3][c]
        
        state[0][c] = self._multiply(0x02, s0) ^ self._multiply(0x03, s1) ^ s2 ^ s3
        state[1][c] = s0 ^ self._multiply(0x02, s1) ^ self._multiply(0x03, s2) ^ s3
        state[2][c] = s0 ^ s1 ^ self._multiply(0x02, s2) ^ self._multiply(0x03, s3)
        state[3][c] = self._multiply(0x03, s0) ^ s1 ^ s2 ^ self._multiply(0x02, s3)

# Добавляем методы в класс
Rijndael256.encrypt_block = _encrypt_block
Rijndael256._sub_bytes = _sub_bytes
Rijndael256._shift_rows = _shift_rows
Rijndael256._mix_columns = _mix_columns


def encrypt_project_data(plaintext: str) -> str:
    """Зашифровывает xmlData проекта."""
    return encrypt_rijndael_256(plaintext, PROJECT_KEY, PROJECT_IV)


def encrypt_save_data(plaintext: str) -> str:
    """Зашифровывает данные сохранения."""
    return encrypt_rijndael_256(plaintext, SAVE_KEY, SAVE_IV)


def main():
    parser = argparse.ArgumentParser(
        description='ORK Framework XML Data Decryptor/Encryptor',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog='''
Examples:
  Decrypt project xmlData from file:
    python ork_decrypt.py -d input.txt -o output.xml
    
  Decrypt from stdin:
    echo "BASE64_DATA" | python ork_decrypt.py -d -
    
  Decrypt savegame:
    python ork_decrypt.py -d save.txt -o save.xml —save
    
  Encrypt XML back:
    python ork_decrypt.py -e input.xml -o output.txt
        '''
    )
    
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-d', '--decrypt', metavar='FILE', 
                       help='Decrypt file (use - for stdin)')
    group.add_argument('-e', '--encrypt', metavar='FILE',
                       help='Encrypt file (use - for stdin)')
    
    parser.add_argument('-o', '--output', metavar='FILE',
                        help='Output file (default: stdout)')
    parser.add_argument('--save', action='store_true',
                        help='Use savegame keys instead of project keys')
    
    args = parser.parse_args()
    
    # Read input
    if args.decrypt:
        if args.decrypt == '-':
            data = sys.stdin.read().strip()
        else:
            data = Path(args.decrypt).read_text(encoding='utf-8').strip()
        
        # Decrypt
        if args.save:
            result = decrypt_save_data(data)
        else:
            result = decrypt_project_data(data)
            
    elif args.encrypt:
        if args.encrypt == '-':
            data = sys.stdin.read()
        else:
            data = Path(args.encrypt).read_text(encoding='utf-8')
        
        # Encrypt
        if args.save:
            result = encrypt_save_data(data)
        else:
            result = encrypt_project_data(data)
    
    # Write output
    if args.output:
        Path(args.output).write_text(result, encoding='utf-8')
        print(f"Output written to: {args.output}")
    else:
        print(result)


if __name__ == '__main__':
    main()

 

 

  • Лайк (+1) 1

Поделиться сообщением


Ссылка на сообщение

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

  • Похожие публикации

    • Автор: SamhainGhost

      Steam
      DunHero - это фэнтезийный рогалик в жанре экшн. Выберите героя, чтобы начать свое путешествие по разным мирам. У каждого героя разные стартовые предметы и сильные стороны. Чем глубже вы будете продвигаться, тем больше предметов вы найдете, которые помогут вам, и тем сильнее вы станете. В Dunhero вас всегда ждет что-то новое - например, торговец, мощный предмет или могущественный враг.
      Русификатор от SamhainGhost (от 26.01.2026) — гугл диск / boosty
      По ссылке 2 русификатора:
      v1a (Универсальный, но хуже по качеству) — Поддерживаемые версии игры - 1.0 и выше
      v2d — (для конкретной версии, но значительно лучше по качеству) — только для версии 1.0.1 от 25 января 2026 (билд 21637357 по steamdb):

      Переведено через Deepseek, доработано и проверено человеком. Архивные версии на гугл-диске.


Zone of Games © 2003–2026 | Реклама на сайте.

×