naby

导航

BuildCTF2024-Crypto

差一题古典不想看了,其他方向就不献丑了

Crypto

OVO开门爽!开到南天门了兄弟

from Crypto.Util.number import *

flag = b'BuildCTF{******}'

#随机生成p,q
p = getPrime(1024)
q = getPrime(1024)

#计算模数n
n = p*q

e = 65537

m = bytes_to_long(flag)

#c=m^e%n
c = pow(m, e, n)

print('P = ',p**2)
print('Q = ',q**2)
print('n = ',n)
print('e = ',e)
print('c = ',c)

开根就行了

from Crypto.Util.number import *
from gmpy2 import *
P =  8279853330757234669136483032750824826175777927506575083710166412897012079466955769715275604152872242147320194640165649152928984919315754419447729793483984130396358578571137956571302516202649076619076831997922675572705848199504309232044502957866317011212505985284129365522570368395368427388904223782742850616983130885152785650513046301920305069822348366931825404271695876688539675285303882189060671184911139742554710018755565518014777733322795522710234091353878298486498244829638878949389690384488573338138825642381687749888102341379254137445546306796258092762099409409285871651688611387507673794784257901946892698481
Q =  9406643503176766688113904226702477322706664731714272632525763533395380298320140341860043591350428258361089106233876240175767826293976534568274153276542755524620138714767338820334748140365080856474253334033236457092764244994983837914955286808153784628739327217539701134939748313123071347697827279169952810727995681780717719971161661561936180553161888359929479143712061627854343656949334882218260141557768868222151468471946884225370009706900640851492798538458384449294042930831359723799893581568677433868531699360789800449077751798535497117004059734670912829358793175346866262442550715622833013235677926312075950550681
n =  8825283482190476005946253343638820879559355306860912268128891241513310054066424567824202757539757712177309282694997613217968336164050770152277369601415394249781577415456224120102543968285035647514461364611734338073523454354376992783551035395558194171202680855182868766563277697325690226849316944101739491659812174054898519492145495098671439125714086449826697343692081109131564556220174583970363431110462222473013021825770267803249515893736989430146194199936335153936611196467225599746830873958085287665223190767137404366840055297859554490123389877396965710177279558954630222879974581602069901175074777191362537419581
e =  65537
c =  27915082942179758159664000908789091022294710566838766903802097394437507062054409033932303966820096232375646873480427485844733381298467171069985418237873120984132166343258345389477844339261488318588760125230979340678006871754125487279212120945061845738130108370814509280317816067243605608952074687396728904772649873860508240809541545939219624254878900291126739390967820141036260712208555574522131446556595562330969209665291757386246648060990840787769772160549862538116370905306402293764494501838709895355570646716245976733542014165663539815972755562821443411642647981898636761822107221203966296758350547477576411216744594534002057673625678188824476543288048956124565509473100550838563085585434675727358831610724920550213350035792170323729397796947598697983084347567191009236345815968927729025919066227704728180060805553787151862426034275526605154807840695498644070184681962311639338273469859838505348823417234722270798882384367058630064108155240680307754557472476430983184039474907188578578484589833812196216551783354411797156409948499012005963943728564803898150155735762695825658678475746559900705796814512838380193603178657226033406812810314960142251012223576984115642351463684724512456778548853002653596485899854303126091917273560


p=int(iroot(P,2)[0])
q=int(iroot(Q,2)[0])
print(long_to_bytes(int(pow(c,invert(e,(p-1)*(q-1)),p*q))))

mitm

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

note = b'Crypt_AES*42$@'
r = 4
keys = []

for i in range(r):
    key = bytes(choices(note, k=3))
    keys.append(sha256(key).digest())

leak = b'Hello_BuildCTF!!'
cipher = leak
for i in range(r):
    cipher = AES.new(keys[i], AES.MODE_ECB).encrypt(cipher)

enc_key = sha256(b"".join(keys)).digest()
enc_flag = AES.new(enc_key, AES.MODE_ECB).encrypt(pad(flag, AES.block_size))

print(f'cipher = {cipher}')
print(f'enc_flag = {enc_flag}')

前段之前遇到过,就想出来了

参考的是小鸡块师傅的

crewCTF-4ES:2024-TFCCTF&crewCTF-wp-crypto | 糖醋小鸡块的blog (tangcuxiaojikuai.xyz)

from hashlib import sha256
from Crypto.Cipher import AES
import itertools
cipher = b'\xb9q\x04\xa3<\xf0\x11-\xe9\xfbo:\x9aQn\x81'
enc_flag = b'q\xcf\x08$%\xb0\x86\xee\x1a(b\x7f\xf8\x86\xbd\xd0\xa7\xee\xd9\x9d2\x82a7H=a\x13\x87e\xad\xd2b\x8e\x07\xa5\xddo\xc0\xf3N\xd4b\xc9o\x88$\xc7\xf4p\xc1\x1e,\xed\xcc\x94\x8c\xf4\x00\xa5\xe0-\xf7\xc5'

note = b'Crypt_AES*42$@'
leak = b'Hello_BuildCTF!!'

