ctfShow愚人杯

  1. 大牛的密码
  2. comedy
  3. easy_xor
  4. ecc_mini

大牛的密码

from Crypto.Util.number import *
from flag import flag
from Crypto.Util.Padding import pad
from random import *
def s_box(a):
    box=[i for i in range(a)]
    shuffle(box)
    return box
BLOCK=16
flag=pad(flag,BLOCK)
S_BOX=s_box(len(flag))
m=[i for i in flag]
def swap(a,b):
    tmp = a
    a = b
    b = tmp
def encrypt1(m):
    enc=[m[i:i+BLOCK] for i in range(0,len(m),BLOCK)]
    for i in enc:
        for j in range(BLOCK):
            aa=j*7%BLOCK
            swap(i[j],i[aa])
def encrypt2(m):
    for i in range(16):
        m=[m[i] for i in S_BOX]
    return m
encrypt1(m)
c=encrypt2(m)
print(S_BOX)
print(c)
'''
[9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]
[99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]
'''

swap函数实际上没发挥作用,可以试一下:

def swap(a,b):
    tmp = a
    a = b
    b = tmp
def text(x,y):
    print(x,y)
    swap(x,y)
    print(x,y)

x = 3
y = 4
text(x,y)
print(x,y)
#均输出3 4

所以直接对encrypt2逆就行:

S_box = [9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]
c = [99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]

enc = [0]*len(c)
for x in range(16):
    for i in range(len(S_box)):
        enc[S_box[i]] = c[i]
    c = enc
    enc = [0]*len(c)

for i in c:
    print(chr(i),end="")
#ctfshow{y0u_c5n_make_y0u1_own_CryptO}

comedy

import gmpy2, libnum
from secret import flag1, flag2

m = libnum.s2n(flag1)
assert m.bit_length() < 200
B = gmpy2.next_prime(libnum.s2n(flag2))
A = (2022 - 2023 * m) % B
leak = pow(2, 2023, B)
print(A)
print(leak)
# 493275281479560936332761096886786925792234184811353209227551802099268192839677496844153534128991899414803550843408607188612593757622064753867565869035222715177143938385039508273050267347710495512806264863554858016145161165422812554800693811328453743229819656381224407015421235005940088439590887928051969351426291843586132741521121351667152673680122929827805479163871436776753859965413192837591532468372
# 238829196127128263156194898141748280130190920343265228257398802867203846004703877952990524473329125233083096275276064071930416561616135910190674099345267027039386328203653489152769309498199556401574021633071022874689081585677578010276529507102304828451681000682208089162940529052283763507244593173690786957816545746540436261888398732172965945762569416702401859253725696471593023885944262561159982327952

两种方法,方法一:

通过A = (2022 - 2023 * m) % B可以知道B的位数是大于A的位数的(A的位数为1334),所以仅有200位的m对B来说几乎可以忽略,且$2022-2023*m$为负数,因此变形为:

$A = 2022-2023m+B \Rightarrow B-A = 2023m-2022$,A、B是相近的。

再由$leak = pow(2, 2023, B),kB = 2^{2023}-leak \Rightarrow k = \frac {2^{2023}-leak}{B} = \frac {2^{2023}-leak}{A}$,

注意正负号的问题。

通过这个等式求B就能解出m了:

A = 493275281479560936332761096886786925792234184811353209227551802099268192839677496844153534128991899414803550843408607188612593757622064753867565869035222715177143938385039508273050267347710495512806264863554858016145161165422812554800693811328453743229819656381224407015421235005940088439590887928051969351426291843586132741521121351667152673680122929827805479163871436776753859965413192837591532468372
leak = 238829196127128263156194898141748280130190920343265228257398802867203846004703877952990524473329125233083096275276064071930416561616135910190674099345267027039386328203653489152769309498199556401574021633071022874689081585677578010276529507102304828451681000682208089162940529052283763507244593173690786957816545746540436261888398732172965945762569416702401859253725696471593023885944262561159982327952

B = (pow(2,2023)-leak) // ((pow(2,2023)-leak) // A)
m = (B - A + 2022) // 2023
print(m)
print(long_to_bytes(m)+long_to_bytes(B))

方法二:

$leak = pow(2, 2023, B) \Rightarrow k*b=2^{2023}-leak$

