CRYPTO January 16, 2021

GuessKey2

Words count 3.7k Reading time 3 mins.

Autor: TonyTowers
*CTF2021

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

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 código es igual que el del desafío GuessKey, la única diferencia esque esta vez no se imprime el valor de la variable key.

Elaborar el exploit

Esta vez no vale con elegir 0 de máscara e introducir la clave 3 veces seguidas porque no conocemos la clave. El truco está en dos puntos: la clave key no se reestablece tras cada modificación y la variable “q” en algún momento tomará el valor de la posición del 0 menos significativo en la clave “key” en binario. Sabiendo esto, podemos hacer un xor con 1 contínuamente, dejando a 1 todos los 0 de la clave, desde el menos significativo hasta el más 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 máscara y el valor anterior como “guess” y ya obtendremos la flag:

exploit.py

#!/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)
0%