keys=[]
for key in itertools.product(note, repeat=3):
    keys.append(sha256(bytes(key)).digest())
print("over0")
pre={}
for key in itertools.product(keys, repeat=2):
    pre[AES.new(key[1], AES.MODE_ECB).encrypt(AES.new(key[0], AES.MODE_ECB).encrypt(leak))]=key
print("over1")
for key in itertools.product(keys, repeat=2):
    if AES.new(key[1], AES.MODE_ECB).decrypt(AES.new(key[0], AES.MODE_ECB).decrypt(cipher)) in pre.keys():
        pre_key=pre[AES.new(key[1], AES.MODE_ECB).decrypt(AES.new(key[0], AES.MODE_ECB).decrypt(cipher))]
        tmp=pre_key[0]+pre_key[1]+key[1]+key[0]
        keys=sha256(tmp).digest()
        flag = AES.new(keys, AES.MODE_ECB).decrypt(enc_flag)
        print(flag)
        exit()
#b'BuildCTF{M1tm_i5_@_simple_w@y_t0_s0lve_pr0bl3m!}\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'

我这辈子就是被古典给害了

from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES
from secret import flag, key

dict1 = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4,
         'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9,
         'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14,
         'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19,
         'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25}

dict2 = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E',
         5: 'F', 6: 'G', 7: 'H', 8: 'I', 9: 'J',
         10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O',
         15: 'P', 16: 'Q', 17: 'R', 18: 'S', 19: 'T',
         20: 'U', 21: 'V', 22: 'W', 23: 'X', 24: 'Y', 25: 'Z'}

def generate_key(flag, key):
    i = 0
    while True:
        if len(key) == len(flag):
            break
        key += flag[i]
        i += 1
    return key

def cipherText(msg, key_new):
    cipher_text = ''
    i = 0
    for letter in msg:
        x = (dict1[letter] + dict1[key_new[i]]) % 26
        i += 1
        cipher_text += dict2[x]
    return cipher_text

def AES_enc(key, value):
    key = (key * 2).encode()
    cipher = AES.new(key, AES.MODE_ECB)
    value = value.encode()
    padded_text = pad(value, AES.block_size)

    ciphertext = cipher.encrypt(padded_text)
    print("AES Encrypted Text =", ciphertext)

def substitute(msg):
    msg = msg.replace('{', 'X')
    msg = msg.replace('_', 'X')
    msg = msg.replace('}', 'X')
    msg = msg.upper()
    assert msg.isupper()
    return msg

message = substitute(flag)
key_new = generate_key(message, key)
cipher = cipherText(message, key_new)
print("Encrypted Text =", cipher)
AES_enc(key, flag)

讲解写在代码里了

dict1 = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4,
         'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9,
         'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14,
         'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19,
         'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25}

dict2 = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E',
         5: 'F', 6: 'G', 7: 'H', 8: 'I', 9: 'J',
         10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O',
         15: 'P', 16: 'Q', 17: 'R', 18: 'S', 19: 'T',
         20: 'U', 21: 'V', 22: 'W', 23: 'X', 24: 'Y', 25: 'Z'}

text = "HLMPWKGLYSWFACEWBYRSUKYFAXZFXDKOTZHHSLFCXNICAHPGRIFUF"
# len(AES_KEY)=16 24 32
# len(key)=8 12 16

# 假设key一开始长度为8,flag头猜测为BUILDCTFX
# 则key=????????BUILDCTFX
# 密文第9位,就等于现在key第九位'X' 加上 flag第一位'B'
# print(dict1[text[8]]) 24
# 23+1=24 ==> X+B 所以可以猜测一开始key长度为8

pre="BUILDCTF"
key=""
for i in range(8):
    key+=dict2[(dict1[text[i]]-dict1[pre[i]])%26]
# print(key)  # 结果为:GREETING,有明显英文意思,推论正确
from Crypto.Cipher import AES
c = b'\x92T{\x1f\x0f"\xbd\xbb\xfa|O\x11\x83\xa0\xec.\x15]\x9f\x9a\xe5\x85Z\x9f@yUm\xbb\xdc\x93\x08\xe5\x8b\xd5\x98\x84\xfa\x91\xe8\xde\x1b}\xcd\x9056\xa3\xbf\xdb\x85J\xcc\xec\x812T\x11\xa7Tl\x15\xf6"'
key=key*2
cipher = AES.new(key.encode(), AES.MODE_ECB)
ciphertext = cipher.decrypt(c)
print(ciphertext)
#b'BuildCTF{YOU_ALREADY_KNOW_WHAT_A_CLASSICAL_CIPHER_IS}\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b'

gift

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

def get_gift(p, q):
    noise = getPrime(40)
    p, q = p + 2 * noise + 1, q - pow(noise, 2)
    gift = 2024 * (p + q)
    return gift

p = getPrime(512)
q = getPrime(512)
n = p * q
e = 0x10001
m = bytes_to_long(flag)

c = pow(m, e, n)
gift = get_gift(p, q)

