Challenge: Prelim

Description: The challenge involves a Python script (source.py) that scrambles a message and encrypts a flag. Your task is to write a script (decoder.py) to reverse these operations and retrieve the original flag.

Brief Explanation of source.py:

The source.py script performs the following actions:

  1. Initializes n and e.
  2. Defines functions to scramble a list based on a permutation and super_scramble a permutation by applying it multiple times.
  3. Creates a shuffled list of numbers from 0 to n-1.
  4. Applies the super_scramble function to this shuffled list using the exponent e.
  5. Reads the flag from flag.txt, pads it, and encrypts it using AES in ECB mode with a key derived from the initial shuffled list.
  6. Writes the scrambled list and the encrypted flag (in hexadecimal format) to tales.txt.

decoder.py:

from hashlib import sha256
from Crypto.Cipher import AES
import ast

def main():
# Define RSA-like parameters
n = 0x1337  # 4919
e = 0x10001  # 65537

# Read scrambled_message and enc_flag from tales.txt
with open('tales.txt', 'r') as f:
lines = f.readlines()
scrambled_line = lines[0].strip()
enc_flag_line = lines[1].strip()

# Parse scrambled_message
scrambled_str = scrambled_line.split('=', 1)[1].strip()
scrambled_message = ast.literal_eval(scrambled_str)

# Parse enc_flag
enc_flag = enc_flag_line.split('=', 1)[1].strip().strip("'")

# Initialize the original message list
message = [0] * n
visited = [False] * n

# Process each element to find cycles
for i in range(n):
if not visited[i]:
cycle = []
j = i
while not visited[j]:
visited[j] = True
cycle.append(j)
j = scrambled_message[j]  # Follow the permutation

L = len(cycle)
if L == 0:
continue

# Compute inverse of e modulo L
d = pow(e, -1, L)

# Reorder the cycle
reordered_cycle = [cycle[(k * d) % L] for k in range(L)]

# Assign the values to message
for k in range(L):
current = reordered_cycle[k]
next_val = reordered_cycle[(k + 1) % L]
message[current] = next_val

# Generate the key from the original message
key = sha256(str(message).encode()).digest()

# Decrypt the flag
cipher = AES.new(key, AES.MODE_ECB)
encrypted_flag_bytes = bytes.fromhex(enc_flag)
flag = cipher.decrypt(encrypted_flag_bytes)

# The flag might have padding, which we can strip if necessary
print(flag.decode('utf-8').strip())

if __name__ == "__main__":
main()

Solution:

Flag: HTB{t4l3s_fr0m___RS4_1n_symm3tr1c_gr0ups!}