Midnight Flag CTF 2025

周末还是三个比赛,可惜不好弄。不是远端连不上就是远端打不开。再有就是太难了。

Crypto

A²+B²=C

这个题还是不算难的。给了两个30位数的平方和,并且p=u1*base+r0,q=u2*base+r1其中r 都很小,可以copper。

只是sage里的two_squres不管用,因为有4组(正数)解,需要全弄出来试试是哪个。

from sage.all import randint, next_prime
from Crypto.Util.number import bytes_to_long

class RSA:
    def __init__(self, hb, lb) -> None:
        self.hb = hb
        self.lb = lb
        self.u1 = randint(0, 2**30)
        self.u2 = randint(0, 2**30)
        self.keygen()
    
    def keygen(self) -> None:
        self.base = randint(2**self.hb-1, 2**self.hb)
        self.e = 0x10001
        self.p = next_prime(self.u1*self.base + randint(2, 2**self.lb))
        self.q = next_prime(self.u2*self.base + randint(2, 2**self.lb))
        self.n = self.p * self.q
    
    def sum(self):
        return self.u1**2 + self.u2**2
    
    def encrypt(self, m: bytes) -> int:
        m_ = bytes_to_long(m)
        c = pow(m_, self.e, self.n)
        return c
    

rsa = RSA(
    hb=2048,
    lb=256
)
print(f"c0 = {rsa.sum()}")
print(f"c1 = {rsa.encrypt(b'MCTF{ThisIsAFakeFlag}')}")
print(f"c2 = {rsa.encrypt(b'Lorem Ipsum is simply dummy text of')}")
print(f"c3 = {rsa.encrypt(b'the printing and typesetting industry')}")
c0 = 815188129004593690
c1 = 127925291615994657581931619146695269807090069321028068300026702785628490435087413298680092490257386473119689267569976305630148807575684825719646470673354518537583693756638610236703360575725390523075157347945650329643185755019374721283312409555437073732909098741047201773844526561647418227464551267229483364364787507813737149585117565634566192141414340259600731010898093526776126496041547237731611641645486484003184145020567881814736379969229029494635289881135938616525514478902350456632528118064943796968955206904548914444880294647813769276998813113219946458705248043346165647674144729512746228364422970492090341913955974680328429531371057246002643999064173272750228905488785306922291142352536443928185480992771540164041351189897263855717835200997174303403999921094709386555246470299674355058943232903678863339196093611888915090594863104904225697723818302850752252778621729255567862244645828296741411364052759345927008961382069718216739397512177938134054358858778504307167668875379987274830574712603824004594928740077761311104953146589024383734236839245668317380100215644546947907324757631546712895527026941128733402210258099040798244092233062921213678241433301492159422755411303594795618110694805740300672599304274581599355787281881473140136530753285
c2 = 104454128536114134666041330893412849924539319238173846030358370053912259066553198144201647771409151179389296499444225182922737580937571253329036303241246786394696273703737240494606350619424942154134043974057071462964750990605316877522861478098457922126670980711982715700886739488588258928454751146720846461285104408526738717417461756044249496795236713285815410740335507214955619176318929380672905570604946736070454970829122165657529519191829096299562653289959758115282220314539044233440940890830246113981226775616062418119272940675413756550528704261381830683804964448149613789234326868825958311202712158979318207791357868949882157781068305218079123962336473944242076822566261833638654949217602001305205868861207596016799305223552788863815955231724125485952140180911558328890683991762828843660578236671443539626857037266048369875048432191608492096923173890923193063698396903093080818130375913491435899432596884306387277070900092571026594195475769816837963280460673050909448174467601579491721191905742242149320815840931148597139521486968369237822382185925961430998718690684270284663782612688833325942954176755873192287461806363161966656749124978838440843037636615696962613067946478062682619739085469224316287147692903237078068956379036902948739451784308
c3 = 287293965964521577536949600465877039412983676330501517864975724662075373903418313335625721299388975721491357903306320184247853204477040142941778760057485916689064629860222657837690248122034022696608633347098541733229160810131864253603149064874701423636836348322909135954798560398776651665237804954916116590130313684752444052866519034694526102201271444707642449670451542864865493541141728546221679654661093081848121118684594168895062943920921063566925549212250270641028144352434459819122102852072762780335391277683962786782857084040582699842796641523261150308932398544110620418151887847658837961044285094404774616962577265970393150696357457400719726381090518685568644813512490876890790663593699326420593277088351600861395830498853994952245899881834621106473224692036187989636146643992437367194572335837111809655664187790935259739926115874944166340456171845363032300979740488782920318711668046034568790879401209465850491455677846746238706089490902017942125993304620807882387410264371825909245185927481186838760450566656551893404361562801495420174484277284394683958112760663980049171039021132584343301267863299152953512497843386144751245181609419591873712505993146385725244308823894723973026051800808472848805433371109206822668160634407950261536850484088