print(f'c = {c}')
print(f'n = {n}')
print(f'gift = {gift}')
'''
c = 101383046356447336426623798470530695448361708798731382238747567108067236241251384089401506320741815081024352908156466877907424203888923965647318146770258139921360377246187637085549628797640957048672797430217647039035455011311505942632107576730906489223641894279483592789523228409885925263914621255862261546919
n = 131097719698687108485813302886652389604731026998272796315024695395496199386497660846418712521921387496051077394308820230360184411431376692252923609505060476542577219656866593501271690536991944882324175509626138475159461332403161471880082192150081456601522403673111515117219716055561941951891570977025178643791
gift = 46635322848619790584491725916282901439691751328335921415278638528896063068132242718070261114525516272650970256270551306096774004921902972838212903368063625872
'''

不愧是noise,noise40位,平方之后差不多80位,p和q都是512位的,相加之后可以相当于丢失了低80位,所以就想到是p+q的高位攻击。

我直接偷dexter师傅的代码了

https://dexterjie.github.io/2023/09/07/挨打日记/#2023长城杯——p-q高位泄露

N = 131097719698687108485813302886652389604731026998272796315024695395496199386497660846418712521921387496051077394308820230360184411431376692252923609505060476542577219656866593501271690536991944882324175509626138475159461332403161471880082192150081456601522403673111515117219716055561941951891570977025178643791
gift = 46635322848619790584491725916282901439691751328335921415278638528896063068132242718070261114525516272650970256270551306096774004921902972838212903368063625872
gift=gift//2024

gift=gift>>90
gift=gift<<90
 
PR.<x> = PolynomialRing(Zmod(N))
ok = False
test=1
def pq_add(tp,tq,tgift,idx):
    global ok 
    global test
    if ok:
        return 
    if tp*tq>N:
        #print('>')
        return 
    
    if (tp+(2<<idx))*(tq+(2<<idx))<N:
        #print('<', hex((tp+(1<<(idx+2))))[:20], hex(tq+(2<<idx))[:20], hex(N)[:20])
        return 
        
    if idx<=90:
        try:
            test += 1
            print(test)
            for i in range(1024):
                tpp = tp+(i<<90)
                f = tpp + x 
                test += 1
                rr = f.monic().small_roots(X=2^90, beta=0.4)
                if rr != []:
                    print(rr)
                    print(tpp)
                    print('p = ',f(rr[0]))
                    ok = True
                    return
        except:
            pass
        
        return
    
    idx -=1
    b = tgift >>idx 
    one = 1<<idx
    
    #print(hex(tp)[:20],hex(tq)[:20],hex(tgift)[:20],idx,b)
    
    if b==0 or b==1:
        pq_add(tp,tq,tgift,idx)    
    if b==1 or b==2:
        pq_add(tp+one,tq,tgift-one,idx)
        pq_add(tp,tq+one,tgift-one,idx)
    if b==2 or b==3:
        pq_add(tp+one,tq+one,tgift-(one<<1),idx)
        
if 0:
    tp = 1<<511
    tq = 1<<511
    tgift = gift -tp -tq 
    pq_add(tp,tq,tgift,511)
"""
print(test)
print("OK")
print("111111111111")
17427
[700928575142400370721495237]
12795781443930923314957498667934210380943999998587811382302993343213015802362418444051944067150691108651897157419444913377465524852577234852023651836887040
p =  12795781443930923314957498667934210380943999998587811382302993343213015802362418444051944067150691108651897157419444913377465525553505809994424022558382277
17432
OK
111111111111
"""
from Crypto.Util.number import *
p =  12795781443930923314957498667934210380943999998587811382302993343213015802362418444051944067150691108651897157419444913377465525553505809994424022558382277
c = 101383046356447336426623798470530695448361708798731382238747567108067236241251384089401506320741815081024352908156466877907424203888923965647318146770258139921360377246187637085549628797640957048672797430217647039035455011311505942632107576730906489223641894279483592789523228409885925263914621255862261546919

print(long_to_bytes(int(pow(c,inverse_mod(65537,p-1),p))))
# b'BuildCTF{M@y_b3_S0m3th1ng_go_wr0ng}'

ominous

from Crypto.Util.number import *
from secret import flag
import random
import string

Ominous_dic = ['啊', '米', '诺', '斯']
flag_word = (string.ascii_letters + string.digits + '{}@_!').encode()
assert all(char in flag_word for char in flag)

msg = bytes_to_long(flag)
random.shuffle(Ominous_dic)

def Ominous_enc(msg):
    res = 0
    for idx, word in enumerate(Ominous_dic):
        res += random.randint(0, 200) * ord(word) * (2 ** (50 * (idx + 1))) 
    
    return res + msg

cipher = Ominous_enc(msg)
print(f'cipher = {cipher}')

本质上还是跟位数相关,res每次加的随机值都是每50位的低位,所以我们可以分段来考虑爆破

每次提取密文的48位(按字节分组才好处理)

具体看代码就能理解了。

from Crypto.Util.number import *
import string
flag_word = (string.ascii_letters + string.digits + '{}@_!').encode()
cipher = 11174132013050242293373893046306047184706656363469879247040688497021

