2024 网鼎杯 CTF --- Crypto wp

news2024/11/5 18:32:07

文章目录

      • 青龙组
        • Crypto1
        • Crypto2
      • 白虎组
        • Crypto1
        • Crypto2
      • 朱雀组
        • Crypto2
        • Crypto3
          • part1
          • part2
          • part3
          • part4

青龙组

Crypto1

题目:

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

p = getPrime(512)
q = getPrime(512)
n = p * q
d = getPrime(299)
e = inverse(d,(p-1)*(q-1))
m = bytes_to_long(flag)
c = pow(m,e,n)
hint1 = p >> (512-70)
hint2 = q >> (512-70)

print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")
print(f"hint1 = {hint1}")
print(f"hint2 = {hint2}")

n = 123789043095302886784777548580725867919630872720308267296330863659260260632444171595208750648710642616709290340791408935502415290984231140635423328808872594955139658822363033096014857287439409252367248420356169878044065798634016290690979979625051287064109800759113475629317869327100941592970373827299442569489
e = 112070481298571389221611833986644006256566240788306316765530852688390558290807060037831460397016038678699757261874520899143918664293504728402666398893964929840011110057060969775245481057773655679041350091817099143204028098431544760662690479779286160425059494739419234859710815966582837874194763305328789592245
c = 63662561509209168743977531923281040338804656992093161358503738280395090747786427812762995865224617853709000826994250614233562094619845247321880231488631212423212167167713869682181551433686816142488666533035193128298379649809096863305651271646535125466745409868274019550361728139482502448613835444108383177119

hint1 = 897446442156802074692
hint2 = 1069442646630079275131

论文:367.pdf
在这里插入图片描述

高位boneh_durfee攻击
exp:

import time
time.clock = time.time
 
debug = True
 
strict = False
 
helpful_only = True
dimension_min = 7 # 如果晶格达到该尺寸,则停止移除
# 显示有用矢量的统计数据
def helpful_vectors(BB, modulus):
    nothelpful = 0
    for ii in range(BB.dimensions()[0]):
        if BB[ii,ii] >= modulus:
            nothelpful += 1


# 显示带有 0 和 X 的矩阵
def matrix_overview(BB, bound):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d ' % ii)
        for jj in range(BB.dimensions()[1]):
            a += '0' if BB[ii,jj] == 0 else 'X'
            if BB.dimensions()[0] < 60: 
                a += ' '
        if BB[ii, ii] >= bound:
            a += '~'
        #print (a)

# 尝试删除无用的向量
# 从当前 = n-1(最后一个向量)开始
def remove_unhelpful(BB, monomials, bound, current):
    # 我们从当前 = n-1(最后一个向量)开始
    if current == -1 or BB.dimensions()[0] <= dimension_min:
        return BB
 
    # 开始从后面检查
    for ii in range(current, -1, -1):
        #  如果它没有用
        if BB[ii, ii] >= bound:
            affected_vectors = 0
            affected_vector_index = 0
             # 让我们检查它是否影响其他向量
            for jj in range(ii + 1, BB.dimensions()[0]):
                # 如果另一个向量受到影响:
                # 我们增加计数
                if BB[jj, ii] != 0:
                    affected_vectors += 1
                    affected_vector_index = jj
 
            # 等级:0
            # 如果没有其他载体最终受到影响
            # 我们删除它
            if affected_vectors == 0:
                #print ("* removing unhelpful vector", ii)
                BB = BB.delete_columns([ii])
                BB = BB.delete_rows([ii])
                monomials.pop(ii)
                BB = remove_unhelpful(BB, monomials, bound, ii-1)
                return BB
 
           # 等级:1
            #如果只有一个受到影响,我们会检查
            # 如果它正在影响别的向量
            elif affected_vectors == 1:
                affected_deeper = True
                for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
                    # 如果它影响哪怕一个向量
                    # 我们放弃这个
                    if BB[kk, affected_vector_index] != 0:
                        affected_deeper = False
                # 如果没有其他向量受到影响,则将其删除,并且
                # 这个有用的向量不够有用
                #与我们无用的相比
                if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
                    #print ("* removing unhelpful vectors", ii, "and", affected_vector_index)
                    BB = BB.delete_columns([affected_vector_index, ii])
                    BB = BB.delete_rows([affected_vector_index, ii])
                    monomials.pop(affected_vector_index)
                    monomials.pop(ii)
                    BB = remove_unhelpful(BB, monomials, bound, ii-1)
                    return BB
    # nothing happened
    return BB
 
