Post

CTF2021 - GuessKey

Crypto

No hay descripción del desafío, solamente nos adjuntan un zip.


Analizar el código

El primer paso es analizar el código del archivo que nos adjuntan en el zip:

GuessKey.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from random import randint
import os
from flag import flag
N=64
key=randint(0,2**N)
print key
key=bin(key)[2:].rjust(N,'0')
count=0
while True:
        p=0
        q=0
        new_key=''
        zeros=[0]
        for j in range(len(key)):
                if key[j]=='0':
                        zeros.append(j)
        p=zeros[randint(0,len(zeros))-1]
        q=zeros[randint(0,len(zeros))-1]
        try:
                mask=int(raw_input("mask:"))
        except:
                exit(0)
        mask=bin(mask)[2:]
        if p>q:
                tmp=q
                q=p
                p=tmp
        cnt=0
        for j in range(0,N):
        for j in range(0,N):
                if j in range(p,q+1):
                        new_key+=str(int(mask[cnt])^int(key[j]))
                else:
                        new_key+=key[j]
                cnt+=1
                cnt%=len(mask)
        key=new_key
        try:
                guess=int(raw_input("guess:"))
        except:
                exit(0)
        if guess==int(key,2):
                count+=1
                print 'Nice.'
        else:
                count=0
                print 'Oops.'
        if count>2:
		print flag

Primero se genera una cave aleatoria “key” de 64 bits y se imprime por pantalla.

Después se crea un array llamado “zeros” en el que se añaden las posiciones de los 0 en la clave “key” expresada en binario y se guardarán dos elementos aleatorios de “zeros” en las variables “p” y “q”. Se espera por STDIN un número que se guarda en la variable “mask”.

Lo siguiente es asegurarse de que “p” es menor que “q” para poder hacer un bucle desde “p” hasta “q” para variar los bits de la clave “key” dentro de este rango (p-q), la modificación consiste en hacer un XOR con la variable “mask”.

Por último se espera otro número por STDIN que se guardará en “guess”, para obtener la flag, “guess” ha de ser igual a “key” tres veces seguidas.

Escribir el exploit

El problema es que no conocemos el rango de la clave que será modificado, pero como podemos elegir la máscara con la que se hará el XOR, si hacemos que esa máscara sea 0, no habremos modificado ningún bit de la clave entonces “guess == key”. El exploit sería así:

exploit.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/python3
from pwn import *
#p = process("./GuessKey.py")
p = remote("52.163.228.53", 8080)

# Guardar el valor de "key"
key = p.recvuntil("\n")

# Repetir el procedimiento 3 veces
for i in range(3):

    # Enviar un 0 cuando se pida la variable "mask"
    p.recvuntil("mask:")
    p.send("0\n")

    # Enviar la clave "key" cuando se pida la variable "guess"
    p.recvuntil("guess:")
    p.send(key)

# Imprimir la flag
p.recvuntil("Nice.\n")
print(p.recvuntil("}"))

p.close()
exit(0)
This post is licensed under CC BY 4.0 by the author.