#print(bin(cipher))
flag1="1101010000110101100111101101100"
flag2="011001000100001101011001011000010011001011010111"
flag3="011010000100000001111000010010111000100101010101"
flag4="010111110011000001101101111001101111011010100111"
flag5="011101010111001100100001001000010010000101111101"


Ominous_dic = ['啊', '米', '诺', '斯']
words=[ord(word) for word in Ominous_dic]
#print(words)

"""words=[21834, 31859, 35834, 26031]
for i in words:
    for j in range(200):
        tmp=int(flag4+flag5,2)
        tmp-=i*j*2**50
        tmp=long_to_bytes(tmp)
        if all(char in flag_word for char in tmp):
            print(tmp,i,j)
#b'_0m1nous!!!}' 35834 83"""

"""words=[21834, 31859, 26031]
for i in words:
    for j in range(200):
        tmp=int(flag3+flag4+flag5,2)
        tmp-=i*j*2**100+35834*83*2**50
        tmp=long_to_bytes(tmp)
        if all(char in flag_word for char in tmp):
            print(tmp,i,j)
#b'h@t_i5_0m1nous!!!}' 26031 158"""

"""words=[21834, 31859]
for i in words:
    for j in range(200):
        tmp=int(flag2+flag3+flag4+flag5,2)
        tmp-=i*j*2**150+26031*158*2**100+35834*83*2**50
        tmp=long_to_bytes(tmp)
        if all(char in flag_word for char in tmp):
            print(tmp,i,j)
#b'dCTF{Wh@t_i5_0m1nous!!!}' 31859 42"""

words=[21834]
for i in words:
    for j in range(200):
        tmp=int(flag1+flag2+flag3+flag4+flag5,2)
        tmp-=i*j*2**200+31859*42*2**150+26031*158*2**100+35834*83*2**50
        tmp=long_to_bytes(tmp)
        if all(char in flag_word for char in tmp):
            print(tmp,i,j)
#b'BuildCTF{Wh@t_i5_0m1nous!!!}' 21834 119

ez_matrix

#SageMath 9.5
from Crypto.Util.number import *
from gmpy2 import powmod
from secret import msg

def pad(x, pad_length):
    return x + b'\x00' * (pad_length - len(x))

def rsa_gen(bits):
    p = getPrime(bits)
    q = getPrime(bits)
    return p, q

bits = 1024
pad_length = 200
matrix_size = 32
e = 65537

p, q = rsa_gen(bits)
n = p * q
m = bytes_to_long(pad(msg, pad_length))
c = powmod(m, e, n)

p_binary = bin(p).replace('0b', '').zfill(bits)
q_binary = bin(q).replace('0b', '').zfill(bits)

P = matrix(GF(2), [list(map(int, p_binary[i:i+matrix_size])) for i in range(0, len(p_binary), matrix_size)])
Q = matrix(GF(2), [list(map(int, q_binary[i:i+matrix_size])) for i in range(0, len(q_binary), matrix_size)])
gift = P.solve_right(Q)

with open('output', 'w') as file:
    file.write(f'c = {c}\n')
    file.write(f'p ^ q = {p ^^ q}\n')
    file.write('gift:\n')
    for row in gift:
        file.write(' '.join(map(str, row)) + '\n')

关键点,要能意识到p^q,实际上就是矩阵P+Q,因为都是模2域下的操作,所以都是模2加法。

所以我们就能得到P+Q和Pgift=Q,推导如下:

\[设A=P+Q,B=gift=P^{-1}Q\\ 因为是模2域下,所以有Q=A-P=A+P,带入B得\\ B=P^{-1}(A+P)=P^{-1}A+E\\ 同理有P^{-1}A=B+E\\ 使用sagemath中的solve\_left,可以直接求解出P^{-1}\\ 然后求逆就好了 \]

from Crypto.Util.number import *
from gmpy2 import *
bits = 1024
matrix_size = 32
pxorq = 89144063720545532404936347749976033995959352088369581593483294017916269127126015515514164556238892315116219488234599276283755643115494368387307879815221830970632672104176330851649236203019768799744400071934922875736029236458980333704716550922984411453411523931115952319603510996580835848026227775168231757398
pxorq_binary = bin(pxorq).replace('0b', '').zfill(bits)

gift="0010111001000011001001000100110010100001011111010111010001100001010111110110100100011011011110000111010000100100000001111010110101011110100100110011101001001011111001000101000010000101000000111010111011101111000000101010010010101010110111001010010001111010001011101110010000010001001010111000000111111011000000010110111110001100110110111111000000000111001110100010101110011101011110001100110101010010000010111010110110001100111100010011110010010110100111011100011000110011000001111001001011110011110010110000111001000100100000001011001011111001000101111011110000100000011011010011111001001110000111001001010001000010110101011001000000110011100000001111011001010111101100010000001011111010001101110011111101011001001110000111111111110111110001101100000010010110010010111100000110001111110111111001011001110101001000011100001110000100010110000111111010101011001100101111101100010010000100110110001111111110111001010110000111010000011110011011101101000101100000110110101010100011110000110101111101101101101001000110101100110111"
gift_binary = gift.zfill(bits)

