1 minute read

Overview

  • 134 solves/121 points
  • author: wwm

Description

lsb oracles are pretty overdone… anyway here’s fizzbuzz

nc be.ax 31100

Attached

#!/usr/local/bin/python
from Crypto.Util.number import *
from os import urandom

flag = open("flag.txt", "rb").read()
flag = bytes_to_long(urandom(16) + flag + urandom(16))

p = getPrime(512)
q = getPrime(512)
n = p * q
e = 0x10001
d = pow(e, -1, (p-1)*(q-1))
assert flag < n
ct = pow(flag, e, n)

print(f"{n = }")
print(f"{e = }")
print(f"{ct = }")

while True:
    ct = int(input("> "))
    pt = pow(ct, d, n)
    out = ""
    if pt == flag:
        exit(-1)
    if pt % 3 == 0:
        out += "Fizz"
    if pt % 5 == 0:
        out += "Buzz"
    if not out:
        out = pt
    print(out)

Analyzation

When receiving value x, the server returns x^d (mod n).

So if we send ct * r^e (mod n), the server will return (ct * r^e)^d (mod n), which equals to flag * r (mod n). Just multiply pow(r, -1, n) and the flag will be yours.

Remember that r must not be divisible by 3 and 5, and r is invertible in mod n.

Solution

from pwn import *

server = remote("be.ax", 31100)

server.recvuntil("n = ")
n = int(server.recvline())
server.recvuntil("e = ")
e = int(server.recvline())
server.recvuntil("ct = ")
ct = int(server.recvline())


r = 2 # make sure r is invertible
to_send = (pow(r, e, n) * (ct % n) ) % n

server.sendline(str(to_send))

server.recvuntil("> ")
flag_r = int(server.recvline())


from Crypto.Util.number import *

flag = flag_r * pow(r, -1, n) % n
print(long_to_bytes(flag)[16:-16])

The flag is

corctf{h4ng_0n_th15_1s_3v3n_34s13r_th4n_4n_LSB_0r4cl3...4nyw4y_1snt_f1zzbuzz_s0_fun}