The challenge text reads:"I heard that add-rotate-xor are good operations for a cipher so I tried to make my own..."And we can download the following python script:```pythonclass baby_arx():    def __init__(self, key):        assert len(key) == 64        self.state = list(key)
    def b(self):        b1 = self.state[0]        b2 = self.state[1]        b1 = (b1 ^ ((b1 << 1) | (b1 & 1))) & 0xff        b2 = (b2 ^ ((b2 >> 5) | (b2 << 3))) & 0xff        b = (b1 + b2) % 256        self.state = self.state[1:] + [b]        return b
    def stream(self, n):        return bytes([self.b() for _ in range(n)])
FLAG = open('./flag.txt', 'rb').read().strip()cipher = baby_arx(FLAG)out = cipher.stream(64).hex()print(out)
# cb57ba706aae5f275d6d8941b7c7706fe261b7c74d3384390b691c3d982941ac4931c6a4394a1a7b7a336bc3662fd0edab3ff8b31b96d112a026f93fff07e61b```We assume that the hex dump in the last line comment is the 'encrypted' flag.We know that all flags usually start with 'DUCTF{'.Modifying the script to```pythonFLAG = 'DUCTF{}'```produces the output```cb57ba706a21```We clearly see that the first 5 hex tuples correspond to the hex dump in the comment. These first 5 tuples consist of the encrypted string 'DUCT'. We can assume that adding the correct suffix to 'DUCTF{' will provide the correct hex tuple for '{' at the end of our output.The idea is to add letters to the plaintext and encrypt it until we find the matching hex tuple (e.g. brute-forcing):```DUCTF{aDUCTF{bDUCTF{c...DUCTF{|DUCTF{}DUCTF{~```To compare the produced hex tuple to the known cipher text we first split up the cipher text into tuples```pythoncipher_flag = 'cb57ba706aae5f275d6d8941b7c7706fe261b7c74d3384390b691c3d982941ac4931c6a4394a1a7b7a336bc3662fd0edab3ff8b31b96d112a026f93fff07e61b'cipher_flag_byte_pairs = [''.join([cipher_flag[i], cipher_flag[i+1]]) for i in range(0, 128, 2)]```Since we know the prefix of our flag we can already provide a partial solution.```pythonflag_solution = 'DUCTF{'```Next we need a function to add letters to our partial solution:```pythonimport stringdef add_letters(flag):    return [flag+c for c in string.printable]```We also need a function to  encrypt the extended flag and return the last hex tuple we want to compare:```pythondef get_encrypted_tuple(flag_solution):    cipher = baby_arx(bytes(flag_solution, 'utf-8'))    out = cipher.stream(len(flag_solution)).hex()    return out[-4:-2]```Another function makes use of these two functions to extend the current flag, encrypt all extended flags and return the next correct char to append to our flag solution:```pythondef get_next_char(flag, cipher_flag_bytes):    cipher_prefix = cipher_flag_bytes[:len(flag)]    for extended_flag in add_letters(flag):        last_correct_tuple = get_encrypted_tuple(extended_flag)        if last_correct_tuple == cipher_prefix[-1]:            return extended_flag[-1]```The last function creates a partial solution until the length of the encrypted solution is equal to the length of the cipher text:```pythondef print_solution(partial_solution):    remaining_chars = len(cipher_flag_byte_pairs[len(partial_solution):])    while remaining_chars > 0:        partial_solution += get_next_char(partial_solution, cipher_flag_byte_pairs)        remaining_chars = len(cipher_flag_byte_pairs[len(partial_solution):])        print(partial_solution)```Finally we can call this function with our flag_solution as inital input.The whole script looks like this:```pythonclass baby_arx():    def __init__(self, key):        self.state = list(key)
    def b(self):        b1 = self.state[0]        b2 = self.state[1]        # b1 = (b1 XOR ((b1 LSHIFT 1) OR (b1 AND 1))) AND 0xff        b1 = (b1 ^ ((b1 << 1) | (b1 & 1))) & 0xff        # b2 = (b2 XOR ((b2 RSHIFT 5) | (b2 LSHIFT 3))) AND 0xff        b2 = (b2 ^ ((b2 >> 5) | (b2 << 3))) & 0xff        # b = (b1 ADD b2) MOD 256        b = (b1 + b2) % 256        self.state = self.state[1:] + [b]        return b
    def stream(self, n):        return bytes([self.b() for _ in range(n)])
# FLAG = open('./flag.txt', 'rb').read().strip()# cipher = baby_arx(bytes(FLAG, 'utf-8'))# out = cipher.stream(len(FLAG)).hex()# print(out)
import string
cipher_flag = 'cb57ba706aae5f275d6d8941b7c7706fe261b7c74d3384390b691c3d982941ac4931c6a4394a1a7b7a336bc3662fd0edab3ff8b31b96d112a026f93fff07e61b'cipher_flag_byte_pairs = [''.join([cipher_flag[i], cipher_flag[i+1]]) for i in range(0, 128, 2)]flag_solution = 'DUCTF{'
def add_letters(flag):    return [flag+c for c in string.printable]
def get_encrypted_tuple(flag_solution):    cipher = baby_arx(bytes(flag_solution, 'utf-8'))    out = cipher.stream(len(flag_solution)).hex()    return out[-4:-2]
def get_next_char(flag, cipher_flag_bytes):    cipher_prefix = cipher_flag_bytes[:len(flag)]    for extended_flag in add_letters(flag):        last_correct_tuple = get_encrypted_tuple(extended_flag)        if last_correct_tuple == cipher_prefix[-1]:            return extended_flag[-1]
def print_solution(partial_solution):    remaining_chars = len(cipher_flag_byte_pairs[len(partial_solution):])    while remaining_chars > 0:        partial_solution += get_next_char(partial_solution, cipher_flag_byte_pairs)        remaining_chars = len(cipher_flag_byte_pairs[len(partial_solution):])    print(partial_solution)
print_solution(flag_solution)```Executing this produces the output:```DUCTF{iDUCTF{i_DUCTF{i_dDUCTF{i_d0DUCTF{i_d0n...DUCTF{i_d0nt_th1nk_th4ts_h0w_1t_w0rks_actu4lly_92f45fb961ecf42DUCTF{i_d0nt_th1nk_th4ts_h0w_1t_w0rks_actu4lly_92f45fb961ecf420DUCTF{i_d0nt_th1nk_th4ts_h0w_1t_w0rks_actu4lly_92f45fb961ecf420}```