A = matrix(GF(2), [list(map(int, pxorq_binary[i:i+matrix_size])) for i in range(0, len(pxorq_binary), matrix_size)])
B = matrix(GF(2), [list(map(int, gift[i:i+matrix_size])) for i in range(0, len(gift_binary), matrix_size)])

E=identity_matrix(GF(2), 32)

P_1=A.solve_left(B+E)
P=P_1.inverse()
p=""
for i in P:
    for j in i:
        p+=str(j)
p=int(p,2)
print(p.bit_length(),isPrime(p))
Q=P+A
q=""
for i in Q:
    for j in i:
        q+=str(j)
q=int(q,2)
print(q.bit_length(),isPrime(q))
 

n=p*q
phi=(p-1)*(q-1)
e=65537
c = 5750862006780374919287214285692236210204656897730327429454502213453716609006462693326927544526483929921956237739564314742381291228170724611684726314766300684189083862768843433748971907962075938141567163713163231477418107343867114651242407427262164467193346523730926798966915657982552864539513197192523866321569716738540583056085357621328692775578162692288348251605475475005408200801081747601745630186390866011595954211521326069111983199120520535552104591110478015154646709731714695120857959832894595677697407284511806934799265823961155753765208975629786832407640872204810033141414096894416317703257346937008503926274
print(long_to_bytes((int(powmod(c,invert(e,phi),n)))))
#BuildCTF{78e09053-bc0a-4fdc-9dec-0f107bf9ba43}

Ju5t_d3c0de_1t!

e = 'VTJGc2RHVmtYMThUWGplSkN2YzJwazJ2KzJieQ=='
c = 10110011010010110101101101011110100001010100101110111011101101111101101001000010111010010011101111001111111000000001111000000010101
p = 1100010000110101100011011010101011111101001101010011001010110111100011110110101111000101100001011011001100110010010111111100110000001111010111111101111001100111100011100110110011101011111011100111010011000100011001101101111011010110000011011100101010010101110001011011010111001010101101100101011111101000110010111000011010111001101001
q = 11000010010010011110101110100011011100101101100100011011100010111000011110111000000011111100010100100000101101010101000101101101101011011100001101111010001010010011001010110010110101001100100011010110100011110011101110101110111110100000011110101010011011111010111100011000011111001000010101100100011110010000010001110010101100100111001
key = 592924741013363689040199750462798275514934297277010275281372369969899775117892551575873706970423924419480394766364097497072075403342004187895966953143489192628648965081601335846012859223829286606349019
# use m minus key to get the final flag!

解码e,解第一层base64,再解一层的话发现前面为Salt_开头,猜测为Rabbit加密,无密钥解密就得到了
https://tool.oschina.net/encrypt

剩下的都一眼出了(最后根据提示m减一下key就行了)

from Crypto.Util.number import *
from base64 import *
e = 'VTJGc2RHVmtYMThUWGplSkN2YzJwazJ2KzJieQ=='
c = 10110011010010110101101101011110100001010100101110111011101101111101101001000010111010010011101111001111111000000001111000000010101
p = 1100010000110101100011011010101011111101001101010011001010110111100011110110101111000101100001011011001100110010010111111100110000001111010111111101111001100111100011100110110011101011111011100111010011000100011001101101111011010110000011011100101010010101110001011011010111001010101101100101011111101000110010111000011010111001101001
q = 11000010010010011110101110100011011100101101100100011011100010111000011110111000000011111100010100100000101101010101000101101101101011011100001101111010001010010011001010110010110101001100100011010110100011110011101110101110111110100000011110101010011011111010111100011000011111001000010101100100011110010000010001110010101100100111001
key = 592924741013363689040199750462798275514934297277010275281372369969899775117892551575873706970423924419480394766364097497072075403342004187895966953143489192628648965081601335846012859223829286606349019

e=65537
c=int(str(c),2)
p=int(str(p),2)
q=int(str(q),2)

n=p*q
m=pow(c,inverse(e,(p-1)*(q-1)),n)
m=m-key
print(long_to_bytes(m))
#b'I_l1k3_crypt0_5o_h4rd!'

ezzzzz_RSA

import libnum
from Crypto.Util.number import *

flag = b'BuildCTF{*******}'

m = libnum.s2n(flag)

e = 65537
q = getPrime(1024)
q1 = getPrime(1024)
p = getPrime(1024)
p1 = getPrime(1024)

n = p * q
n1 = q * p1
n2 = p * q1
c = pow(m, e, n)
h0 = pow(2023 * p + 2024, q1, n2)
h1 = pow(2024 * p1 + 2023 * q, 113, n1)
h2 = pow(2023 * p1 + 2024 * q, 629, n1)

print(f'n1 = {n1}')
print(f'n2 = {n2}')
print(f'c = {c}')
print(f"h0 = {h0}")
print(f"h1 = {h1}")
print(f"h2 = {h2}")

解出来一个就够m的大小了

解p

