0xGame 2023【WEEK2】Crypto全解

发布时间 2023-10-21 06:43:59作者: Kicky_Mu

中间的那个人

题目信息

from secret import flag
from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
from random import *

p = getPrime(128)
g = 2
A = getrandbits(32)
B = getrandbits(32)

Alice = pow(g,A,p)
Bob = pow(g,B,p)
key = pow(Alice,B,p)
key = sha256(long_to_bytes(key)).digest()

iv = b"0xGame0xGameGAME"
aes = AES.new(key, AES.MODE_CBC, iv)
enc = aes.encrypt(flag)
print(f'g={g}\np={p}')  #we tell
print(f'Bob={Bob}')     #Bob tell
print(f'Alice={Alice}') #Alice tell

print(f'enc={enc}')#Here is they secret

'''
g=2
p=250858685680234165065801734515633434653
Bob=33067794433420687511728239091450927373
Alice=235866450680721760403251513646370485539
enc=b's\x04\xbc\x8bT6\x846\xd9\xd6\x83 y\xaah\xde@\xc9\x17\xdc\x04v\x18\xef\xcf\xef\xc5\xfd|\x0e\xca\n\xbd#\x94{\x8e[.\xe8\xe1GU\xfa?\xda\x11w'
'''

题目分析:
离散对数求解B后再求flag
exp:

g=2
p=250858685680234165065801734515633434653
Bob=33067794433420687511728239091450927373
Alice=235866450680721760403251513646370485539
enc=b's\x04\xbc\x8bT6\x846\xd9\xd6\x83 y\xaah\xde@\xc9\x17\xdc\x04v\x18\xef\xcf\xef\xc5\xfd|\x0e\xca\n\xbd#\x94{\x8e[.\xe8\xe1GU\xfa?\xda\x11w'
Z = Zmod(p)
B = ZZ(discrete_log(Z(Bob),Z(2)))
print(B)
#1620639479
from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
from sympy import discrete_log
g=2
p=250858685680234165065801734515633434653
Bob=33067794433420687511728239091450927373
Alice=235866450680721760403251513646370485539
enc=b's\x04\xbc\x8bT6\x846\xd9\xd6\x83 y\xaah\xde@\xc9\x17\xdc\x04v\x18\xef\xcf\xef\xc5\xfd|\x0e\xca\n\xbd#\x94{\x8e[.\xe8\xe1GU\xfa?\xda\x11w'

B = 1620639479
key = pow(Alice,B,p)
key = sha256(long_to_bytes(int(key))).digest()
iv = b"0xGame0xGameGAME"
aes = AES.new(key, AES.MODE_CBC, iv)
flag = aes.decrypt(enc)
print(flag)
# 0xGame{51393fe1fd5fc2df1bf018d06f0fa11d}

What’s CRT?

题目信息

from Crypto.Util.number import *
from secert import flag

m = bytes_to_long(flag)
e = 260792700
q,p,q_,p_ = [getPrime(512) for _ in range(4)]
gift = [q+p,q_+p_]
n,n_ = q*p,q_*p_
mq_ = pow(m,4,q_)
mp_ = pow(m,4,p_)
c = pow(m,e,n)

print(f'mygift={gift}\nmq_={mq_}\nmp_={mp_}\nn={n}\nn_={n_}\nc={c}')
'''
mygift=[15925416640901708561793293991573474917595642805739825596593339102414328214313430010166125066639132916608736569443045051644173933089503934675628814467277922, 18342424676996843423829480445042578097182127446865571536445030052846412665700132683433441858073625594933132038175200824257774638419166516796318527302903098]
mq_=6229615098788722664392369146712291169948485951371133086154028832805750551655072946170332335458186479565263371985534601035559229403357396564568667218817197
mp_=7514598449361191486799480225087938913945061715845128006069296876457814528347371315493644046029376830166983645570092100320566196227210502897068206073043718
n=63329068473206068067147844002844348796575899624395867391964805451897110448983910133293450006821779608031734813916287079551030950968978400757306879502402868643716591624454744334316879241573399993026873598478532467624301968439714860262264449471888606538913071413634346381428901358109273203087030763779091664797
n_=84078907800136966150486965612788894868587998005459927216462899940718213455112139441858657865215211843183780436155474431592540465189966648565764225210091190218976417210291521208716206733270743675534820816685370480170120230334766919110311980614082807421812749491464201740954627794429460268010183163151688591417
c=12623780002384219022772693100787925315981488689172490837413686188416255911213044332780064192900824150269364486747430892667624289724721692959334462348218416297309304391635919115701692314532111050955120844126517392040880404049818026059951326039894605004852370344012563287210613795011783419126458214779488303552
'''

