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:
5915f8ba06db0a50aa2f3eee4baef82e70be1a9ac80cb59e5b9cb15a15a7f7246604a5e456ad5324167411480f893f97e3
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:
import random as rand
#Setando a seed.
base20 = int('1665663c', 20)
rand.seed(base20)
#Abrindo o arquivo .txt
arquivoBin = bytearray(open('flag.txt', 'rb').read())
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'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
lista9 = [
b'arRRrrRRrRRrRRrRr',
b'aRrRrrRRrRr',
b'arRRrrRRrRRrRr',
b'arRRrRrRRrRr',
b'arRRrRRrRrrRRrRR'
b'arRRrrRRrRRRrRRrRr',
b'arRRrrRRrRRRrRr',
b'arRRrrRRrRRRrRr'
b'arRrRrRrRRRrrRrrrR',
]
func1L = lambda param: bytearray([pos + 1 for pos in param])
func2L = lambda param: bytearray([pos - 1 for pos in param])
def func(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
listaF = [func, func1L, func2L]
listaF = [rand.choice(listaF) for pos in range(128)]
def rand(arr, ar):
for r in ar:
arr = listaF[r](arr)
return arr
def funcModificada(arr, ar):
ar = int(ar.hex(),17)
for r in arr:
ar += int(r, 35)
return bytes.fromhex(hex(ar)[2:])
arrRRrrrrRRrRRRrRrRRRRr = rand(arquivoBin, R.encode())
arrRRrrrrRRrRRRrRrRRRRr = funcModificada(lista9, arrRRrrrrRRrRRRrRrRRRRr)
print(arrRRrrrrRRrRRRrRrRRRRr.hex())
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.
import random as r
#Converte o inteiro '1665663c' para um inteiro na base 20 (0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j)
base20 = int('1665663c', 20)
r.seed(base20)
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'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
lista9 = [
b'arRRrrRRrRRrRRrRr',
b'aRrRrrRRrRr',
b'arRRrrRRrRRrRr',
b'arRRrRrRRrRr',
b'arRRrRRrRrrRRrRR'
b'arRRrrRRrRRRrRRrRr',
b'arRRrrRRrRRRrRr',
b'arRRrrRRrRRRrRr'
b'arRrRrRrRRRrrRrrrR',
]
flag = bytearray(open('output.txt', 'rb').read())
def revFuncModificada(arr, ar):
ar = int(ar,16)
for r in arr:
ar -= int(r, 35)
valor3 = ''
while ar >= 17:
if str(ar%17) == '16':
valor3 += '1f'
elif str(ar%17) == '15':
valor3 += 'f'
elif str(ar%17) == '14':
valor3 += 'e'
elif str(ar%17) == '13':
valor3 += 'd'
elif str(ar%17) == '12':
valor3 += 'c'
elif str(ar%17) == '11':
valor3 += 'b'
elif str(ar%17) == '10':
valor3 += 'a'
else:
valor3 += str(ar%17)
ar = ar//17
if str(ar) == '16':
valor3 += '1f'
elif str(ar) == '15':
valor3 += 'f'
elif str(ar) == '14':
valor3 += 'e'
elif str(ar) == '13':
valor3 += 'd'
elif str(ar) == '12':
valor3 += 'c'
elif str(ar) == '11':
valor3 += 'b'
elif str(ar) == '10':
valor3 += 'a'
else:
valor3 += str(ar)
return bytes.fromhex(valor3[::-1])
func1L = lambda param: bytearray([pos - 1 for pos in param])
func2L = lambda param: bytearray([pos + 1 for pos in param])
def func(hex):
for list in range(1, len(hex) - 1, 2):
hex[list], hex[list + 1] = hex[list + 1], hex[list]
for id in range(0, len(hex) - 1, 2):
hex[id], hex[id + 1] = hex[id + 1], hex[id]
return hex
listaF = [func, func1L, func2L]
listaF = [r.choice(listaF) for pos in range(128)]
def rand(arr, ar):
for r in ar:
arr = listaF[r](arr)
return arr
fg = revFuncModificada(lista9, flag)
fg = rand(bytearray(fg), R.encode())
print(fg)
Resultado
amateursCTF{4t_l3ast_th15_fl4g_isn7_misspelll3d}
Atualizado