\[h_0=(2023p+2024)^q\mod n\\ 二项式定理展开模去p,得h_0=2024^q\mod p\\ n=p*q→p=\frac{n}{q}→p-1=\frac{n-q}{q}→q=n-q(p-1)\\ h_0=2024^{n-q(p-1)}\mod p\\ 由费马小定理得:h_0=2024^n\mod p\\ h_0=2024^n+kp\\ kp=2024^n-h_0\\ 之后求gcd即可。 \]

from Crypto.Util.number import *
from gmpy2 import *
n2 = 11933661747067216317642315621042074566046499785197709817779978157416906347669444374234313329064859622960743743511735672614999566264025648698589886185056758071718319964262619819143757922916624196354313322456534266520150543008117888101349920396737532937616502689667208207329048979872222563877933742673021891249520999021187404065706388700711208445628041386956459398271230236018476964839399245143666534359113777846535151773174701732284280083586580489995666306373839417946648196140879978268472361473557375951972193618245984950374326806423407152520541682571610372434453778172497925696535270204943842467472100237854318244291
h0 = 2996726009726260695732821166504040344731102637047682432884058857493935625094258046641569918904978173116793673563730117949606727933902262668880339210084101176866383602543966179840353633735507442926707342258391362245904850297416642271123328980812931025677857373199540129280097315832907023777052101133649877194495480543646472133854655383755313968952550827443970931104462445312146328606862802196901953935238972759852435882720786570965542286278549107402918041194008845717507735786897968734831064393337773557817839343449001368565856921138408039931608804233595980497557733714560035682416265029819340316734845279080134432704

p = gcd(pow(2024,n2,n2)-h0,n2)

c = 20080676122944896238797522372441559951736929534371084097400233944319893926800196694449564534150770085554349952433141815637324753386484549616573636001763815852095984830828952020047938406909274311785306299061021662484544371813739713520361343350959698642021322243662988875917088108399877176033404097457939417134483333264562602633853694382014472747500159100723626314928476484037666519857604568300967071868151508142784271042600815406853978696857309760951105852288354603503207383899902135741426285551161292195639862478256231538619968275273876467583013024899054710124331145912185471501398910765579441956531091561893256832468
e=65537

m=long_to_bytes(pow(c,invert(e,p-1),p))
print(m)
#b'BuildCTF{29g5blh5-7829-5k38-a836-9bk54h291h6}'

解q

\[h_1=(ap+bq)^{e_1}\mod n\\ h_2=(bp+aq)^{e_2}\mod n\\ h_1=(ap)^{e_1}\mod q\\ h_2=(bp)^{e_2}\mod q\\ h_1*b^{e_1}=(abp)^{e_1}\mod q\\ h_2*a^{e_2}=(abp)^{e_2}\mod q\\ (h_1*b^{e_1})^{e_2}=(abp)^{e_1e_2}+k_1q\\ (h_2*a^{e_2})^{e_1}=(abp)^{e_1e_2}+k_2q\\ 两式相减,再与n求gcd即可 \]

from Crypto.Util.number import *
from gmpy2 import *
n1 = 19957426023169626195602761840035904096149402534966487535713447987366768645542881124782551268978342063458430846877824210659778126281705984711061190351636497944943321988950188171159903717348936556346198638311950016136865425015037098270040031872702873264144372191898253134939805153141701819590164140250130420280491966786900651186941317959556066730959744279963976065565436153399679475410040773637142677936926894677919242351610457296203864806991539480593546084449323017670431590012312526757477514457145686070196978477495658962519391041011847512041022828710693830661412217389320600888361578917153088073678587422269955710471
h1 = 19843160604742228074331688651361052208481287636527838615063387670722213224954610448720065937378201545177278841575633697012434074186046556843292068835752113384756149944114298949115412819730843598288637259467085268861201775723817790428386595559040938133481222229290199923979132846871398172318539492741755408720073350962388138453341677009547616238262211176727424067946020683742262782319735286357465817786446238528187722959357444676512705451504136333336415880020502524009647940182721264953084120705872870651891290569527156804993340563927419561415555818468261824287933683736509372616293569615247228388443284457740072850735
h2 = 15147052684674827267989051566164167603473413362261253296001082161136918959833294463185335416662127368473980239667918561600741667513285708843081475074688239507330230558331408877583246661862040918410036936505307437329914363201630212163952357444441705663871720438955166472073576526814546767805314463827075388036712200327696168965762177567346966479399896578190111819130000991594490932388132188241726654756368698998232826340969288082645860324404980143489489946490266439447342461483490582149239131554246756547000945718737195930407251232848166108751122870333559461452459416252942341423373918245090162970624108991537972775066

e1=113
e2=629
a=2024
b=2023

tmp1=pow(h1*(pow(b,e1,n1)),e2,n1)
tmp2=pow(h2*(pow(a,e2,n1)),e1,n1)

q=gcd(tmp1-tmp2,n1)

