Post

CTF2021 - GuessKey2

Crypto

No hay descripcion del desafio, solamente nos adjuntan un zip.


Analizar el codigo

El primer paso es analizar el codigo 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

El codigo es igual que el del desafio GuessKey, la unica diferencia es que esta vez no se imprime el valor de la variable key.

Elaborar el exploit

Esta vez no vale con elegir 0 de mascara e introducir la clave 3 veces seguidas porque no conocemos la clave.

El truco esta en dos puntos: la clave key no se reestablece tras cada modificacion y la variable “q” en algun momento tomare el valor de la posicion del 0 menos significativo en la clave “key” en binario.

Sabiendo esto, podemos hacer un xor con 1 continuamente, dejando a 1 todos los 0 de la clave, desde el menos significativo hasta el mas significativo (de derecha a izquierda). Sabremos que ya hemos dejado toda la clave a 1 cuando al establecer el valor de “guess” a “2^64 - 1” el servidor nos responda con “Nice.” en vez de “Oops.”, en este punto solo tendremos que enviar 0 como mascara y el valor anterior como “guess” y ya obtendremos la flag:

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
26
#!/usr/bin/python3
from pwn import *
#p = process("./GuessKey_Fix.py")
p = remote("52.163.228.53", 8082)
while True:
    p.recvuntil("mask:")
    p.send("1\n")
    p.recvuntil("guess:")
    p.send("18446744073709551615\n")

    check=p.recvuntil(".")
    print(check)
    if(check==b'Nice.'):
        p.recvuntil("mask:")
        p.send("0\n")
        p.recvuntil("guess:")
        p.send("18446744073709551615\n")
        p.recvuntil("mask:")
        p.send("0\n")
        p.recvuntil("guess:")
        p.send("18446744073709551615\n")
        p.recvuntil("Nice.\n")
        print(p.recvuntil("}"))
        p.close()
        exit(0)

This post is licensed under CC BY 4.0 by the author.