题目分析:

exp:

from gmpy2 import *
from Crypto.Util.number import *
from libnum import *
mq_=6229615098788722664392369146712291169948485951371133086154028832805750551655072946170332335458186479565263371985534601035559229403357396564568667218817197
mp_=7514598449361191486799480225087938913945061715845128006069296876457814528347371315493644046029376830166983645570092100320566196227210502897068206073043718
n=63329068473206068067147844002844348796575899624395867391964805451897110448983910133293450006821779608031734813916287079551030950968978400757306879502402868643716591624454744334316879241573399993026873598478532467624301968439714860262264449471888606538913071413634346381428901358109273203087030763779091664797
n_ =84078907800136966150486965612788894868587998005459927216462899940718213455112139441858657865215211843183780436155474431592540465189966648565764225210091190218976417210291521208716206733270743675534820816685370480170120230334766919110311980614082807421812749491464201740954627794429460268010183163151688591417
c=12623780002384219022772693100787925315981488689172490837413686188416255911213044332780064192900824150269364486747430892667624289724721692959334462348218416297309304391635919115701692314532111050955120844126517392040880404049818026059951326039894605004852370344012563287210613795011783419126458214779488303552
paddq = 15925416640901708561793293991573474917595642805739825596593339102414328214313430010166125066639132916608736569443045051644173933089503934675628814467277922
p_addq_ = 18342424676996843423829480445042578097182127446865571536445030052846412665700132683433441858073625594933132038175200824257774638419166516796318527302903098