$A = (2022 - 2023m) mod B \Rightarrow kB = A+2023m-2022$

以$kB为域,求解方程A+2023m-2022$:

A = 493275281479560936332761096886786925792234184811353209227551802099268192839677496844153534128991899414803550843408607188612593757622064753867565869035222715177143938385039508273050267347710495512806264863554858016145161165422812554800693811328453743229819656381224407015421235005940088439590887928051969351426291843586132741521121351667152673680122929827805479163871436776753859965413192837591532468372
leak = 238829196127128263156194898141748280130190920343265228257398802867203846004703877952990524473329125233083096275276064071930416561616135910190674099345267027039386328203653489152769309498199556401574021633071022874689081585677578010276529507102304828451681000682208089162940529052283763507244593173690786957816545746540436261888398732172965945762569416702401859253725696471593023885944262561159982327952

kb = 2**2023 - leak

P.<x> = PolynomialRing(Zmod(kb))
f = A + 2023 * x - 2022
roots = f.monic().small_roots(X=2 ^ 200, beta=0.4)
m = roots[0]
B = f(m)

print(long_to_bytes(m) + long_to_bytes(B))
#ctfshow{UNKNOWN_MODULUS_T0_BR1NG_L3UGHTER_AND_J@Y_TO_TH3_W0RLD}

easy_xor

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

assert len(flag[8:-1])==23
m = bytes_to_long(flag)
p = getPrime(1024)
q = getPrime(1024)
n = p*q
e = 65537
c1 = m^p
c2 = pow(m,e,n)
print(f'c1 = {c1}')
print(f'c2 = {c2}')
print(f'n = {n}')
'''
c1 = 151198307301713399973545627808177783191262282577048906899567665485020342464366268384613589477129150406859219553325982275344405383612415523342568367197935454935162234419239807109194526080836070453102172720442102673200212658553214847476648456720629906051324248179394810385918370092764118401652990951968387233220
c2 = 7894512574379281106340582833782408137686355961537832816105517328532111343730615739255485918919146012721446905489729048235088965936700563973759759039693443386542070451737445467143517377017890468837697907596398070608179281207203217576205857817411996178441661371846647602166663752324880657668362355493701482869858528298247422875427747085642627978367348931707497113936723122393282697211257939351221141536029828744507560524637999804394951722319070365576391442828074457050403771353328835153787572457070779602728359333021922987279454923820866436212282592764768470608545881718922440010751845730974331917142224339664090863915
n = 20873587976264698212013861921447267548758723109929620330136081844796427967720295581580927324390713931549639540337285515365487607593546367886570408812338077846317206794057714877394609181224434104303259411081376607299962306250984285173463537669954845497211859940191392861121877814873939865829555350848523691546006073264112091406848179785659505299775196062799482197712761744192962658799557108701192680225134300686608396391566674966897700511638643429161735764600752699251493599533703928135311599575989253347234975026924804433742500175666009324057320386262109587593814197687132304704244158862263859846356497849518103755981
'''

$c_1 = m \bigoplus p $,随便编个m看看位数:

c = b"ctfshow{abcdefghijklmnopqrstuvw}"
print(bytes_to_long(c).bit_length())
#255

位数可以说是大差不差了,所以$c_1的高位与p的相同$,使用copper解:

n = 20873587976264698212013861921447267548758723109929620330136081844796427967720295581580927324390713931549639540337285515365487607593546367886570408812338077846317206794057714877394609181224434104303259411081376607299962306250984285173463537669954845497211859940191392861121877814873939865829555350848523691546006073264112091406848179785659505299775196062799482197712761744192962658799557108701192680225134300686608396391566674966897700511638643429161735764600752699251493599533703928135311599575989253347234975026924804433742500175666009324057320386262109587593814197687132304704244158862263859846356497849518103755981
c1 = 151198307301713399973545627808177783191262282577048906899567665485020342464366268384613589477129150406859219553325982275344405383612415523342568367197935454935162234419239807109194526080836070453102172720442102673200212658553214847476648456720629906051324248179394810385918370092764118401652990951968387233220