c = 20080676122944896238797522372441559951736929534371084097400233944319893926800196694449564534150770085554349952433141815637324753386484549616573636001763815852095984830828952020047938406909274311785306299061021662484544371813739713520361343350959698642021322243662988875917088108399877176033404097457939417134483333264562602633853694382014472747500159100723626314928476484037666519857604568300967071868151508142784271042600815406853978696857309760951105852288354603503207383899902135741426285551161292195639862478256231538619968275273876467583013024899054710124331145912185471501398910765579441956531091561893256832468
e=65537
m=long_to_bytes(pow(c,invert(e,q-1),q))
print(m)

where is my n?

from Crypto.Util.number import*
from gmpy2 import*

flag = "..."
e=65537
p=getPrime(512)
q=gmpy2.next_prime(p)
n=p*q
phi=(p-1)*(q-1)
d=inverse(e,phi)
c=pow(flag,e,n)
print("c=",c)
print("e=",e)
print("d=",d)

SHCTF第一周的d_known

我自己的博客:SHCTF2024-week1-crypto&其他 - Naby - 博客园 (cnblogs.com)

from Crypto.Util.number import*
from gmpy2 import*
c= 107973408658512316248795675829719026556281556876279221462095299771897472835817102507431099132436173117611783572607408542140665445616624626408781699266046553444252772105867617770124779786841928535661872891635303381758336724610931502145965143374870804147444436791292512235485326451051756451904673491759905663466
e= 65537
d= 62036379179617188220635702722848631787124203142048526951004487465970915306760341332025319712290841316288636152355908585406155087541334717529113872233640624205650204907669681116401961584897042519881342485819364897891612540596760113597723865477121348794797592568686540283535491492936074500143092361821406613969
p_bits=512
q_bits=512
 
k_phi = e*d -1
pphi = []
for k in range(e,2,-1):
    if k_phi % k == 0:
        tmp = k_phi // k
        if int(tmp).bit_length()==p_bits+q_bits:
            pphi.append(tmp)
for k in pphi:
    pp=iroot(k,2)[0]
    pp=next_prime(pp)
    for i in range(100):
        flag=long_to_bytes(pow(c,invert(e,pp-1),pp))
        if b'BuildCTF' in flag:
            print(flag)
            exit()
        pp=next_prime(pp)
#b'BuildCTF{Y0u_F1nd_7he_n_success7u1_!}'

girls_band_cry_pto

from Crypto.Util.number import *
import gmpy2


def getprime(kbit,FLAG):
    a = getPrime(kbit)
    b = getPrime(kbit)
    N = getPrime(kbit+5)
    seed = getPrime(kbit)
    t = seed
    list_t = []
    for i in range(10):
        t = (a*t+b)%N
        list_t.append(t)
    if FLAG:
        print(list_t)
    return seed



p = getprime(512,1)
q = getprime(512,0)
flag = b'...'
flag = bytes_to_long(flag)
n = p*q
e = 1384626

assert flag.bit_length() < n.bit_length()//2

c = pow(flag,e,n)

print('c=',c)

具体过程我就不讲了,太麻烦了,直接拿一些模板了

第一步利用LCG,求出p

然后发现e和phi(p)不互素,gcd之后为6

直接求e//6的逆,求出m的6次方

发现(p-1)%4=1,利用cipoll算法(参考0xGame一题)进行开平方根

得到m的3次方,最后使用AMM算法开3次根,直接就能秒出了

(直接用AMM跑开6次根貌似出不来)

import math
import random
from Crypto.Util.number import *
from gmpy2 import *
s=[37382128984932009103055100236038298684187701771245912912208816283882352432386956435965036367810667394024993955812239704879381327228911265588017046627348503, 78860822396220922181257740301787328387654351181949135165584053897837116358564567613593406267620270397593757280733139576593428399156673217202739776358215953, 71961258377748802736482119449608198361898650603044501972923193831637292104436919483148544126546157761435847502622416800596454167412705966674707485447149592, 87271087644907910379168026089161507515679859469787715709089631773745967695993043069981508275969979669395420678260957179827954920361899134388830957711827969, 72060448202158281754256475874109091993193239479491265267010728401711694585210195554635415348891139571830347004379216450772696235700910532153698412887476412, 198822737610698203376629161658629276556973499054887457432530950247888991546498594767954251786997515337433684733300663470799887569646159225800449429896258899, 186920895499932700150962847893153648403293237986492275627558112493385728113172211076262656795948951216023567806119078906412693819469136004563793414149643278, 56472634592713718635518027850351194341092172882542912776939953869983486542308422043454035086533070566859787384014556343587278097326244663175874047755695694, 42665120723108982921319232615099077060109901818313520605789700720605479528247045699344736360219784997528870841912999130951916510491705708498185762196467897, 205629005887807114384057131575309344114082007367662384600399313743755704623421415135564859072125246431180953419843187244789534372794288258609006920825136808]
"""
1.Xn+1反推出Xn	Xn=(a-1 (Xn+1 - b))%m
2.求a	        a=((Xn+2-Xn+1)(Xn+1-Xn)-1)%m
3.求b	        b=(Xn+1 - aXn)%m
4.求m	        tn=Xn+1-Xn,m=gcd((tn+1tn-1 - tntn) , (tntn-2 - tn-1tn-1))
逆着求
"""
length=len(s)
t = []
for i in range(length-1):
    t.append(s[i]-s[i-1])
