typo

Autor: HenriUz

Analisando o desafio

Ao olhar para o desafio temos dois arquivos para serem baixados, o primeiro é um arquivo .py e o segundo um .txt.

mian.py:

import random as RrRrRrrrRrRRrrRRrRRrrRr
RrRrRrrrRrRRrrRRrRRrRrr = int('1665663c', 20)
RrRrRrrrRrRRrrRRrRRrrRr.seed(RrRrRrrrRrRRrrRRrRRrRrr)
arRRrrRRrRRrRRRrRrRRrRr = bytearray(open('flag.txt', 'rb').read())
arRRrrRrrRRrRRRrRrRRrRr = '\r'r'\r''r''\\r'r'\\r\r'r'r''r''\\r'r'r\r'r'r\\r''r'r'r''r''\\r'r'\\r\r'r'r''r''\\r'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
arRRrrRRrRRrRrRrRrRRrRr = [
    b'arRRrrRRrRRrRRrRr',
    b'aRrRrrRRrRr',
    b'arRRrrRRrRRrRr',
    b'arRRrRrRRrRr',
    b'arRRrRRrRrrRRrRR'
    b'arRRrrRRrRRRrRRrRr',
    b'arRRrrRRrRRRrRr',
    b'arRRrrRRrRRRrRr'
    b'arRrRrRrRRRrrRrrrR',
]
arRRRrRRrRRrRRRrRrRRrRr = lambda aRrRrRrrrRrRRrrRRrRrrRr: bytearray([arRrrrRRrRRrRRRrRrRrrRr + 1 for arRrrrRRrRRrRRRrRrRrrRr in aRrRrRrrrRrRRrrRRrRrrRr])
arRRrrRRrRRrRRRrRrRrrRr = lambda aRrRrRrrrRrRRrrRRrRrrRr: bytearray([arRrrrRRrRRrRRRrRrRrrRr - 1 for arRrrrRRrRRrRRRrRrRrrRr in aRrRrRrrrRrRRrrRRrRrrRr])
def arRRrrRRrRRrRrRRrRrrRrRr(hex):
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    return hex
arRRRRRRrRRrRRRrRrRrrRr = [arRRrrRRrRRrRrRRrRrrRrRr, arRRRrRRrRRrRRRrRrRRrRr, arRRrrRRrRRrRRRrRrRrrRr]
arRRRRRRrRRrRRRrRrRrrRr = [RrRrRrrrRrRRrrRRrRRrrRr.choice(arRRRRRRrRRrRRRrRrRrrRr) for arRrrrRRrRRrRRRrRrRrrRr in range(128)]
def RrRrRrrrRrRRrrRRrRRrrRr(arr, ar):
    for r in ar:
        arr = arRRRRRRrRRrRRRrRrRrrRr[r](arr)
    return arr
def arRRrrRRrRRrRrRRrRrrRrRr(arr, ar):
    ar = int(ar.hex(), 17)
    for r in arr:
        ar += int(r, 35)
    return bytes.fromhex(hex(ar)[2:])
arrRRrrrrRRrRRRrRrRRRRr = RrRrRrrrRrRRrrRRrRRrrRr(arRRrrRRrRRrRRRrRrRRrRr, arRRrrRrrRRrRRRrRrRRrRr.encode())
arrRRrrrrRRrRRRrRrRRRRr = arRRrrRRrRRrRrRRrRrrRrRr(arRRrrRRrRRrRrRrRrRRrRr, arrRRrrrrRRrRRRrRrRRRRr)
print(arrRRrrrrRRrRRRrRrRRRRr.hex())

output.txt:

Analisando o código

Para resolver esse desafio primeiro a gente deve dar um jeito de entender o código mian.py, ele obviamente é quem deixa a flag igual à saída do output.txt, e minha abordagem para entender esse código foi renomear todas as variáveis.

main.py:

Com as variáveis renomeadas fica bem mais fácil entender o que esse código faz, vale notar que o código reutiliza variáveis em certos momentos, mas isso não faz uma grande diferença para nós. Olhando o código podemos ver que o código pega a flag e faz uma série de operações em cima dela.

A função rand recebe como parâmetro a flag e uma string convertida pelo .encode(), essa função tem acesso à uma lista que contém 3 funções, em que 2 funções servem para aumentar ou diminuir 1 de cada valor da flag (func1L e func2L) e a outra troca as posições da flag. Note que quando eu me refiro à flag eu estou me referindo ao seu valor no bytearray gerado com a função open. Com acesso à essas 3 funções, a função rand usa um for para percorrer o segundo parâmetro, e com isso é usado a variável do for para escolher qual função da lista de função será usado na flag. Por fim é retornado a flag.

A função funcModificada recebe 2 parâmetros, o primeiro é uma lista com 9 strings de bytes, e o segundo é o bytearray da flag. A função começa convertendo o bytearray para um inteiro em base 17, e em seguida faz um for percorrendo o primeiro parâmetro e converte cada valor da lista para base 35 e soma com o inteiro gerado na base 17. Por fim retorna o resultado de todas as somas em bytes.

Resolução

Para resolver precisamos fazer todo o processo inverso. Primeiramente setamos a seed do random para ficar igual à seed no código main.py, porque com a mesma seed qualquer valor gerado aleatóriamente no nosso computador será igual aos valores gerados aleatorimente na geração do output.txt. Depois precisamos criar as variáveis que não são modificadas e que são usadas nas funções, elas são a string R (que é usada com o .encode()), a lista9 (que contém as strings de bytes) e abrimos a flag com a função open.

Após criarmos as variáveis, precisamos modificar as funções. A função func1L nós só preisamos modificar o + 1 para - 1, a função func2L segue a mesma lógica, só precisamos modificar o - 1 para + 1, e a função func só precisamos trocar a ordem dos for.

A função funModificada é a mais complicada, preisamos transformar nosso bytearray em inteiro (usando base 16 pelo output.txt estar em hexadecimal), após isso subtraímos o valor das strings de bytes convertidas em base 35 do nosso inteiro, e agora a função complica, precisamos fazer o processo inverso de converter para base 17 e para isso precisamos fazer diversas divisão por 17 e vamos salvando o resto até o valor ser menor do que 17, no fim verificamos se sobrou algum valor no inteiro e salvamos ele. O método escolhido para resolver isso foi usando uma string (por ser mais fácil de concatenar) e um while que ficará em loop até o inteiro ficar menor que 17. No while é verificado se o resto por 17 esta entre 10 e 16 para caso isso acontece nós colocamos o valor correspondente em hexadecimal e caso contrário é só colocar o resto, depois fazemos o inteiro ser ele mesmo dividido por 17. Após o while verificamos se sobrou algo no inteiro e no fim invertemos a string e retornamos ela convertida para bytes.

A função rand continua a mesma coisa, pois modificamos as funções que ela utiliza acima.

Resultado

amateursCTF{4t_l3ast_th15_fl4g_isn7_misspelll3d}

Atualizado