p_q_ = iroot((paddq) ** 2 - 4 * n,2)[0]
p = (paddq + p_q_) // 2
q = n // p
phi = (p - 1) * (q - 1)
d4 = invert(260792700 // 4,phi)
m4 = pow(c,d4,n)

p_q_1 = iroot((p_addq_) ** 2 - 4 * n_,2)[0]
p_ = (p_addq_ + p_q_1) // 2
q_ = n_ // p_
m = iroot(solve_crt([mp_,mq_,m4],[q_,p_,n]),4)[0]
print(long_to_bytes(m))
# 0xGame{7881ed67088e9f72b860f8c376599785}

EzLFSR

题目信息

from Crypto.Util.number import *
from secret import flag,secret

assert flag == b'0xGame{'+secret+b'}'

def make_mask(m):
    tmp = str(bin(bytes_to_long(m)))[2:].zfill(128)
    return tmp

def string2bits(s):
    return [int(b) for b in s]

def bits2string(bs):
    s = [str(b) for b in bs]
    return ''.join(s)

def lfsr(state, mask):
    assert(len(state) == 128)
    assert(len(mask)  == 128)

    output = 0
    for i in range(128):
        output = output ^ (state[i] & mask[i])

    return output

if __name__ == '__main__':
    initState = [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
    secret = make_mask(secret)
    mask = string2bits(secret)

    for b in secret: assert(b == '0' or b == '1')
    assert(len(secret) == 128)

    for i in range(256):
        state = initState[i:]
        output = lfsr(state, mask)
        initState += [output]

    outputState = bits2string(initState[128:])
    print('outputState =', outputState)

'''
outputState = 1101111111011101100001000011111101001000111000110100010011110111010011100110100100111001101010110110101110000011110101000110010010000011111111001111000110111001100111101110010100100001101001111110001010000100111101011011100010000000100000100000100111010110
'''

题目分析:

exp:

init = [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
R = 0b01011001100001001000111001101101001010100101101011111111011010011010100000110101000111111101101010011110011110101101000000110100
output = 0b1101111111011101100001000011111101001000111000110100010011110111010011100110100100111001101010110110101110000011110101000110010010000011111111001111000110111001100111101110010100100001101001111110001010000100111101011011100010000000100000100000100111010110
c = '1101111111011101100001000011111101001000111000110100010011110111010011100110100100111001101010110110101110000011110101000110010010000011111111001111000110111001100111101110010100100001101001111110001010000100111101011011100010000000100000100000100111010110'
c  = [int(i) for i in c]

from Crypto.Util.number import *
from gmpy2 import *
R = 0b01011001100001001000111001101101001010100101101011111111011010011010100000110101000111111101101010011110011110101101000000110100
output = 0b1101111111011101100001000011111101001000111000110100010011110111010011100110100100111001101010110110101110000011110101000110010010000011111111001111000110111001100111101110010100100001101001111110001010000100111101011011100010000000100000100000100111010110

R_list = [R]
for i in range(1, 256):
    R = ((R << 1) ^^ (output >> 255)) & 0xffffffffffffffffffffffffffffffff
    output = (output << 1) & (2 ** 256 - 1)
    R_list.append(R)

R_binary_list = [list(format(R, '0>128b')) for R in R_list]
R_int_list = [[int(bit) for bit in binary] for binary in R_binary_list]
Rt = matrix(Zmod(2),R_int_list).transpose()

c = matrix(Zmod(2),c)
m = Rt.solve_left(c).list()
m = int(''.join(str(i) for i in m),2)
print(long_to_bytes(m))
# Rec0ver_the_M@sk

Fault!Fault!

题目信息

from Crypto.Util.number import *
import socketserver
import signal
from secret import flag
import random
import os
import string
from hashlib import sha256
from string import ascii_uppercase
from random import shuffle,choice,randint
import os

q = getPrime(512)
p = getPrime(512)
e = 65537
n = q*p
phi = (q-1)*(p-1)
d = inverse(e,phi)

def decrypt(c,d,n,index):
    """something go wrong"""
    d_ = d^(1<<(index))
    m_ = pow(c,d_,n)
    return str(m_)

MEMU = """
    Welc0me_2_0xGame2023!
/----------------------------\\
|          options           |
| [S]ign                     |
| [F]ault injection          |
| [C]heck answer             |
\\---------------------------/
"""

class Task(socketserver.BaseRequestHandler):
    def proof_of_work(self):
        '''验证函数'''
        random.seed(os.urandom(8))
        proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
        _hexdigest = sha256(proof.encode()).hexdigest()
        self.send(f"[+] sha256(XXXX+{proof[4:]}) == {_hexdigest}".encode())
        x = self.recv(prompt=b'[+] Plz tell me XXXX: ')
        if len(x) != 4 or sha256(x+proof[4:].encode()).hexdigest() != _hexdigest:
            return False
        return True

    def _recvall(self):
        BUFF_SIZE = 2048
        data = b''
        while True:
            part = self.request.recv(BUFF_SIZE)
            data += part
            if len(part) < BUFF_SIZE:
                break
        return data.strip()

    def send(self, msg, newline=True):
        try:
            if newline:
                msg += b'\n'
            self.request.sendall(msg)
        except:
            pass

    def recv(self, prompt=b'> '):
        self.send(prompt, newline=False)
        return self._recvall()

    def timeout_handler(self, signum, frame):
        raise TimeoutError

        '''以上是交互部分'''
    def handle(self):
        '''题干'''
        signal.signal(signal.SIGALRM, self.timeout_handler)
        signal.alarm(300)
        self.send(MEMU)
        if not self.proof_of_work():
            self.send(b'[!] Wrong!')
            return

        self.send(MEMU.encode())
        while True:
            code = self.recv()
            if code == b'S':
                self.send(b'What you want to sign?:')
                m = bytes_to_long(self.recv())
                c = pow(m,e,n)
                self.send(f'{n}\n{e}\n{c}'.encode())
                
            elif code == b'F':
                self.send(b'Give me the Signatrue:')
                Signatrue = int(self.recv())
                self.send(b'Where you want to interfere?')
                index = int(self.recv())
                self.send(b'The decrypt text:')
                self.send(decrypt(Signatrue,d,n,index).encode())

            elif code == b'C':
                self.send(b'Give me the private key:')
                ans = int(self.recv())
                if ans == d:
                    self.send(b'Here is your flag:')
                    self.send(flag)
                    
            else:
                self.send(b'invaild input')

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

class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
    pass

if __name__ == "__main__":
    HOST, PORT = '0.0.0.0', 10005
    server = ForkedServer((HOST, PORT), Task)
    server.allow_reuse_address = True
    print(HOST, PORT)
    server.serve_forever()

题目分析:

m,n,e,c已知,求d

关键在这串:

def decrypt(c,d,n,index):
    """something go wrong"""
    d_ = d^(1<<(index))
    m_ = pow(c,d_,n)
    return str(m_)

 

exp:

import hashlib
import string
from pwn import *
ip = 'IP'
port = 端口号
r = remote(ip,port)

def proof_of_work():
    r.recvuntil(b'XXXX+')
    suffix = r.recv(16).decode()
    r.recvuntil(b'== ')
    shaa = r.recv(64).decode()

    def f(x):
        hashresult = hashlib.sha256(x.encode() + suffix.encode()).hexdigest()
        return hashresult == shaa

    prefix = util.iters.mbruteforce(f,string.ascii_letters + string.digits,4)
    r.sendline(prefix.encode())

    r.sendlineafter(b'> ',b'S')
    r.sendlineafter(b'> ',b'1')
    n = int(r.recvline().decode().strip())
    e = int(r.recvline().decode().strip())
    c = int(r.recvline().decode().strip())
    d = ''
    for i in range(0,1025):
        r.sendlineafter(b'> ',b'F')
        r.sendlineafter(b'> ',str(c).encode())
        r.sendlineafter(b'>',str(i).encode())
        r.recvline()
        c_ = int(r.recvline().decode().strip())
        t = c_ * pow(c,-2 ** i,n) % n

        if t == 49:
            d = '0' + d
        else:
            d = '1' + d
        print(i)
    print(d)
    d = int(d,2)
    r.sendlineafter(b'> ',b'C')
    r.sendlineafter(b'> ',str(d).encode())
    r.recvline()
    print(r.recvline().decode().strip())
    return
    
proof_of_work()
r.interactive
# 0xGame{F@ult_Milest0ne!!}

EzRSA

题目信息

challenge1.py:

from Crypto.Util.number import *
from secret import flag1
import random

class RSAServe:
    def __init__(self) -> None:
        self.e = 65537
        self.p = getPrime(1024)
        self.q = getPrime(1024)
        self.n = self.q*self.p
        self.g, self.r1 = [random.randint(1, self.q*self.p) for _ in range(2)]
        self.gift = pow(self.g, self.r1 * (self.p - 1), self.n)
        self.m = flag1

    def encrypt(self):
        m_ = bytes_to_long(self.m)
        c = pow(m_, self.e, self.p*self.q)
        return hex(c)

    def check(self, msg):
        return msg == self.m

    def pubkey(self):
        return self.p*self.q, self.e,self.gift

challenge2.py:

from Crypto.Util.number import *
from secret import flag2
from random import choice

class RSAServe:
    def __init__(self) -> None:
        self.e = 65537
        self.m = flag2
        self.p = self.GetMyPrime(1024)
        self.q = self.GetMyPrime(1024)

    def GetMyPrime(self,bits):
        while True:
            n = 2
            while n.bit_length() < bits:
                a = choice(sieve_base)
                n *= a
            if isPrime(n + 1):
                return n + 1

    def encrypt(self):
        m_ = bytes_to_long(self.m)
        c = pow(m_, self.e, self.p*self.q)
        return hex(c)

    def check(self, msg):
        return msg == self.m

    def pubkey(self):
        return self.p*self.q, self.e

challenge3.py:

from Crypto.Util.number import *
from secret import flag3
from random import choice
from sympy import *
class RSAServe:
    def __init__(self) -> None:
        self.e = 65537
        self.m = flag3
        self.p = getPrime(896)
        self.n1 = self.getN()
        self.n2 = self.getN()

    def getN(self):
        q = getPrime(128)
        self.p = nextprime(self.p)
        return q*self.p

    def encrypt(self):
        m_ = bytes_to_long(self.m)
        c = pow(m_, self.e, self.n2)
        return hex(c)

    def check(self, msg):
        return msg == self.m

    def pubkey(self):
        return self.n1, self.n2 , self.e

题目分析:

part1:
费马小定理

 

exp1:

n = 
p = 
gift = 
e = 
c = 
p = gcd(gift - 1,n)
q = n // p
phi = (p - 1)*(q - 1)
d = invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m)) # b"Fermat's little theorem?"

part2:
Pollard’s p-1光滑
exp2:

n = 
e = 
c = 
def Pollards_p_1(N):
    n = 2
    a = 2
    while True:
        a = pow(a,n,N)
        res = gcd(a-1,N)
        print(n)
        if res != 1 and res != N:
            print('p = ',res)
            return res
        n += 1
p = Pollards_p_1(n)
q = n // p
phi = (p-1)*(q-1)
d = invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m)) # b'EzFactor!'