""" 
Returns:
* 0,0   if it fails
* -1,-1 如果 "strict=true",并且行列式不受约束
* x0,y0 the solutions of `pol`
"""
def boneh_durfee(pol, modulus, mm, tt, XX, YY):
    """
    Boneh and Durfee revisited by Herrmann and May
 
 在以下情况下找到解决方案:
* d < N^delta
* |x|< e^delta
* |y|< e^0.5
每当 delta < 1 - sqrt(2)/2 ~ 0.292
    """
 
    # substitution (Herrman and May)
    PR.<u, x, y> = PolynomialRing(ZZ)   #多项式环
    Q = PR.quotient(x*y + 1 - u)        #  u = xy + 1
    polZ = Q(pol).lift()
 
    UU = XX*YY + 1
 
    # x-移位
    gg = []
    for kk in range(mm + 1):
        for ii in range(mm - kk + 1):
            xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk
            gg.append(xshift)
    gg.sort()
 
    # 单项式 x 移位列表
    monomials = []
    for polynomial in gg:
        for monomial in polynomial.monomials(): #对于多项式中的单项式。单项式():
            if monomial not in monomials:  # 如果单项不在单项中
                monomials.append(monomial)
    monomials.sort()
 
    # y-移位
    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk)
            yshift = Q(yshift).lift()
            gg.append(yshift) # substitution
 
    # 单项式 y 移位列表
    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            monomials.append(u^kk * y^jj)
 
    # 构造格 B
    nn = len(monomials)
    BB = Matrix(ZZ, nn)
    for ii in range(nn):
        BB[ii, 0] = gg[ii](0, 0, 0)
        for jj in range(1, ii + 1):
            if monomials[jj] in gg[ii].monomials():
                BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)
 
    #约化格的原型
    if helpful_only:
        #  #自动删除
        BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1)
        # 重置维度
        nn = BB.dimensions()[0]
        if nn == 0:
            print ("failure")
            return 0,0
 
    # 检查向量是否有帮助
    if debug:
        helpful_vectors(BB, modulus^mm)
 
    # 检查行列式是否正确界定
    det = BB.det()
    bound = modulus^(mm*nn)
    if det >= bound:
        print ("We do not have det < bound. Solutions might not be found.")
        print ("Try with highers m and t.")
        if debug:
            diff = (log(det) - log(bound)) / log(2)
            print ("size det(L) - size e^(m*n) = ", floor(diff))
        if strict:
            return -1, -1
    else:
        print ("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")
 
    # display the lattice basis
    if debug:
        matrix_overview(BB, modulus^mm)
 
    # LLL
    if debug:
        print ("optimizing basis of the lattice via LLL, this can take a long time")
 
    #BB = BB.BKZ(block_size=25)
    BB = BB.LLL()
 
    if debug:
        print ("LLL is done!")
 
    # 替换向量 i 和 j ->多项式 1 和 2
    if debug:
        print ("在格中寻找线性无关向量")
    found_polynomials = False
 
    for pol1_idx in range(nn - 1):
        for pol2_idx in range(pol1_idx + 1, nn):
 
            # 对于i and j, 构造两个多项式
 
            PR.<w,z> = PolynomialRing(ZZ)
            pol1 = pol2 = 0
            for jj in range(nn):
                pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY)
                pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)
 
            # 结果
            PR.<q> = PolynomialRing(ZZ)
            rr = pol1.resultant(pol2)
 
 
            if rr.is_zero() or rr.monomials() == [1]:
                continue
            else:
                print ("found them, using vectors", pol1_idx, "and", pol2_idx)
                found_polynomials = True
                break
        if found_polynomials:
            break
 
    if not found_polynomials:
        print ("no independant vectors could be found. This should very rarely happen...")
        return 0, 0
 
    rr = rr(q, q)
 
    # solutions
    soly = rr.roots()
 
    if len(soly) == 0:
        print ("Your prediction (delta) is too small")
        return 0, 0
 
    soly = soly[0][0]
    ss = pol1(q, soly)
    solx = ss.roots()[0][0]
    return solx, soly
 
def example():
    ############################################
    # 随机生成数据
    ##########################################
    #start_time =time.perf_counter
    start =time.clock()
    size=512
    length_N = 2*size;
    ss=0
    s=70;
    M=1   # the number of experiments
    delta = 299/1024
    # p =  random_prime(2^512,2^511)
    for i in range(M):
#         p =  random_prime(2^size,None,2^(size-1))
#         q =  random_prime(2^size,None,2^(size-1))
#         if(p<q):
#             temp=p
#             p=q
#             q=temp
        N = 123789043095302886784777548580725867919630872720308267296330863659260260632444171595208750648710642616709290340791408935502415290984231140635423328808872594955139658822363033096014857287439409252367248420356169878044065798634016290690979979625051287064109800759113475629317869327100941592970373827299442569489
        e = 112070481298571389221611833986644006256566240788306316765530852688390558290807060037831460397016038678699757261874520899143918664293504728402666398893964929840011110057060969775245481057773655679041350091817099143204028098431544760662690479779286160425059494739419234859710815966582837874194763305328789592245
        c = 63662561509209168743977531923281040338804656992093161358503738280395090747786427812762995865224617853709000826994250614233562094619845247321880231488631212423212167167713869682181551433686816142488666533035193128298379649809096863305651271646535125466745409868274019550361728139482502448613835444108383177119
        hint1 = 897446442156802074692  # p高位
        hint2 = 1069442646630079275131  # q高位
#         print ("p真实高",s,"比特:", int(p/2^(512-s)))
#         print ("q真实高",s,"比特:", int(q/2^(512-s)))
 