p4 = c1 >> 300 << 300
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X=2^300, beta=0.4)
if roots:        
    p = p4+int(roots[0]) 
    print("n: "+str(n))
    print("p: "+str(p))
    print("q: "+str(n//p))
p: 151198307301713399973545627808177783191262282577048906899567665485020342464366268384613589477129150406859219553325982275344405383612415523342568367197935454935162234419239807109194526080836070453102172720442102673200212658553214847460852578711847453220002917585398257703718559772706814411685969778039384808889
q: 138054376062635694915086418886453465665768025801737649544228871881593344677210971372037454304349232263758231557875602849595669813224972600445750315510602198944307489874579256775934881073232401059932558896153129338214973126954953220540176740524331286201822240648611598820456813823721825014692448715872634683829

后面就是基础部分了,就不贴了,解出flag为:

b'ctfshow{m_xor_p_but_coppersmith}'

ecc_mini

#sage
from Crypto.Util.number import *
from secret import flag
flag=bytes_to_long(flag)
a =getPrime(256)
b =getPrime(256)
p =getPrime(256)
m1=int(str(flag)[:5])-4585
m2=int(str(flag)[5:])
#EllipticCurve([a1, a2, a3, a4, a6]) -- y^2+(a1)xy+(a3)y=x^3+(a2)x^2+(a4)x+(a6)
E = EllipticCurve(GF(p), [a, b])
X=E.lift_x(m1)
Y=7*X
m = E.random_point()
G = E.random_point()
k = getPrime(256)
K = k * G
r = getPrime(256)
c1 = m + r * K
c2 = r * G
w2=m[0]*m2
print(f"p = {p}")
print(f"a = {a}")
print(f"b = {b}")
print(f"k = {k}")
print(f"E = {E}")
print(f'Y = {Y}')
print(f"c1 = {c1}")
print(f"c2 = {c2}")
print(f"w2 = {w2}")
'''
p = 71397796933602469825964946338224836258949974632540581233301840806613437378503
a = 106105288190268015217241182934677375171023341761047638573248022053052499733117
b = 76170541771321874396004434442157725545076211607587599314450304327736999807927
k = 58155941823118858940343657716409231510854647214870891375273032214774400828217
E = Elliptic Curve defined by y^2 = x^3 + 34707491256665545391276236596452538912073367128507057339946181246439062354614*x + 4772744837719404570039488103932889286126236975047018081148463521123562429424 over Finite Field of size 71397796933602469825964946338224836258949974632540581233301840806613437378503
Y = (33237936857741483513705672980652927705102229733798436323453609986072499230366 : 52619411226266177137991318059937693955038910547834999771526408984808553907338 : 1)
c1 = (37414446283406201193977113266234367761786780230360175925999700345196415953455 : 17037724145039910971426670298726906655653040365428438334942732090559637519851 : 1)
c2 = (60560423732267272277570046154733119097475794979191838027420415113112056962844 : 54372226143125971429691267751299496959531971082475860532181772357190222938465 : 1)
w2 = 16315249811700998894876359855091105114973337718373913477026230968747515636405
'''

学了个大概,搞懂了一点,但还是不够,只能说目前能看懂大佬的wp。

m被分成了两部分,第一部分比较短。所以分别进行求解。

E = EllipticCurve(GF(p), [a, b])
X=E.lift_x(m1)
Y=7*X
#在椭圆上找到一点,该点的x坐标等于m1

Y是知道的,但椭圆里不存在除法,没法直接求,但又考虑到m1就5位数,直接爆破:

import tqdm

p = 71397796933602469825964946338224836258949974632540581233301840806613437378503
a = 106105288190268015217241182934677375171023341761047638573248022053052499733117
b = 76170541771321874396004434442157725545076211607587599314450304327736999807927
E = EllipticCurve(GF(p), [a, b])

for m1 in range(10000, 99999):
    try:
        X = E.lift_x(m1 - 4585)
        Y = 7 * X
        if Y[0] == 33237936857741483513705672980652927705102229733798436323453609986072499230366:
            print(m1)
            break
    except:
        pass
# 62428

第二部分可以得到下面的关系:

$c_1 = m + rK$

$K = kG$

$c_2 = rG$

$\Rightarrow m = c_1-rK = c_1-rkG = c_1-kc_2$

m = c1 - k*c2
#且又有w2 = m[0]*m2 
m2 = (w2 * inverse_mod(m[0], p))%p
#7196365442241205186856420688221367789171469258517476477

最后进行拼接就ok。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1666739907@qq.com
github