Skip to content

Latest commit

 

History

History

nobus-101

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

nobus-101

After reverse-engineering the binary, we learned that it uses the Dual_EC_DRBG backdoored keys. The curve generatoin itself is deterministic, but we needed to reverse it. It looks like this:

MAGIC = 0x132867e88e82431dc40ba24e11bf3ec7ffb18764a3b4df1f5957fd5f37d8be40

def gen_backdoor():
    P = P256.G
    e = MAGIC
    d = mod_inv(e, P256.q)
    Q = e * P
    return P, Q, d

This makes it possible to recover the seed using only two random numbers, using the well-studied attack technique on Dual_EC_DRBG keys.

We modified the https://github.com/AntonKueltz/dual-ec-poc attack to get a deterministic seed recovery.

The interesting piece of our code is:

def recover_s(bits0, bits1, Q, d):
    for high_bits in range(2**16):
        guess = (high_bits << (8 * 30)) | bits0
        on_curve, y = find_point_on_p256(guess)

        if on_curve:
            # use the backdoor to guess the next 30 bytes
            point = Point(guess, y, curve=P256)
            s = (d * point).x
            r = (s * Q).x & (2**(8 * 30) - 1)

            if r == bits1:
                return s


def main():
    P, Q, d = gen_backdoor()
    data = requests.get("http://nobus101.insomnihack.ch:13337/prng").text
    bits0, bits1, *rest = data.split()
    bits0 = int(bits0, 16)
    bits1 = int(bits1, 16)

    s = recover_s(bits0, bits1, Q, d)
    curve = DualEC(s, P, Q)
    prediction = hex(curve.genbits())[2:].rjust(60, '0')
    text = requests.post("http://nobus101.insomnihack.ch:13337/flag", data=prediction.encode())

    print(text.text)

This allowed us to recover the flag.

INS{7ru57_7h3_5c13nc3}