#         N = p*q;
 
 
    # 解密指数d的指数( 最大0.292)
 
 
 
        m = 7   # 格大小(越大越好/越慢)
        t = round(((1-2*delta) * m))  # 来自 Herrmann 和 May 的优化
        X = floor(N^delta)  # 
        Y = floor(N^(1/2)/2^s)    # 如果 p、 q 大小相同,则正确
        for l in range(int(hint1),int(hint1)+1):
            print('\n\n\n l=',l)
            pM=l;
            p0=pM*2^(size-s)+2^(size-s)-1;
            q0=N/p0;
            qM=int(q0/2^(size-s))
            A = N + 1-pM*2^(size-s)-qM*2^(size-s);
        #A = N+1
            P.<x,y> = PolynomialRing(ZZ)
            pol = 1 + x * (A + y)  #构建的方程
 
            # Checking bounds
            #if debug:
                #print ("=== 核对数据 ===")
                #print ("* delta:", delta)
                #print ("* delta < 0.292", delta < 0.292)
                #print ("* size of e:", ceil(log(e)/log(2)))  # e的bit数
                # print ("* size of N:", len(bin(N)))          # N的bit数
                #print ("* size of N:", ceil(log(N)/log(2)))  # N的bit数
                #print ("* m:", m, ", t:", t)
 
            # boneh_durfee
            if debug:
                ##print ("=== running algorithm ===")
                start_time = time.time()
 
 
            solx, soly = boneh_durfee(pol, e, m, t, X, Y)
 
 
            if solx > 0:
                #print ("=== solution found ===")
                if False:
                    print ("x:", solx)
                    print ("y:", soly)
 
                d_sol = int(pol(solx, soly) / e)
                ss=ss+1

                print ("=== solution found ===")
                print ("p的高比特为:",l)
                print ("q的高比特为:",qM)
                print ("d=",d_sol) 
 
            if debug:
                print("=== %s seconds ===" % (time.time() - start_time))
            #break
        print("ss=",ss)
                            #end=time.process_time
        end=time.clock()
        print('Running time: %s Seconds'%(end-start))
if __name__ == "__main__":
    example()  

解出d

d = 815288165251971990144240125719456676622201418787728487985993940108011619486967079496288981

接着RSA解密

n = 123789043095302886784777548580725867919630872720308267296330863659260260632444171595208750648710642616709290340791408935502415290984231140635423328808872594955139658822363033096014857287439409252367248420356169878044065798634016290690979979625051287064109800759113475629317869327100941592970373827299442569489
e = 112070481298571389221611833986644006256566240788306316765530852688390558290807060037831460397016038678699757261874520899143918664293504728402666398893964929840011110057060969775245481057773655679041350091817099143204028098431544760662690479779286160425059494739419234859710815966582837874194763305328789592245
c = 63662561509209168743977531923281040338804656992093161358503738280395090747786427812762995865224617853709000826994250614233562094619845247321880231488631212423212167167713869682181551433686816142488666533035193128298379649809096863305651271646535125466745409868274019550361728139482502448613835444108383177119
d = 815288165251971990144240125719456676622201418787728487985993940108011619486967079496288981
m = pow(c,d,n)
flag = bytes.fromhex(hex(m)[2:])
print(flag)
Crypto2

题目:

# coding: utf-8
#!/usr/bin/env python2

import gmpy2
import random
import binascii
from hashlib import sha256
from sympy import nextprime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import long_to_bytes
from FLAG import flag
#flag = 'wdflag{123}'

def victory_encrypt(plaintext, key):
    key = key.upper()
    key_length = len(key)
    plaintext = plaintext.upper()
    ciphertext = ''

    for i, char in enumerate(plaintext):
        if char.isalpha():
            shift = ord(key[i % key_length]) - ord('A')
            encrypted_char = chr((ord(char) - ord('A') + shift) % 26 + ord('A'))
            ciphertext += encrypted_char
        else:
            ciphertext += char

    return ciphertext

victory_key = "WANGDINGCUP"
victory_encrypted_flag = victory_encrypt(flag, victory_key)

p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
a = 0
b = 7
xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
G = (xG, yG)
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
h = 1
zero = (0,0)

dA = nextprime(random.randint(0, n))

if dA > n:
    print("warning!!")

def addition(t1, t2):
    if t1 == zero:
        return t2
    if t2 == zero:
        return t2
    (m1, n1) = t1
    (m2, n2) = t2
    if m1 == m2:
        if n1 == 0 or n1 != n2:
            return zero
        else:
            k = (3 * m1 * m1 + a) % p * gmpy2.invert(2 * n1 , p) % p
    else:
        k = (n2 - n1 + p) % p * gmpy2.invert((m2 - m1 + p) % p, p) % p
    m3 = (k * k % p - m1 - m2 + p * 2) % p
    n3 = (k * (m1 - m3) % p - n1 + p) % p
    return (int(m3),int(n3))

def multiplication(x, k):
    ans = zero
    t = 1
    while(t <= k):
        if (k &t )>0:
            ans = addition(ans, x)
        x = addition(x, x)
        t <<= 1
    return ans

def getrs(z, k):
    (xp, yp) = P
    r = xp
    s = (z + r * dA % n) % n * gmpy2.invert(k, n) % n
    return r,s

z1 = random.randint(0, p)
z2 = random.randint(0, p)
k = random.randint(0, n)
P = multiplication(G, k)
hA = multiplication(G, dA)
r1, s1 = getrs(z1, k)
r2, s2 = getrs(z2, k)

print("r1 = {}".format(r1))
print("r2 = {}".format(r2))
print("s1 = {}".format(s1))
print("s2 = {}".format(s2))
print("z1 = {}".format(z1))
print("z2 = {}".format(z2))

key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC)
iv = cipher.iv
encrypted_flag = cipher.encrypt(pad(victory_encrypted_flag.encode(), AES.block_size))
encrypted_flag_hex = binascii.hexlify(iv + encrypted_flag).decode('utf-8')

print("Encrypted flag (AES in CBC mode, hex):", encrypted_flag_hex)