part3:

exp3:

n1 = 
n2 = 
e = 
c = 
def continuedFra(x, y):
    cf = []
    while y:
        cf.append(x // y)
        x, y = y, x % y
    return cf

def gradualFra(cf):
    numerator = 0 # 分子
    denominator = 1 # 分母
    for x in cf[::-1]:
        # 这里的渐进分数分子分母要分开
        numerator, denominator = denominator, x * denominator + numerator
    return numerator, denominator

def getGradualFra(cf):
    gf = []
    for i in range(1, len(cf) + 1):
        gf.append(gradualFra(cf[:i]))
    return gf

def wienerAttack(e, n):
    cf = continuedFra(e, n)
    gf = getGradualFra(cf)
    for q2, k in gf:
        if isPrime(q2) and q2.bit_length() == 128:
            print(q2,q2.bit_length())
            return q2

q2 = wienerAttack(n1, n2)
p2 = n2 // q2
phi = (p2 - 1) * (q2 - 1)
d = inverse(e,phi)
print(long_to_bytes(pow(c,d,n2))) # Continued fractionnnn

完整exp:

import hashlib
import string
from gmpy2 import *
from Crypto.Util.number import *
from pwn import *
ip = 'IP'
port = 端口号
r = remote(ip,port)
def proof_of_work():
    r.recvuntil(b'XXXX+')
    suffix = r.recv(16).decode()
    r.recvuntil(b'== ')
    shaa = r.recv(64).decode()

    def f(x):
        hashresult = hashlib.sha256(x.encode() + suffix.encode()).hexdigest()
        return hashresult == shaa

    prefix = util.iters.mbruteforce(f,string.ascii_letters + string.digits,4)
    r.sendline(prefix.encode())

    r.sendlineafter(b'> ',b'1')
    r.sendlineafter(b'> ',b'1')
    n = int(r.recvline().decode().strip())
    e = int(r.recvline().decode().strip())
    gift = int(r.recvline().decode().strip())
    r.sendlineafter(b'> ',b'2')
    c = int(r.recvline().decode().strip()[2:],16)
    def decrypt1(n,e,gift,c):
        p = gcd(gift - 1,n)
        q = n // p
        d = inverse(e,(p - 1) * (q - 1))
        m = long_to_bytes(pow(c,d,n))
        return m
    r.sendlineafter(b'> ',b'3')
    r.sendlineafter(b'answer: ',decrypt1(n,e,gift,c))

    r.sendlineafter(b'> ',b'2')
    r.sendlineafter(b'> ',b'1')
    n = int(r.recvline().decode().strip())
    e = int(r.recvline().decode().strip())
    r.sendlineafter(b'> ',b'2')
    c = int(r.recvline().decode().strip()[2:],16)
    def decrypt2(N,e,c):
        n = 2
        a = 2
        while True:
            a = pow(a,n,N)
            p = gcd(a-1,N)
            if p != 1 and p != N:
                q = N // p
                d = inverse(e, (p - 1) * (q - 1))
                m = long_to_bytes(pow(c, d, N))
                return m
            n += 1
    r.sendlineafter(b'> ',b'3')
    r.sendlineafter(b'answer: ', decrypt2(n, e, c))

    r.sendlineafter(b'> ', b'3')
    r.sendlineafter(b'> ', b'1')
    n1 = int(r.recvline().decode().strip())
    n2 = int(r.recvline().decode().strip())
    e = int(r.recvline().decode().strip())
    r.sendlineafter(b'> ', b'2')
    c = int(r.recvline().decode().strip()[2:],16)
    def decrypt3(n1,n2,e,c):
        def continuedFra(x, y):

            cf = []
            while y:
                cf.append(x // y)
                x, y = y, x % y
            return cf

        def gradualFra(cf):

            numerator = 0  # 分子
            denominator = 1  # 分母
            for x in cf[::-1]:
                # 这里的渐进分数分子分母要分开
                numerator, denominator = denominator, x * denominator + numerator
            return numerator, denominator

        def getGradualFra(cf):

            gf = []
            for i in range(1, len(cf) + 1):
                gf.append(gradualFra(cf[:i]))
            return gf

        def wienerAttack(e, n):

            cf = continuedFra(e, n)
            gf = getGradualFra(cf)
            for q2, k in gf:
                if isPrime(q2) and q2.bit_length() == 128:
                    print(q2, q2.bit_length())
                    return q2

        q2 = wienerAttack(n1, n2)
        p2 = n2 // q2
        phi = (p2 - 1) * (q2 - 1)
        d = inverse(e, phi)
        m = long_to_bytes(pow(c,d,n2))
        return m

    r.sendlineafter(b'> ', b'3')
    r.sendlineafter(b'answer: ', decrypt3(n1,n2, e, c))
    r.recvuntil(b'flag:')
    print(r.recvline().decode().strip())
    return 

proof_of_work()
r.interactive()
# 0xGame{a1425c9ce44989ffd64968130ee2f9fd}