#u1,u2 = 615951939,660144937
#u1,u2 = 60616161,900840613
#u1,u2 = 96674589,897687113
u1,u2 = 492011439,757042187 #ok

m1 = b'Lorem Ipsum is simply dummy text of'
m2 = b'the printing and typesetting industry'

n = gcd(bytes_to_long(m1)^e-c2, bytes_to_long(m2)^e-c3)

r = isqrt(n//u1//u2)
P. = PolynomialRing(Zmod(n))
f = (u1*r + k1)*(u2*r + k2)
small_roots(f,bounds=(2^256,2^256), m=3, d=5)


r = isqrt(n//u1//u2)
P. = Zmod(n)[]
f = u1*r + x
v = f.small_roots(X=2^256, beta=0.499, epsilon=0.02)
p = int(f(v[0]))

m = pow(c1, inverse_mod(0x10001,p-1),p)
long_to_bytes(int(m))
#b'MCTF{hardy_muskat_williams2coppersmith}'

Counter On Me

AES CTR模式 padding oracle的题

from Crypto.Cipher import AES
from Crypto.Util import Counter
from Crypto.Util.Padding import pad, unpad
from Crypto.Util.number import bytes_to_long
import os

class CTR:
    def __init__(self):
        self.key = os.urandom(16)

    def encrypt(self, pt):
        iv = os.urandom(16)
        ctr = Counter.new(128, initial_value=bytes_to_long(iv))
        cipher = AES.new(self.key, AES.MODE_CTR, counter=ctr)
        enc = iv + cipher.encrypt(pad(pt, 16))
        return enc

    def decrypt(self, ct):
        try:
            ctr = Counter.new(128, initial_value=bytes_to_long(ct[:16]))
            cipher = AES.new(self.key, AES.MODE_CTR, counter=ctr)
            dec = unpad(cipher.decrypt(ct[16:]), 16)
            return dec
        except Exception:
            return False

if __name__ == "__main__":
    cipher = CTR()
    flag = os.getenv('FLAG', 'MCTF{ThisIsAFakeFlag}').encode()
    ct = cipher.encrypt(flag)
    print(f"CTR(flag)={ct.hex()}")
    while 1:
        enc = bytes.fromhex(input("enc="))
        dec = cipher.decrypt(enc)
        if bool(dec) or dec == flag:
            print('Look\'s good')
        else:
            print('Hum,this is a weird input')

CTR模式是每用counter生成密文再与明文异或。从后向前调整密文,使尾部符合pad就不会报错。这样得到未异或的密文,从而得到明文。

不过由于一些小问题,这个全自动有点麻烦。第1个是尾块,因为尾块是pad过的,所以爆破的时候会有两个不报错的情况。第2个是头块,头块不能出现pad 16的情况,所以第1个字符爆不出来,但是可以猜出来。

没有远端只能弄个测试数据了。

from pwn import *
#context.log_level = 'debug'

#p = remote('',)

from Crypto.Cipher import AES
from Crypto.Util import Counter
from Crypto.Util.Padding import pad, unpad
from Crypto.Util.number import bytes_to_long
import os
class CTR:
    def __init__(self):
        self.key = b'0123456789abcdef' #os.urandom(16)
    
    def encrypt(self, pt):
        iv = b'abcdef0123456789' #os.urandom(16)
        ctr = Counter.new(128, initial_value=bytes_to_long(iv))
        cipher = AES.new(self.key, AES.MODE_CTR, counter=ctr)
        enc = iv + cipher.encrypt(pad(pt, 16))
        return enc
    
    def decrypt(self, ct):
        try:
            ctr = Counter.new(128, initial_value=bytes_to_long(ct[:16]))
            cipher = AES.new(self.key, AES.MODE_CTR, counter=ctr)
            dec0 = cipher.decrypt(ct[16:])
            #print(ct[:16],ct[16:],dec0)
            dec = unpad(dec0, 16)
            return dec
        except Exception:
            return False

def getstate(enc):
    dec = cipher.decrypt(enc)
    if bool(dec) or dec == flag:
        return b'Look\'s good'
    else:
        return b'Hum,this is a weird input'

flag = 'MCTF{ThisIsAFakeFlag}'.encode()
cipher = CTR()
ct = cipher.encrypt(flag)
print(ct)
#p.recvuntil(b"CTR(flag)=")
#ct = bytes.fromhex(p.recvline().strip().decode())


#1
iv = ct[:16]
c1 = ct[16:]
print(iv,c1)
tail = b''
#末位,确定最后一个字符 如pad为 \x0b 则在 \x01,\x0b时都会正常返回good
for i in range(c1[-1]+1, c1[-1]+16):
    tc = c1[:len(c1)-1]+xor(bytes([1]), bytes([i])+tail)
    msg = getstate(iv+tc)
    if b'good' in msg:
        print(i, msg)

#37^47^1 = 0xb
tail = xor(c1[-11:],b'\x0b'*0xb)

#末段
for j in range(len(tail)+1, 17):
    #print(j)
    for i in range(256):
        tc = c1[:len(c1)-len(tail)-1]+xor(bytes([j]), bytes([i])+tail)
        msg = getstate(iv+tc)
        #print('send ',j,tc.hex(), msg)
        if b'good' in msg:
            tail = bytes([i]) + tail
            #print('--',i,tail)
            break

#得到
#tail = b'\x9b\xe9\x94\x91\xcb!\xd2\xe0B\xaf\x13\xe0\x0c\xe1\x97'
print(len(tail),tail, xor(tail,c1[-16:]))

tail = b''
c1 = c1[:-16]
#前边段,第1段少1位
for j in range(len(tail)+1, 17):
    #print(j)
    for i in range(256):
        tc = c1[:len(c1)-len(tail)-1]+xor(bytes([j]), bytes([i])+tail)
        msg = getstate(iv+tc)
        #print('send ',j,tc.hex(), msg)
        if b'good' in msg:
            tail = bytes([i]) + tail
            print('--',i,tail)
            break

print(len(tail),tail, xor(b'\0'+tail,c1[-16:]))

NeuraTek's Secrets

共用素数的题,gcd一下就得到p了。同时由于e很小crt也行

from Crypto.Util.number import getPrime, bytes_to_long
import math
from oh import FLAG

public_keys = []
private_keys = []

p = getPrime(512)
q1 = getPrime(512)
q2 = getPrime(512)
N1 = p * q1
N2 = p * q2
public_keys.extend([(N1, 3), (N2, 3)])
private_keys.extend([(p, q1), (p, q2)])

for _ in range(8):
    p = getPrime(512)
    q = getPrime(512)
    N = p * q
    public_keys.append((N, 3))
    private_keys.append((p, q))

ciphertexts = [pow(bytes_to_long(FLAG), 3, N) for N, _ in public_keys]

with open("public_keys.txt", "w") as f:
    for N, e in public_keys:
        f.write(f"{N},{e}\n")

with open("ciphertexts.bin", "wb") as f:
    for ct in ciphertexts:
        f.write(ct.to_bytes((ct.bit_length() + 7) // 8, 'big'))

你可能感兴趣的:(CTF)