# output
# r1 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
# r2 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
# s1 = 73636354334739290806716081380360143742414582638332132893041295586890856253300
# s2 = 64320109990895398581134015047131652648423777800538748939578192006599226954034
# z1 = 35311306706233977395060423051262119784421232920823462737043282589337379493964
# z2 = 101807556569342254666094290602497540565936025601030395061064067677254735341454
# ('Encrypted flag (AES in CBC mode, hex):', u'3cdbe372c9bc279e816336ad69b8247f4ec05647a7e97285dd64136875004b638b77191fe9bef702cb873ee93dbe376c050d0c721b69f17f539cff83372cc37b')

ECDSA 共k攻击求dA
已知
s 1 = ( z 1 + r ∗ d A )   m o d   n ∗ k − 1   m o d   n s_1 = (z_1+r*dA) \space mod \space n *k^{-1} \space mod \space n s1=(z1+rdA) mod nk1 mod n
s 2 = ( z 2 + r ∗ d A )   m o d   n ∗ k − 1   m o d   n s_2 = (z_2+r*dA) \space mod \space n *k^{-1} \space mod \space n s2=(z2+rdA) mod nk1 mod n
两边同时乘上k
s 1 k = ( z 1 + r ∗ d A )   m o d   n s_1k = (z_1+r*dA) \space mod \space n s1k=(z1+rdA) mod n
s 2 k = ( z 2 + r ∗ d A )   m o d   n s_2k = (z_2+r*dA) \space mod \space n s2k=(z2+rdA) mod n
两式相减,得到k
k = ( s 2 − s 1 ) − 1 ( z 2 − z 1 )   m o d   n k = (s_2-s_1)^{-1}(z_2-z_1) \space mod \space n k=(s2s1)1(z2z1) mod n
带入式子1,即可计算出dA
d A = ( s 1 k − z 1 ) × k − 1   m o d   n dA = (s_1k-z_1)\times k^{-1} \space mod \space n dA=(s1kz1)×k1 mod n
之后直接计算出key和iv解AES密文即可
然后根据加密代码逻辑还原明文

import gmpy2
from hashlib import sha256
from Crypto.Util.number import *
from Crypto.Cipher import AES
import binascii

def victory_decrypt(ciphertext, key):
    key = key.upper()
    key_length = len(key)
    plaintext = ''

    for i, char in enumerate(ciphertext):
        if char.isalpha():
            shift = ord(key[i % key_length]) - ord('A')
            decrypted_char = chr((ord(char) - ord('A') - shift + 26) % 26 + ord('A'))
            plaintext += decrypted_char
        else:
            plaintext += char

    return plaintext


r1 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
r2 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
s1 = 73636354334739290806716081380360143742414582638332132893041295586890856253300
s2 = 64320109990895398581134015047131652648423777800538748939578192006599226954034
z1 = 35311306706233977395060423051262119784421232920823462737043282589337379493964
z2 = 101807556569342254666094290602497540565936025601030395061064067677254735341454
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
c = '3cdbe372c9bc279e816336ad69b8247f4ec05647a7e97285dd64136875004b638b77191fe9bef702cb873ee93dbe376c050d0c721b69f17f539cff83372cc37b'
k = (z2-z1)*gmpy2.invert(s2-s1,n) %n
dA = (s1*k-z1)*gmpy2.invert(r1,n)%n
key = sha256(long_to_bytes(dA)).digest()
iv = binascii.unhexlify(c[:32])
enc = binascii.unhexlify(c[32:])
cipher = AES.new(key, AES.MODE_CBC,iv)
flag = cipher.decrypt(enc)
print(flag)
#SDSRDO{34697E430N6H6URW68849Q8HWT81039J}
ciphertext = "SDSRDO{34697E430N6H6URW68849Q8HWT81039J}"
victory_key = "WANGDINGCUP"
decrypted_flag = victory_decrypt(ciphertext, victory_key)

print("Decrypted flag:", decrypted_flag)
#WDFLAG{34697E430F6B6ACA68849D8FCE81039B}

白虎组

Crypto1

先ddl了,有时间再补上

Crypto2

题目:

from Crypto.Util.number import getPrime, isPrime, GCD, inverse

nbits = 2048
gbits = 1000
g = getPrime(int(gbits))
while True:
    a = getPrime(int(nbits*0.5)-gbits)
    p = 2*g*a + 1
    if isPrime(p):
        break

while True:
    b = getPrime(int(nbits*0.5)-gbits)
    q = 2*g*b + 1
    if p!=q and isPrime(q):
        break
N = p*q
e = 65537

def str2int(s):
    return int(s.encode('latin-1').hex(),16)

def int2str(i):
    tmp=hex(i)[2:]
    if len(tmp)%2==1:
        tmp='0'+tmp
    return bytes.fromhex(tmp).decode('latin-1')

with open('pubkey.txt','w') as f:
    f.write(str(e)+'\n')
    f.write(str(N)+'\n')

with open('flag.txt') as f:
    plain = str2int(f.read())

c = pow(plain,e,N)
with open('cipher.txt','wb') as f:
    f.write(int2str(c).encode('latin-1'))

分析代码,我们可以发现p和q的生成都存在一个共同的因子g,约为1000bit
∵ p = 2 g a + 1 , q = 2 g b + 1 \because p = 2ga+1,q = 2gb+1 p=2ga+1,q=2gb+1
⇒ g = g c d ( p − 1 , q − 1 ) \Rightarrow g = gcd(p-1,q-1) g=gcd(p1,q1)
所以我们可以使用Pollard’s rho来分解n,从而求得p和q
最后再把密文处理成整数型,然后计算出phi,d解密即可获得flag
exp:

