IJCTF | LSB

#!/usr/bin/env python3
import socketserver, sys
from Crypto.Util.number import getPrime
import gmpy2
import random, math
from secret import flag

def recvline(req):
    buf = b""
    while not buf.endswith(b"\n"):
        buf += req.recv(1)
    return buf

class RequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        rounds = 1 + int(2048 // math.log2(2020))
        p = getPrime(1024)
        q = getPrime(1024)
        e = 65537
        n = p * q
        phin = (p - 1) * (q - 1)
        d = int(gmpy2.invert(e, phin))
        self.request.sendall(str(n).encode() + b"\n")
        secret_number = random.randint(0, n)
        c = pow(secret_number, e, n)
        self.request.sendall(str(c).encode() + b"\n")
        for _ in range(rounds):
            data = recvline(self.request).strip()
            c = int(data)
            resp = pow(c, d, n) % 2020
            self.request.sendall(str(resp).encode() + b"\n")
        data = recvline(self.request).strip()
        m = int(data)
        if m == secret_number:
            self.request.sendall(flag)
        else:
            self.request.sendall(b"Oops...")

class TCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

if __name__ == '__main__':
    HOST, PORT = "0.0.0.0", 9999
    socketserver.TCPServer.allow_reuse_address = True
    server = TCPServer((HOST, PORT), RequestHandler)
    print("Server listening on port %d" % PORT)
    server.serve_forever()

mod2020のLSBLeakAttackだということを(ソースコードは与えられていなかったので)guessingする。あとは InCTF | waRSAwと同じなのでやるだけ

from Crypto.Util.number import *
from socket import socket, AF_INET, SOCK_STREAM

def read_data():
    return int(file.readline().decode().strip())

def send_data(x):
    file.write(str(x).encode() + b'\n')
    file.flush()

sock = socket(AF_INET, SOCK_STREAM)
sock.connect(('34.87.174.144', 9999))
file = sock.makefile('rwb')
n = read_data()
e = 65537
c = read_data()
M = 2020

def oracle(x):
    send_data(x)
    return read_data()

i = 1
z = oracle(c)
while True:
    inv = inverse(pow(M, i, n), n)
    c2 = (c * pow(inv, e, n)) % n

    ith_z = (oracle(c2) - (z * inv) % n) % M
    z = ith_z * (M ** i) + z
    i += 1
    print(f"[+] {i}")

    if pow(z, e, n) == c:
        break

while True:
    send_data(z)
    line = file.readline()
    print(line)
    if len(line) == 0:
        break