all_n = []
for i in range(length-3):
    all_n.append(gcd((t[i+1]*t[i-1]-t[i]*t[i]), (t[i+2]*t[i]-t[i+1]*t[i+1])))


for n in all_n:
    try:
        n=abs(n)
        if n==1:
            continue
        a=(s[2]-s[1])*invert((s[1]-s[0]),n)%n
        ani=invert(a,n)
        b=(s[1]-a*s[0])%n
        seed = (ani*(s[0]-b))%n
        if isPrime(seed) and seed.bit_length()==512:
            p=int(seed)
    except:
        pass


c= 51846448616255629242918159354807752786692784645460532308823434086479848425723111371477823327980874708898952566998637230358105087254392989515438172155717708590176244736140994735777168368143405720703501031813936741444894000217727880068767785957507824708838189619286341612305393812568642372035793481458142583420
e = 1384626


g=gcd(e,p-1)
e=e//g
m=pow(c,invert(e,(p-1)//g),p)

def square_root_of_quadratic_residue(n, modulo):
    """Square root of quadratic residue

    Solve the square root of quadratic residue using Cipolla's algorithm with Legendre symbol
    Returns:
        int -- if n is a quadratic residue,
                   return x, such that x^{2} = n (mod modulo)
               otherwise, return -1
    """
    if modulo == 2:
        return 1
    if n % modulo == 0:
        return 0
    Legendre = lambda n: pow(n, modulo - 1 >> 1, modulo)
    if Legendre(n) == modulo - 1:
        return -1
    t = 0
    while Legendre(t ** 2 - n) != modulo - 1:
        t += 1
    w = (t ** 2 - n) % modulo
    return (generate_quadratic_field(w, modulo)(t, 1) ** (modulo + 1 >> 1)).x

def generate_quadratic_field(d, modulo=0):
    """Generate quadratic field number class

    Returns:
        class -- quadratic field number class
    """
    assert (isinstance(modulo, int) and modulo >= 0)

    class QuadraticFieldNumber:
        def __init__(self, x, y):
            self.x = x % modulo
            self.y = y % modulo

        def __mul__(self, another):
            x = self.x * another.x + d * self.y * another.y
            y = self.x * another.y + self.y * another.x
            return self.__class__(x, y)

        def __pow__(self, exponent):
            result = self.__class__(1, 0)
            if exponent:
                temporary = self.__class__(self.x, self.y)
                while exponent:
                    if exponent & 1:
                        result *= temporary
                    temporary *= temporary
                    exponent >>= 1
            return result

        def __str__(self):
            return '({}, {} \\sqrt({}))'.format(self.x, self.y, d)

    return QuadraticFieldNumber

mp=square_root_of_quadratic_residue(m,p)
mp=[mp,p-mp]
def onemod(e, q):
    p = random.randint(1, q-1)
    while(powmod(p, (q-1)//e, q) == 1):  # (r,s)=1
        p = random.randint(1, q)
    return p

def AMM_rth(o, r, q):  # r|(q-1
    assert((q-1) % r == 0)
    p = onemod(r, q)

    t = 0
    s = q-1
    while(s % r == 0):
        s = s//r
        t += 1
    k = 1
    while((s*k+1) % r != 0):
        k += 1
    alp = (s*k+1)//r

    a = powmod(p, r**(t-1)*s, q)
    b = powmod(o, r*a-1, q)
    c = powmod(p, s, q)
    h = 1

    for i in range(1, t-1):
        d = powmod(int(b), r**(t-1-i), q)
        if d == 1:
            j = 0
        else:
            j = (-math.log(d, a)) % r
        b = (b*(c**(r*j))) % q
        h = (h*c**j) % q
        c = (c*r) % q
    result = (powmod(o, alp, q)*h)
    return result

def ALL_Solution(m, q, rt, cq, e):
    mp = []
    for pr in rt:
        r = (pr*m) % q
        # assert(pow(r, e, q) == cq)
        mp.append(r)
    return mp


def calc(mp, mq, e, p, q):
    i = 1
    j = 1
    t1 = invert(q, p)
    t2 = invert(p, q)
    for mp1 in mp:
        for mq1 in mq:
            j += 1
            if j % 100000 == 0:
                print(j)
            ans = (mp1*t1*q+mq1*t2*p) % (p*q)
            if check(ans):
                return
    return



def ALL_ROOT2(r, q):  # use function set() and .add() ensure that the generated elements are not repeated
    li = set()
    while(len(li) < r):
        p = powmod(random.randint(1, q-1), (q-1)//r, q)
        li.add(p)
    return li
for i in mp:
    cp = i % p
    mp = AMM_rth(cp, 3, p)
    rt1 = ALL_ROOT2(3, p)
    amp = ALL_Solution(mp, p, rt1, cp, 3)
    for j in amp:
        print(long_to_bytes(int(j)))
#b'BuildCTF{crypt0_15_s0_e@5y!}'

posted on 2024-10-27 10:08  Naby  阅读(145)  评论(0编辑  收藏  举报