import gmpy2
from Crypto.Util.number import *


def f(x, n):
    return (pow(x, n - 1, n) + 3) % n


def rho(n):
    i = 1
    while True:
        a = getRandomRange(2, n)
        b = f(a, n)
        j = 1
        while True:
            p = GCD(abs(a - b), n)
            print('{} in {} circle'.format(j, i))
            if p == n:
                break
            elif p > 1:
                return (p, n // p)
            else:
                a = f(a, n)
                b = f(f(b, n), n)
            j += 1
        i += 1



#将密文转换整型
with open('cipher.txt', 'rb') as f:
    c_bytes = f.read()  # 读取字节内容
    c_hex = c_bytes.hex()  # 将字节转换为十六进制字符串
    c = int(c_hex, 16)  # 将十六进制字符串转换为整数

e = 65537
n = 49025724928152491719950645039355675823887062840095001672970308684156817293484070166684235178364916522473822184239221170514602692903302575847326054102901449806271709230774063675539139201327878971370342483682454617270705142999317092151456200639975738970405158598235961567646064089356496022247689989925574384915789399433283855087561428970245448888799812611301566886173165074558800757040196846800189738355799057422298556992606146766063202605288257843684190291545600282197788724944382475099313284546776350595539129553760118549158103804149179701853798084612143809757187033897573787135477889183344944579834942896249251191453
#Pollard’s rho分解n,
#p,q = rho(n)
p = 181081097501198023069853833182353184261284123229534078254107942099502325869566163846505417960576038861954213847321685798395883194037860319430010178354074600519049325312842897561278830450748961589667396822373094094674865532726953310816962745801088563041800719074771895743022649725941252134035150899684475275107
q = 270739053411293468044358005572326880715866131246316305975150551797771999927260913691624449594733673350641598358977228099278925982221096409496197961213452575581038864123668037331549492912118266914139408344450017736857756347795681452284667629499583154669046006953194443040693208729068117415444168170452989294079

phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
flag = long_to_bytes(m)
print(flag)

朱雀组

Crypto2

题目给了密文c,n以及p,其中p的高256bit已知
显然这是一个p高位泄露的题型,但是卡界了。
这一类题,我在2023 LitCTF 的baby_xor一题中出过一样的考点,详情移步下方链接,这里就不细讲了。
2023 LitCTF — Crypto wp

from tqdm import *
n = 0x00b8cb1cca99b6ac41876c18845732a5cbfc875df346ee9002ce608508b5fcf6b60a5ac7722a2d64ef74e1443a338e70a73e63a303f3ac9adf198595699f6e9f30c009d219c7d98c4ec84203610834029c79567efc08f66b4bc3f564bfb571546a06b7e48fb35bb9ccea9a2cd44349f829242078dfa64d525927bfd55d099c024f

ph = 0xe700568ff506bd5892af92592125e06cbe9bd45dfeafe931a333c13463023d4f0000000000000000000000000000000000000000000000000000000000000000
pbits = 512
p_high = ph>>256
for i in trange(2**8):
    p4 = p_high<<8
    p4 = p4 + i
    kbits = pbits - p4.nbits()
    p4 = p4 << kbits
    PR.<x> = PolynomialRing(Zmod(n))
    f = x + p4
    roots = f.small_roots(X=2^kbits, beta=0.4, epsilon=0.01)
    if roots:        
        p = p4+int(roots[0]) 
        if n%p==0:
            print(i,p)
            break

爆破得到

i = 194 
p = 12098520864598198757294135341465388062087431109285224283440314414683283061468500249596026217234382854875647811812632201834942205849073893715844547051090363
from Crypto.Util.number import *
import gmpy2
import libnum

f = open("flag.enc","rb").read()
c = bytes_to_long(f)
p = 12098520864598198757294135341465388062087431109285224283440314414683283061468500249596026217234382854875647811812632201834942205849073893715844547051090363
n = 0x00b8cb1cca99b6ac41876c18845732a5cbfc875df346ee9002ce608508b5fcf6b60a5ac7722a2d64ef74e1443a338e70a73e63a303f3ac9adf198595699f6e9f30c009d219c7d98c4ec84203610834029c79567efc08f66b4bc3f564bfb571546a06b7e48fb35bb9ccea9a2cd44349f829242078dfa64d525927bfd55d099c024f
e = 65537
q = n//p
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
flag = long_to_bytes(m)
print(flag)

之后计算出q = n//p,把密文变成数字型,再RSA解密即可得到flag

Crypto3
part1

n 1 ≈ p 1 × 2024 p 1 ≈ 2024 p 1 2 n_1 \approx p_1 \times 2024p_1 \approx 2024p_1^{2} n1p1×2024p12024p12
整除2024,然后对n1开方即可得到p1,进而得到q1

n1 = 
p1 = gmpy2.iroot(n1//2024,2)[0]
q1 = n1//p1

得到p1和q1

p1 = 146187607535300384587509957494226602879910697731111793338231366571998962914635615996598727004205169961576448628561413122161261394771744901435074146079222198287010135623393031759366562782057113205707175142954551779767710913840908209285742147746099427389400973759220801645310208401376788865791190217328962123279
q1 = 295883717651447978405120153968314644228939252207770269716580285941725900939222486777115823456511264002230732024208300159254393063018011680504590071664345729332908514501747496280957923070883597128351322489340012802249846889613998215594342107038105241036147570888662902530107861804386620664361368999873819337516721
part2

已知
n 2 = p 2 ∗ q 2 , n 22 = p 2 2 + q 2 2 n_2 = p_2*q_2,n_{22} = p_2^{2}+q_2^{2} n2=p2q2,n22=p22+q22
那么我们直接构建方程组解方程即可

n2 = 
n22 = 
p2,q2 = Ints('p2 q2')
s = Solver()
s.add(p2*q2==n2)
s.add(p2**2+q2**2==n22)
if s.check()==sat:
    print(s.model())
   

得到p2和q2

p2 = 133064204383114442564887327191574256650055020929830824588577417753167292659660059589564610129957808064002805580421156153609277092389753135192904997169182787255213644860856072991606212800442053226675120936710208060680648681274616282517421189570805017586256581334157425386374483509501090965717646720700424863423
q2 = 161350628589676557525881716966340935717969334783533837289612088856244362686139907887162014592790132128414148723412888028361068777482425667132948875411222080236173967775667519908708279765880512473014384298105752518090429868307024159426520644435015258039304108930727310884096853455754839248318020906028016894579
part3

根据p3和q3得生成代码,可知
p 3 + q 3 = 2 ( n 3 + 1 ) p_3+q_3 = 2(\sqrt{n_3}+1) p3+q3=2(n3 +1)
再联合
n 3 = p 3 q 3 n_3 = p_3q_3 n3=p3q3
可以构造方程组计算出p3和q3

n3 = 
tmp = gmpy2.iroot(n3,2)[0]
p3,q3 = Ints('p3 q3')
s = Solver()
s.add(p3*q3==n3)
s.add(p3+q3==2*tmp+2)
if s.check()==sat:
    print(s.model())

得到p3和q3

p3 = 122919460677181447255662000442101333281019894158297462412806821518657755917099521145678690717375396316626833583612356812214587401412448220563982839146665862717678495178437386577882720343715419646347453965273307650714361987001939787363067549306301977112348400269518912107383153989960205330328806948574142432881
q3 = 122919460677181447255662000442101333281019894158297462412806821518657755917099521145678690717375396316626833583612356812214587401412448220563982839146665862719627439871738815429215471546402837328038925028763750154507765739783853121032116043651820874648359779165148305098515735172075366847764584719616506196289
part4

已知
m 1 = p 1 m 2 + p 2 m + p 3 m_1 = p_1m^2+p_2m+p_3 m1=p1m2+p2m+p3
m 2 = q 1 m 2 + q 2 m + q 3 m_2 = q_1m^2+q_2m+q_3 m2=q1m2+q2m+q3
c 1 = m 1 e   m o d   n c_1 = m_1^e \space mod \space n c1=m1e mod n
c 2 = m 2 e   m o d   n c_2 = m_2^e \space mod \space n c2=m2e mod n
一眼顶针 Franklin-Reiter攻击,但是e = 2999,有点大,不太好多项式GCD,所以我们使用half gcd来加速多项式得gcd

#sage
from Crypto.Util.number import *
import sys

def HGCD(a, b):
    if 2 * b.degree() <= a.degree() or a.degree() == 1:
        return 1, 0, 0, 1
    m = a.degree() // 2
    a_top, a_bot = a.quo_rem(x^m)
    b_top, b_bot = b.quo_rem(x^m)
    R00, R01, R10, R11 = HGCD(a_top, b_top)
    c = R00 * a + R01 * b
    d = R10 * a + R11 * b
    q, e = c.quo_rem(d)
    d_top, d_bot = d.quo_rem(x^(m // 2))
    e_top, e_bot = e.quo_rem(x^(m // 2))
    S00, S01, S10, S11 = HGCD(d_top, e_top)
    RET00 = S01 * R00 + (S00 - q * S01) * R10
    RET01 = S01 * R01 + (S00 - q * S01) * R11
    RET10 = S11 * R00 + (S10 - q * S11) * R10
    RET11 = S11 * R01 + (S10 - q * S11) * R11
    return RET00, RET01, RET10, RET11
    
def GCD(a, b):
    q, r = a.quo_rem(b)
    if r == 0:
        return b
    R00, R01, R10, R11 = HGCD(a, b)
    c = R00 * a + R01 * b
    d = R10 * a + R11 * b
    if d == 0:
        return c.monic()
    q, r = c.quo_rem(d)
    if r == 0:
        return d
    return GCD(d, r)

sys.setrecursionlimit(500000)

p1 = 146187607535300384587509957494226602879910697731111793338231366571998962914635615996598727004205169961576448628561413122161261394771744901435074146079222198287010135623393031759366562782057113205707175142954551779767710913840908209285742147746099427389400973759220801645310208401376788865791190217328962123279
q1 = 295883717651447978405120153968314644228939252207770269716580285941725900939222486777115823456511264002230732024208300159254393063018011680504590071664345729332908514501747496280957923070883597128351322489340012802249846889613998215594342107038105241036147570888662902530107861804386620664361368999873819337516721

p2 = 133064204383114442564887327191574256650055020929830824588577417753167292659660059589564610129957808064002805580421156153609277092389753135192904997169182787255213644860856072991606212800442053226675120936710208060680648681274616282517421189570805017586256581334157425386374483509501090965717646720700424863423
q2 = 161350628589676557525881716966340935717969334783533837289612088856244362686139907887162014592790132128414148723412888028361068777482425667132948875411222080236173967775667519908708279765880512473014384298105752518090429868307024159426520644435015258039304108930727310884096853455754839248318020906028016894579

p3 = 122919460677181447255662000442101333281019894158297462412806821518657755917099521145678690717375396316626833583612356812214587401412448220563982839146665862717678495178437386577882720343715419646347453965273307650714361987001939787363067549306301977112348400269518912107383153989960205330328806948574142432881
q3 = 122919460677181447255662000442101333281019894158297462412806821518657755917099521145678690717375396316626833583612356812214587401412448220563982839146665862719627439871738815429215471546402837328038925028763750154507765739783853121032116043651820874648359779165148305098515735172075366847764584719616506196289
e = 2999
n = 16384707752002961811357426356040804358820450429112719059482965460688633224199445850016434753713403979835193345762008018698844949530549502743281731789334994428312464772130516824285978243651287411553116255652677650004040824347186268439788928865418368468897627214552572846541839629323949068937120798767586917684764944219031287061253819651989184659516095370231858355076296906499453937821927440892978892852470311395853382511321806654834173438462402181182706548632711364029421502619027705821496435350762046222825598323497861393301677598992958820184003364763320507041485736186970914568690758845870075203051617037883827279119
c1 = 11382473352009511791762101735529507838446758824791351775250810654314066423650685628073502579664186057184344713574429940611514864513995383801386486394825452589218688059897458368223518637647179221771655104137667329953446341815527699304599435283634443556038985090968474934734321344125280569467142049038929368549733232047316780077686016318662303350081357699377969335914292631398295061602601940464649624118295616080162917211435856653333110858004250959483891522407923876955812205685375843940874486371994485161526059198019014530740524036481557433830304867422828002361446861419824025752025995296741718962141953713234949894732
c2 = 13291355062242181017235433629558689027068114611650872691659197232933062720760260933280099178334615566562244698391494264051061145257215694115131167336658805533954362024110598093368016089512260336234014588390607552801658614571912470713860293915607463462319165043506295500174873235810829299741016973929360670488678562024980338443636210602228872744449850339238513161642644630785241443001404597604581629303749287855365022218361488602768556292856610619067231689100946362621816109192111615866980116556776737918323907474176583284350758109722993772794866722135312051956704194889790127430725508449097365193657563726357277350509

R.<x> = PolynomialRing(Zmod(n))
f = (p1 * x * x + p2 * x + p3)^e - c1
g = (q1 * x * x + q2 * x + q3)^e - c2
res = GCD(f,g)
m = -res.monic().coefficients()[0]
flag = long_to_bytes(int(m))
print(flag)

【许多的故事,大大小小的,末尾就两个字,“还好”。而”还好“的注解,大概就是”希望“。】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2231133.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java并发编程-volatile的作用

文章目录 volatile的作用1.改变线程间的变量可见性2.禁止指令重排序 参考的学习视频 volatile的作用 1.改变线程间的变量可见性 每个线程都有一个专用的工作集内存&#xff0c;下图里面粉色的表示专用工作集内存&#xff0c;黄色的是共享内存工作区&#xff0c;如果加入了vol…

目前最新最好用 NET 混淆工具 .NET Reactor V6.9.8

目前最新最好用 NET 混淆工具 .NET Reactor V6.9.8 1、.NET Reactor V6.9.8 功能简介2、官方下载 1、.NET Reactor V6.9.8 功能简介 业界领先的源代码保护 .NET Reactor通过多种方法来防止反编译&#xff0c;这些方法会将 .NET 程序集转换为任何现有工具都无法反编译的进程。…

计算机性能分析的三个模型

计算机性能分析的三个模型【1】 一、瓶颈分析&#xff08;Bottleneck Analysis&#xff09;二、利特尔法则&#xff08;Littles Law&#xff09;【2】三、M/M/1 QueueReference 一、瓶颈分析&#xff08;Bottleneck Analysis&#xff09; 瓶颈分析可以帮我们更好地定位导致性能…

2025四川省考报名流程详细教程

2025年四川省考报名马上就要开始了&#xff0c;有想要参加四川省考的姐妹们&#xff0c;可以提前了解一下考试报名流程&#xff0c;提前准备好报名照片。 报名时间&#xff1a;2024年11月1日至7日上午8:00 审核时间&#xff1a;2024年11月1日至8日上午8:00 缴费时间&#xff1a…

Ts基础总结

文章目录 TS是什么&#xff1f;Ts编译Ts编译选项:如何在项目中使用Ts?为什么要使用 TS ? TypeScript 相对于 JavaScript 的优势是什么&#xff1f;ts 中有哪些类型&#xff1f;any 和 unknown的区别是&#xff1f;void 和 never 的区别是&#xff1f;TypeScript中的访问修饰符…

ImportError: Install xlrd >= 1.0.0 for Excel support

文章目录 一、报错问题二、问题解释三、解决方法 一、报错问题 问题描述&#xff1a; python2.7使用pandas读取excel文件时报错ImportError: Install xlrd > 1.0.0 for Excel support。 问题代码&#xff1a; # codingutf-8import pandas as pddata pd.read_excel(D:\Wo…

算法学习(七)—— 分治

关于分治 分治&#xff0c;就是“分而治之”的意思&#xff0c;就是把一个大问题&#xff0c;转化为若干个相同或者相似的几个子问题&#xff0c;然后在子问题的基础上再进行划分&#xff0c;直到能够快速一个子问题时停止划分 我们的快速排序和归并排序就是典型的分治思想 …

2-141 怎么实现ROI-CS压缩感知核磁成像

怎么实现ROI-CS压缩感知核磁成像&#xff0c;这个案例告诉你。基于matlab的ROI-CS压缩感知核磁成像。ROI指在图像中预先定义的特定区域或区域集合&#xff0c;选择感兴趣的区域&#xff0c;通过减少信号重建所需的数据来缩短信号采样时间&#xff0c;减少计算量&#xff0c;并在…

C++ 实现俄罗斯方块游戏

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

VS+Qt解决提升控件后,包含头文件格式不对问题处理

一、前言 VSQt 提升控件后&#xff0c;在uic目录下会生成ui相关的初始化文件&#xff0c;对于提升的控件头文件包含的格式为#include<> 而非 #include “ ” 导致无法找到头文件。如果手动修改为 #include “ ”相当麻烦&#xff0c;甚至每次编译都要修改一遍&#xff0c…

02- 模块化编程-002 DS1302数码显示时间与日期

1、数码显示时间日期的电路 2、电路原理简介 电路组件与功能 单片机&#xff08; PIC16F887&#xff09;&#xff1a; 作为系统的主控芯片&#xff0c;处理所有输入输出&#xff0c;进行时间控制和显示信息更新。 DS1302&#xff08;实时时钟芯片&#xff09;&#xff1a; 用于…

java计算机毕设课设—Java聊天室(附源码、文章、相关截图、部署视频)

这是什么系统&#xff1f; 资源获取方式再最下方 java计算机毕设课设—Java聊天室(附源码、文章、相关截图、部署视频) Java聊天室系统是一个基于Java语言开发的在线即时通讯平台&#xff0c;旨在为用户提供一个简单、易用的实时交流环境。该系统支持多用户同时在线交流&…

编译原理第一次实验报告

源代码及附件&#xff1a;编译原理实验一源程序及附件资源-CSDN文库实验题目 实验要求 实验设计 前两部分指出了实验的宏观把控&#xff0c;为了具体实施实验&#xff0c;我们需要预先为实验做出如下设计&#xff1a; 本次实验我选取了C语言的一个子集进行设计词法分析器&…

Llama 3.2 Vision Molmo:多模态开源生态系统基础

编者按&#xff1a; 视觉功能的融入对模型能力和推理方式的影响如何&#xff1f;当我们需要一个既能看懂图像、又能生成文本的 AI 助手时&#xff0c;是否只能依赖于 GPT-4V 这样的闭源解决方案&#xff1f; 我们今天为大家分享的这篇文章&#xff0c;作者的核心观点是&#xf…

C++_day01

目录 0. 课前须知 1. C发展历史&#xff08;了解&#xff09; 2. C特点&#xff08;熟悉&#xff09; 3. 面向对象核心术语&#xff08;熟悉&#xff09; 4. 开发环境 5. 新建项目 4. 开发环境 5. 新建项目 0. 课前须知 C的思维与C语言完全不同&#xff0c;不能生搬硬套。 C偏向…

安娜的档案(Anna’s Archive) 镜像网站/国内最新可访问入口(持续更新)

安娜的档案&#xff08;Anna’s Archive&#xff09;是一个颇受关注的资源库。它涵盖了广泛的内容&#xff0c;可能包括各类文献、资料等。其特色在于丰富的信息储备和一定的系统性。安娜的档案&#xff08;Anna’s Archive&#xff09;用户可以从中获取多样的知识和数据&#…

Linux 下执行定时任务之 Systemd Timers

不知道 ECS 因为什么缘故&#xff0c;上面安装的 MySQL 服务老是不定期挂掉&#xff0c;本来想通过 Linux 得 Cron 配置个半小时的定时检测任务&#xff0c;结果一直没有执行&#xff0c;因此又尝试使用了 Systemd Timers 进行了重新配置&#xff0c;简要做个记录。 Systemd Ti…

【星闪EBM-H63开发板】AT固件的接口简介

引言 前面介绍了星闪EBM-H63开发板的透传固件&#xff0c;现在介绍一下AT固件。AT固件比透传固件要复杂的多&#xff0c;都让功能也多很多&#xff0c;可以配置很多星闪相关的参数。AT固件没有AT命令模式和数据模式切换的问题&#xff0c;因为收发的数据是出现在AT命令中的。 …

51单片机教程(四)- 点亮LED灯

1、项目分析 让输入/输出口的P1.0连接一盏LED灯进行点亮。 2、技术准备 1 LED组成 ​ 说明 二极管有 P型 和 N型材料构成&#xff0c;通常是&#xff1a;硅/锗 掺杂其他元素&#xff08;硼、磷等&#xff09; 电子是带负电的&#xff0c;是负电荷的载体&#xff0c;电子流…

开源库 FloatingActionButton

开源库FloatingActionButton Github:https://github.com/Clans/FloatingActionButton 这个库是在前面这个库android-floating-action-button的基础上修改的&#xff0c;增加了一些更强大和实用的特性。 特性&#xff1a; Android 5.0 以上点击会有水波纹效果 可以选择自定义…