Easy_3L
题目
from gmpy2 import *
from Crypto.Util.number import *
from secret import flag
m = bytes_to_long(flag)
def get_key():
p = getPrime(1400)
f = getRandomNBitInteger(1024)
while True:
q = getPrime(512)
if gcd(f, q) != 1:
continue
else:
break
h = (invert(f, p) * q) % p
return p, h
def encrypt1(m):
a = getPrime(250)
b = getRandomNBitInteger(240)
n = getPrime(512)
seed = m
s = [0] * 6
s[0] = seed
for i in range(1, 6):
s[i] = (s[i - 1] * a + b) % n
return s
def encrypt2(msg, p, h):
s = getRandomNBitInteger(512)
c = (s * h + msg) % p
return c
s = encrypt1(m)
print("S1 =", s[1])
print("S2 =", s[2])
print("S4 =", s[4])
print("S5 =", s[5])
p, h = get_key()
c = encrypt2(s[3], p, h)
print("p =", p)
print("h =", h)
print("c =", c)
# S1 = 28572152986082018877402362001567466234043851789360735202177142484311397443337910028526704343260845684960897697228636991096551426116049875141
# S2 = 1267231041216362976881495706209012999926322160351147349200659893781191687605978675590209327810284956626443266982499935032073788984220619657447889609681888
# S4 = 9739918644806242673966205531575183334306589742344399829232076845951304871478438938119813187502023845332528267974698273405630514228632721928260463654612997
# S5 = 9755668823764800147393276745829186812540710004256163127825800861195296361046987938775181398489372822667854079119037446327498475937494635853074634666112736
# p = 25886434964719448194352673440525701654705794467884891063997131230558866479588298264578120588832128279435501897537203249743883076992668855905005985050222145380285378634993563571078034923112985724204131887907198503097115380966366598622251191576354831935118147880783949022370177789175320661630501595157946150891275992785113199863734714343650596491139321990230671901990010723398037081693145723605154355325074739107535905777351
# h = 2332673914418001018316159191702497430320194762477685969994411366563846498561222483921873160125818295447435796015251682805613716554577537183122368080760105458908517619529332931042168173262127728892648742025494771751133664547888267249802368767396121189473647263861691578834674578112521646941677994097088669110583465311980605508259404858000937372665500663077299603396786862387710064061811000146453852819607311367850587534711
# c = 20329058681057003355767546524327270876901063126285410163862577312957425318547938475645814390088863577141554443432653658287774537679738768993301095388221262144278253212238975358868925761055407920504398004143126310247822585095611305912801250788531962681592054588938446210412897150782558115114462054815460318533279921722893020563472010279486838372516063331845966834180751724227249589463408168677246991839581459878242111459287
LCG
中的初始种子就是
m
m
m,已知
S
1
,
S
2
,
S
4
,
S
5
S_{1},S_{2},S_{4},S_{5}
S1,S2,S4,S5,要恢复初始种子,我们要先求出
S
3
S3
S3.
在函数 encrypt2(msg, p, h)
中,已知
p
,
h
,
c
p,h,c
p,h,c.
m s g , s msg,s msg,s是未知的,考虑用格,
构造格
L
L
L,
(
k
,
s
,
1
)
(
−
p
,
0
,
0
−
h
,
1
,
0
c
,
0
,
2
512
)
=
(
m
s
g
,
s
,
2
512
)
(k,s,1)\begin{pmatrix} -p ,&0,&0 \\ -h,&1,&0 \\ c,&0,&2^{512} \end{pmatrix}=(msg,s,2^{512})
(k,s,1)⎝⎛−p,−h,c,0,1,0,002512⎠⎞=(msg,s,2512)
m
s
g
msg
msg就是
S
3
S_{3}
S3,这样就可以恢复
s
e
e
d
seed
seed了
from Crypto.Util.number import *
p = 25886434964719448194352673440525701654705794467884891063997131230558866479588298264578120588832128279435501897537203249743883076992668855905005985050222145380285378634993563571078034923112985724204131887907198503097115380966366598622251191576354831935118147880783949022370177789175320661630501595157946150891275992785113199863734714343650596491139321990230671901990010723398037081693145723605154355325074739107535905777351
h = 2332673914418001018316159191702497430320194762477685969994411366563846498561222483921873160125818295447435796015251682805613716554577537183122368080760105458908517619529332931042168173262127728892648742025494771751133664547888267249802368767396121189473647263861691578834674578112521646941677994097088669110583465311980605508259404858000937372665500663077299603396786862387710064061811000146453852819607311367850587534711
c = 20329058681057003355767546524327270876901063126285410163862577312957425318547938475645814390088863577141554443432653658287774537679738768993301095388221262144278253212238975358868925761055407920504398004143126310247822585095611305912801250788531962681592054588938446210412897150782558115114462054815460318533279921722893020563472010279486838372516063331845966834180751724227249589463408168677246991839581459878242111459287
mat = [[-p,0,0],[-h,1,0],[c,0,2^512]]
M = Matrix(ZZ,mat)
hh = M.LLL()[0]
# print(hh)
msg = hh[0]
print(f"msg = {msg}")
# msg = 10700695166096094995375972320865971168959897437299342068124161538902514000691034236758289037664275323635047529647532200693311709347984126070052011571264606
LCG
恢复seed
import gmpy2
from Crypto.Util.number import GCD, isPrime, long_to_bytes
c=[28572152986082018877402362001567466234043851789360735202177142484311397443337910028526704343260845684960897697228636991096551426116049875141,
1267231041216362976881495706209012999926322160351147349200659893781191687605978675590209327810284956626443266982499935032073788984220619657447889609681888,
10700695166096094995375972320865971168959897437299342068124161538902514000691034236758289037664275323635047529647532200693311709347984126070052011571264606,
9739918644806242673966205531575183334306589742344399829232076845951304871478438938119813187502023845332528267974698273405630514228632721928260463654612997,
9755668823764800147393276745829186812540710004256163127825800861195296361046987938775181398489372822667854079119037446327498475937494635853074634666112736
]
# print(c[2].bit_length())
t=[]
for i in range(1,len(c)):
t.append(c[i]-c[i-1])
m = 0 # 求n
for i in range(1,len(t)-1):
m = GCD(t[i+1]*t[i-1]-t[i]**2, m)
# print(isPrime(m)) # False m的倍数
print(f"n = {m}")
for i in range(1,100):
if isPrime(m//i):
print(i) # i是4
m//=i
break
a = (c[3]-c[2])*gmpy2.invert(c[2]-c[1],m) % m
b = (c[2]-a*c[1]) % m
a_1=gmpy2.invert(a,m)
print(f"a = {a}")
print(f"b = {b}")
print(f"a_1 = {a_1}")
n = 12433235385460084327215142269091752668477278692416805859007828624838647815241707248797912107322868748847211061641608674422095027981318008221949510129177787
a = 1017579321905754831612145134014116183026524698685218523407174987842084260441
b = 1244547131344198183940330607549789182491018543684349414313485985685030480
a_1 = 11328311979915953125685402059730442802186525001769955129939835010285255328316264293029576580150862310729537002669636904024186460482729761660664512406166499
m = (c[0]-b)*a_1 % n
print(long_to_bytes(m))
b'DASCTF{NTRU_L0G_a6e_S1mpLe}'
danger_RSA
题目
from Crypto.Util.number import *
m = bytes_to_long(flag)
def get_key(a, nbit):
assert a >= 2
while True:
X = getRandomInteger(nbit // a)
s = getRandomRange(pow(2, a ** 2 - a + 4), pow(2, a ** 2 - a + 5))
p = X ** a + s
if isPrime(p):
return (p, s)
p, s = get_key(a, 1024)
q, t = get_key(a, 1024)
N = p * q
e = s * t
c = pow(m, e, N)
print("N =", N)
print("e =", e)
print("c =", c)
# N = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
# e = 11079917583
# c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766
题目最终还是回到
R
S
A
RSA
RSA,要求解
p
,
q
p,q
p,q.这里构造了一种公钥生成方式
p
=
a
r
+
s
q
=
b
r
+
t
p=a^{r}+s\\q=b^{r}+t
p=ar+sq=br+t
还知道,
e
=
s
∗
t
e=s*t
e=s∗t
且
s
,
t
s,t
s,t是在一定范围里面的,思考是否可以通过分解
e
e
e,然后排列组合求出
s
,
t
s,t
s,t的组合。这里需要注意的是,组合有很多种,正确的组合才能求出整数解,要多尝试。
根据
e
b
i
t
e_{bit}
ebit我们是可以推断出r
的。
print(e.bit_length())#34
for m in range(10):
print(m,m**2-m+4,m**2-m+5)
# 4,16,17
得到
r
=
4
r=4
r=4,
s
b
i
t
=
17
,
t
b
i
t
=
17
s_{bit}=17,t_{bit}=17
sbit=17,tbit=17,
a
b
i
t
=
256
,
b
b
i
t
=
256
a_{bit}=256,b_{bit}=256
abit=256,bbit=256,所以
s
,
t
s,t
s,t的值不足以影响
N
N
N的大小,故有
N
=
p
∗
q
=
(
a
r
+
s
)
(
b
r
+
t
)
=
(
a
b
)
r
⇒
a
∗
b
=
g
m
p
y
2.
i
r
o
o
t
(
n
,
4
)
N=p*q=(a^{r}+s)(b^{r}+t)=(ab)^{r}\Rightarrow a*b=gmpy2.iroot(n,4)
N=p∗q=(ar+s)(br+t)=(ab)r⇒a∗b=gmpy2.iroot(n,4)
这样,就能联立方程,求出
a
,
b
a,b
a,b了
验证 s b i t = t b i t s_{bit}=t_{bit} sbit=tbit是17的
tepm = [3,7,7,19,691,5741]
for e in combinations(tepm, 3):
sum = 1
for i in e:
sum *= i
if sum in range(2**16, 2**17):
print(e)
print(sum)
s,t = [3*7*5741,7*19*691]
# print(tepm1[0].bit_length()) 17
# print(tepm1[1].bit_length()) 17
然后联立方程解 a , b a,b a,b
import gmpy2
from Crypto.Util.number import *
n = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
e = 11079917583
c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766
r,s=[3*7*5741,7*19*691]
ab=int(gmpy2.iroot(n,4)[0])
var('a b')
f1=a*b==ab
f2=n==(ab**4)+a**4*s+b**4*r+r*s
print(solve([f1,f2],[a,b]))
'''a = 47783641287938625512681830427927501009821495321018170621907812035456872958654
b = 44416071018427916652440592614276227563515579156219730344722242565477265479486'''
在求解私钥 d d d的时候发现 e 和 p h i e和phi e和phi不互素。一般 p 和 q p和q p和q很大,在 f l a g flag flag没有填充的情况下,会小于 p 和 q p和q p和q,可以将 p , q p,q p,q单独作为公钥求解。
先把不互素的部分去除,然后剩下的利用 p 或 者 q p或者q p或者q构建多项式环求根。
a = 47783641287938625512681830427927501009821495321018170621907812035456872958654
b = 44416071018427916652440592614276227563515579156219730344722242565477265479486
p=a**4+r
q=b**4+s
# print(gcd(e,p-1) #3
d=inverse(e//3,p-1)
m_3=pow(c,d,n)
e=3
P.<a>=PolynomialRing(Zmod(p),implementation='NTL')
f=a^e-m_3
mps=f.monic().roots()
for i in mps:
flag=long_to_bytes(int(i[0]))
if b'DASCTF' in flag or b'dasctf' in flag:
print(flag)
b'DASCTF{C0nsTruct!n9_Techn1qUe2_f0r_RSA_Pr1me_EnC2ypt10N}'
赛后尝试用 q q q作为公钥来求解。发现有一个问题就是去除公因数不彻底,逆元不存在。
gcd_eq_1 = gmpy2.gcd(e,q-1) # 7
gcd_2 = gmpy2.gcd(e//7,q-1) # 7
所以为了一次性把公因数去除彻底,让 e e e和 q − 1 q-1 q−1都除以最大公因数,而不应该只让一边去除公因数(只让 e / / 7 e//7 e//7).
import gmpy2
from Crypto.Util.number import *
n =
e =
c =
#print(e.bit_length()) 34
# for m in range(10):
# print(m,m**2-m+4,m**2-m+5)
#4,16,17
r,s=[3*7*5741,7*19*691]
ab=int(gmpy2.iroot(n,4)[0])
# var('a b')
# f1=a*b==ab
# f2=n==(ab**4)+a**4*s+b**4*r+r*s
# print(solve([f1,f2],[a,b]))
a = 47783641287938625512681830427927501009821495321018170621907812035456872958654
b = 44416071018427916652440592614276227563515579156219730344722242565477265479486
p=a**4+r
q=b**4+s
# print(gcd(e//7,q-1)
d = inverse(e//7,(q-1)//7)
# d = inverse(e//49,q-1)
m_49 = pow(c,d,n)
e = 7
# e = 49
q.<a>=PolynomialRing(Zmod(q),implementation='NTL')
f = a^e-m_49
mps = f.monic().roots()
for i in mps:
flag=long_to_bytes(int(i[0]))
if b'DASCTF' in flag or b'dasctf' in flag:
print(flag)
XOR贯穿始终
第一次做这样的题,卡了很久很久。。
题目附件是加密的,要想办法拿到密码。注意到题目给了一个 m a s s e g e . t x t massege.txt massege.txt,打开一看,是社会主义核心价值观编码,在线网站解密就行。
massege.txt
的内容:
自由和谐和谐富强公正友善爱国公正法治法治文明和谐自由法治自由法治平等公正友善公正公正民主法治自由公正敬业和谐富强公正友善爱国和谐平等平等友善敬业法治敬业和谐富强法治平等平等友善敬业公正公正公正友善敬业法治平等平等诚信自由公正自由平等友善敬业公正友善法治和谐和谐
解码:
C0ngr4tulati0n5_y0u_fou^d_m3
现在就能打开附件了,看到题目
from gmpy2 import gcd
from Crypto.Util.number import getPrime
from secret import enflag
p = getPrime(512)
q = getPrime(512)
n = q * p
phi = (p - 1) * (q - 1)
e = getPrime(17)
assert gcd(e, phi) == 1
# 以上信息生成了私钥文件,但文件被损坏了你能提取有用信息吗
c = pow(enflag, e, n)
print('c = ' + str(c))
'''
c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852503264709127650106856760043956604644700201911063515109074933378818
'''
私钥丢失了,但是给了一个 p e m pem pem证书,要我们从中提取私钥。
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALmtMy+2uH1ZtbIL
SuiAukFthyQRH5mp7UmLyzZQkdg9zEP9/5tgffikQ7ytx5kHySHnazgAO1sOzmYE
N4Axlev6uafiP8B1Eij97v5VkYJ1I9e3mtBNheTbXKoT8op+ASQ1fQaF4A8UzLuW
eZeZI8JTH/SH+bolAK3kiZXDFdkTAgMBAAECgYEAl067LaC7Cvs2A5cMPhfYsESv
IgcKN1CwW4Sd3u8dSphhgu7TgyzIuvwxbuo2g1BC6WwKhaI6vGN+csfw6nh98GEn
/p3D0huNroAYvf/DRRB9UnHdttX7wB+Mv3P0RBDWHgBiCDVvHFuFUV78cIs0tnbn
jxjU07aPV2XRC3AfA2ECQQDqWUNPVg3i6vTyHCL7EGkbeUheYpAAfcKCQrxjc5+5
X6A+XtgHAA1JHwykPlCpHUOmlA85DJF1ejuoImzlgRLJAkEAytTCnQF+MN2r1gaA
UETZyj5qMYT7Th8zKEVVVJjDawLnuX4usJ2FyRnjCkk86U75QSJhw5mMc0QnG25u
Gz3++w==
-----END PRIVATE KEY-----
先了解一下 p e m pem pem证书吧
将pem
证书的base64
解码,再转hex
,分割出
n
,
e
,
d
,
p
,
q
n,e,d,p,q
n,e,d,p,q.在这里
d
p
,
d
q
,
m
p
d_{p},d_{q},m_{p}
dp,dq,mp是没有泄露的。
最后发现真正的 f l a g flag flag是 R S A RSA RSA的 f l a g flag flag和社会主义核心价值观解码结果异或的结果。
import gmpy2
from Crypto.Util.number import long_to_bytes, bytes_to_long
# s = '00 ca d4 c2 9d 01 7e 30 dd ab d6 06 80 50 44 d9 ca 3e 6a 31 84 fb 4e 1f 33 28 45 55 54 98 c3 6b 02 e7 b9 7e 2e b0 9d 85 c9 19 e3 0a 49 3c e9 4e f9 41 22 61 c3 99 8c 73 44 27 1b 6e 6e 1b 3d fe fb'
# n1 = ''
# sum = 0
# for i in s:
# if i != ' ':
# n1 += i
# else:
# sum += 1
# print(n1)
# print(sum)
n = 0x00b9ad332fb6b87d59b5b20b4ae880ba416d8724111f99a9ed498bcb365091d83dcc43fdff9b607df8a443bcadc79907c921e76b38003b5b0ece660437803195ebfab9a7e23fc0751228fdeefe5591827523d7b79ad04d85e4db5caa13f28a7e0124357d0685e00f14ccbb9679979923c2531ff487f9ba2500ade48995c315d9130203010001
d = 0x00974ebb2da0bb0afb3603970c3e17d8b044af22070a3750b05b849ddeef1d4a986182eed3832cc8bafc316eea36835042e96c0a85a23abc637e72c7f0ea787df06127fe9dc3d21b8dae8018bdffc345107d5271ddb6d5fbc01f8cbf73f44410d61e006208356f1c5b85515efc708b34b676e78f18d4d3b68f5765d10b701f0361
p = 0x00ea59434f560de2eaf4f21c22fb10691b79485e6290007dc28242bc63739fb95fa03e5ed807000d491f0ca43e50a91d43a6940f390c91757a3ba8226ce58112c9
q = 0x00cad4c29d017e30ddabd606805044d9ca3e6a3184fb4e1f332845555498c36b02e7b97e2eb09d85c919e30a493ce94ef9412261c3998c7344271b6e6e1b3dfefb
e = 0x010001
c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852503264709127650106856760043956604644700201911063515109074933378818
# print(p*q == n)
# print(p == p1)
# print(q == q1)
m = gmpy2.powmod(c,d,p*q)
m1 = b'C0ngr4tulati0n5_y0u_fou^d_m3'
print(long_to_bytes(m^bytes_to_long(m1)))
esyRSA
题目
from gmpy2 import invert
from md5 import md5
from secret import p, q
e = ?????
n = p*q
phi = (p-1)*(q-1)
d = invert(e, phi)
ans = gcd(e,phi)
print n, e, d
print "Flag: DASCTF{%s}" %md5(str(p + q)).hexdigest()
"""
n = 8064259277274639864655809758868795854117113170423331934498023294296505063511386001711751916634810056911517464467899780578338013011453082479880809823762824723657495915284790349150975180933698827382368698861967973964030509129133021116919437755292590841218316278732797712538885232908975173746394816520256585937380642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
"""
题目分析:就是一个 R S A RSA RSA,给了 n , d n,d n,d但是需要恢复 e e e,最后让我们求的是 p + q p+q p+q.这里需要注意的是, n n n重复了一遍,去除重复部分才是真正的 n n n.
n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
格求解
比赛的时候我其实是想过用格来解决的,但是我尝试失败了。之后看到一个师傅的
W
P
WP
WP就是用格来求解的。
e
∗
d
≡
1
m
o
d
p
h
i
⇒
e*d\equiv1\textbf{ }mod\textbf{ }phi\Rightarrow
e∗d≡1 mod phi⇒
e ∗ d = k ∗ n − k ∗ ( p + q − 1 ) + 1 e*d=k*n-k*(p+q-1)+1 e∗d=k∗n−k∗(p+q−1)+1
( k , e ) ( n , 0 − d , 2 512 ) = ( k ∗ ( p + q − 1 ) − 1 , e ∗ 2 512 ) (k,e)\begin{pmatrix} n, &0 \\ -d,&2^{512} \end{pmatrix}=(k*(p+q-1)-1,e*2^{512}) (k,e)(n,−d,02512)=(k∗(p+q−1)−1,e∗2512)
这里解释一下为什么要这样构造格。
p , q p,q p,q都是 512 b i t 512bit 512bit,而 e e e是比较小的(只有5位数),为了使目标向量的两个坐标差不多大,让 e e e乘上 2 512 2^{512} 2512.(我当时就是没乘。。)
from hashlib import md5
import gmpy2
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
m = matrix(ZZ, [[n,0],[-d,2**512]])
k_pq, e = m.LLL()[0]
print("k_pq = ", k_pq)
print("e = ",e)
k_pq = abs(k_pq)
e = abs(e)//2**512
k = gcd(e*d-1,k_pq+1)
p_q = (k_pq+1)//k+1
print("Flag: DASCTF{%s}" %md5(str(p_q).encode()).hexdigest())
Flag: DASCTF{4ae33bea90f030bfddb7ac4d9222ef8f}
连分数求解
e ∗ d ≡ 1 m o d p h i ⇒ e*d\equiv1\textbf{ }mod\textbf{ }phi\Rightarrow e∗d≡1 mod phi⇒
e ∗ d = k ∗ p h i + 1 ⇒ e*d=k*phi+1\Rightarrow e∗d=k∗phi+1⇒
同 除 以 e ∗ p h i , d p h i = k e + 1 e ∗ p h i 同除以e*phi,\frac{d}{phi}=\frac{k}{e}+\frac{1}{e*phi} 同除以e∗phi,phid=ek+e∗phi1
因 为 p h i ≈ n , 且 p h i 非 常 大 , 所 以 1 e ∗ p h i ≈ 0 因为phi\approx n,且phi非常大,所以\frac{1}{e*phi}\approx 0 因为phi≈n,且phi非常大,所以e∗phi1≈0
所 以 , d n = k e + 1 e ∗ p h i 所以,\frac{d}{n}=\frac{k}{e}+\frac{1}{e*phi} 所以,nd=ek+e∗phi1
也 就 是 说 , d n ≈ k e 也就是说,\frac{d}{n}\approx\frac{k}{e} 也就是说,nd≈ek
而 d , n 是 已 知 的 , 所 以 对 d n 进 行 连 分 数 展 开 , 得 到 的 一 串 分 母 很 有 可 能 就 是 e 而d,n是已知的,所以对\frac{d}{n}进行连分数展开,得到的一串分母很有可能就是e 而d,n是已知的,所以对nd进行连分数展开,得到的一串分母很有可能就是e
# sage
from hashlib import md5
n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
c = continued_fraction(d/n) # 计算连分数
i = 1
while True:
k = c.numerator(i) # 分子
e = c.denominator(i) # 分母
if (e*d-1) % k == 0 and len(str(e)) == 5:
print(k)
print(e)
p_q = n+1-(e*d-1)//k
break
i+=1
print(f"p+q = {p_q}")
print("Flag: DASCTF{%s}" %md5(str(p_q).encode()).hexdigest())
Flag: DASCTF{4ae33bea90f030bfddb7ac4d9222ef8f}
维纳攻击求解
维纳攻击的核心就在于连分数
,所以用维纳攻击的脚本来求解也是可以的。
from hashlib import md5
import gmpy2
import libnum
def continuedFra(x, y):
"""计算连分数
:param x: 分子
:param y: 分母
:return: 连分数列表
"""
cf = []
while y:
cf.append(x // y)
x, y = y, x % y
return cf
def gradualFra(cf):
"""计算传入列表最后的渐进分数
:param cf: 连分数列表
:return: 该列表最后的渐近分数
"""
numerator = 0
denominator = 1
for x in cf[::-1]:
# 这里的渐进分数分子分母要分开
numerator, denominator = denominator, x * denominator + numerator
return numerator, denominator
def solve_pq(a, b, c):
"""使用韦达定理解出pq,x^2−(p+q)∗x+pq=0
:param a:x^2的系数
:param b:x的系数
:param c:pq
:return:p,q
"""
par = gmpy2.isqrt(b * b - 4 * a * c)
return (-b + par) // (2 * a), (-b - par) // (2 * a)
def getGradualFra(cf):
"""计算列表所有的渐近分数
:param cf: 连分数列表
:return: 该列表所有的渐近分数
"""
gf = []
for i in range(1, len(cf) + 1):
gf.append(gradualFra(cf[:i]))
return gf
def wienerAttack(d, n):
"""
:param d:
:param n:
:return: e
"""
cf = continuedFra(d, n)
gf = getGradualFra(cf)
for e, k in gf:
if k == 0:
continue
if (e * d - 1) % k != 0:
continue
phi = (e * d - 1) // k
# p, q = solve_pq(1, n - phi + 1, n)
if len(str(e))==5:
p_q = n+1-(e*d-1)//k
return e,p_q
n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
e,p_q = wienerAttack(d, n)
print(f"e = {e}")
print("Flag: DASCTF{%s}" %md5(str(p_q).encode()).hexdigest())
xenny库
值得一提的是,我们也可以直接用 X e n n y 库 Xenny库 Xenny库里面的 w i e n e r 函 数 wiener函数 wiener函数解决。 x e n n y 师 傅 xenny师傅 xenny师傅真的泰裤辣!!
from hashlib import md5
from xenny.ctf.crypto.modern.asymmetric.rsa import wiener
n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
e,p,q = wiener.attack(n, d)
print(f"e = {e}")
print("p = ",p)
print("q = ",q)
print("Flag: DASCTF{%s}" %md5(str(p + q).encode()).hexdigest())
e = 13521
p = 10181341212828413853336916619161138854377885230386496425058202154486415709366161346816273366144505351043947477469664133317598479763451392984403646602585037
q = 7920625690369490250766357750388349704260128405941822835255851274284409978206593795103040446837018619894098452542488850045009467407103749792461438242280929
Flag: DASCTF{4ae33bea90f030bfddb7ac4d9222ef8f}
MCeorpkpleer
题目
from Crypto.Util.number import *
from secret import flag
def pubkey(list, m, w):
pubkey_list = []
for i in range(len(e_bin)):
pubkey_list.append(w * list[i] % m)
return pubkey_list
def e_cry(e, pubkey):
pubkey_list = pubkey
encode = 0
for i in range(len(e)):
encode += pubkey_list[i] * int(e[i]) % m
return encode
p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = getPrime(64)
m = bytes_to_long(flag)
c = pow(m, e, n)
e_bin = (bin(e))[2:]
list = [pow(3, i) for i in range(len(e_bin))]
m = getPrime(len(bin(sum(list))) - 1)
w = getPrime(64)
pubkey = pubkey(list, m, w)
en_e = e_cry(e_bin, pubkey)
print('p = {}\n'
'n = {}\n'
'c = {}\n'
'pubkey = {}\n'
'en_e = {}'.format((p >> 435) << 435, n, c, pubkey, en_e))
'''
p = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179655351110456639347861739783538289295071556484465877192913103980697449775104351723521120185802327587352171892429135110880845830815744
n = 22687275367292715121023165106670108853938361902298846206862771935407158965874027802803638281495587478289987884478175402963651345721058971675312390474130344896656045501040131613951749912121302307319667377206302623735461295814304029815569792081676250351680394603150988291840152045153821466137945680377288968814340125983972875343193067740301088120701811835603840224481300390881804176310419837493233326574694092344562954466888826931087463507145512465506577802975542167456635224555763956520133324723112741833090389521889638959417580386320644108693480886579608925996338215190459826993010122431767343984393826487197759618771
c = 156879727064293983713540449709354153986555741467040286464656817265584766312996642691830194777204718013294370729900795379967954637233360644687807499775502507899321601376211142933572536311131955278039722631021587570212889988642265055045777870448827343999745781892044969377246509539272350727171791700388478710290244365826497917791913803035343900620641430005143841479362493138179077146820182826098057144121231954895739989984846588790277051812053349488382941698352320246217038444944941841831556417341663611407424355426767987304941762716818718024107781873815837487744195004393262412593608463400216124753724777502286239464
pubkey = [18143710780782459577, 54431132342347378731, 163293397027042136193, 489880191081126408579, 1469640573243379225737, 4408921719730137677211, 13226765159190413031633, 39680295477571239094899, 119040886432713717284697, 357122659298141151854091, 1071367977894423455562273, 3214103933683270366686819, 9642311801049811100060457, 28926935403149433300181371, 86780806209448299900544113, 260342418628344899701632339, 781027255885034699104897017, 2343081767655104097314691051, 7029245302965312291944073153, 21087735908895936875832219459, 63263207726687810627496658377, 189789623180063431882489975131, 569368869540190295647469925393, 1708106608620570886942409776179, 601827224419797931380408071500, 1805481673259393794141224214500, 893952418336266652976851386463, 2681857255008799958930554159389, 3523079163584485147344841221130, 1524252287869625983140881149316, 50264262166963219975822190911, 150792786500889659927466572733, 452378359502668979782399718199, 1357135078508006939347199154597, 4071405235524020818041597463791, 3169230503688232995231149877299, 462706308180869526799807117823, 1388118924542608580399421353469, 4164356773627825741198264060407, 3448085117999647764701149667147, 1299270151115113835209806487367, 3897810453345341505629419462101, 2648446157152195057994615872229, 3422845870014670444537026359650, 1223552407160181874717436564876, 3670657221480545624152309694628, 1966986461557807413563286569810, 1378466783231507511243038452393, 4135400349694522533729115357179, 3361215846199738142293703557463, 1038662335715384967987468158315, 3115987007146154903962404474945, 302975818554635252993570910761, 908927455663905758980712732283, 2726782366991717276942138196849, 3657854499533237101379593333510, 1928578295715881845245137486456, 1263242285705730806288591202331, 3789726857117192418865773606993, 2324195368467747797703678306905, 2450093503961328663664213663678, 2827787910442071261545819733997, 3960871129884299055190637944954, 2837628186769067706678271320788]
en_e = 31087054322877663244023458448558
'''
题目分析:
梳理一下已知信息:
p
高
位
,
n
,
c
,
e
n
e
p高位,n,c,en_e
p高位,n,c,ene
e 是 64 b i t , 那 么 列 表 l i s t 也 是 已 知 的 e是64bit,那么列表list也是已知的 e是64bit,那么列表list也是已知的
未知:
q
,
e
q,e
q,e
给出
p
p
p高位,copper
就可以恢复
p
p
p.继而就能知道
q
q
q
列表
l
i
s
t
list
list的值是已知的,且
l
i
s
t
[
0
]
list[0]
list[0]就是
W
W
W.
p
u
b
k
e
y
[
i
]
=
w
∗
l
i
s
t
[
i
]
m
o
d
m
⇒
pubkey[i]=w*list[i]\textbf{ }mod\textbf{ }m\Rightarrow
pubkey[i]=w∗list[i] mod m⇒
k ∗ m = p u b k e y [ i ] − w ∗ l i s t [ i ] k*m=pubkey[i]-w*list[i] k∗m=pubkey[i]−w∗list[i]
求出多组 k ∗ m k*m k∗m,这些 k ∗ m k*m k∗m的最大公因数就是 m m m。
再看
l
i
s
t
list
list是一个超递增序列
,直接用贪心算法
求解
e
e
e。
e
n
c
o
d
e
=
(
p
u
b
k
e
y
[
0
]
∗
e
[
0
]
+
p
u
b
k
e
y
[
1
]
∗
e
[
1
]
+
.
.
.
+
p
u
b
k
e
y
[
63
]
∗
e
[
63
]
)
m
o
d
m
encode=(pubkey[0]*e[0]+pubkey[1]*e[1]+...+pubkey[63]*e[63])\textbf{ }mod\textbf{ }m
encode=(pubkey[0]∗e[0]+pubkey[1]∗e[1]+...+pubkey[63]∗e[63]) mod m
= ( ( w ∗ l i s t [ 0 ] ) ∗ e [ 0 ] + ( w ∗ l i s t [ 1 ] ) ∗ e [ 1 ] + . . . + ( w ∗ l i s t [ 63 ] ) ∗ e [ 63 ] ) m o d m =((w*list[0])*e[0]+(w*list[1])*e[1]+...+(w*list[63])*e[63])\textbf{ }mod\textbf{ }m =((w∗list[0])∗e[0]+(w∗list[1])∗e[1]+...+(w∗list[63])∗e[63]) mod m
= w ∗ ( l i s t [ 0 ] ∗ e [ 0 ] + l i s t [ 1 ] ∗ e [ 1 ] + . . . + l i s t [ 63 ] ∗ e [ 63 ] ) m o d m =w*(list[0]*e[0]+list[1]*e[1]+...+list[63]*e[63])\textbf{ }mod \textbf{ }m =w∗(list[0]∗e[0]+list[1]∗e[1]+...+list[63]∗e[63]) mod m
所 以 , e n c o d e ∗ w − 1 = ( l i s t [ 0 ] ∗ e [ 0 ] + l i s t [ 1 ] ∗ e [ 1 ] + . . . + l i s t [ 63 ] ∗ e [ 63 ] ) m o d m 所以,encode*w^{-1}=(list[0]*e[0]+list[1]*e[1]+...+list[63]*e[63])\textbf{ }mod \textbf{ }m 所以,encode∗w−1=(list[0]∗e[0]+list[1]∗e[1]+...+list[63]∗e[63]) mod m
copper
解
p
p
p
#sage
from Crypto.Util.number import *
hint = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179655351110456639347861739783538289295071556484465877192913103980697449775104351723521120185802327587352171892429135110880845830815744
n = 22687275367292715121023165106670108853938361902298846206862771935407158965874027802803638281495587478289987884478175402963651345721058971675312390474130344896656045501040131613951749912121302307319667377206302623735461295814304029815569792081676250351680394603150988291840152045153821466137945680377288968814340125983972875343193067740301088120701811835603840224481300390881804176310419837493233326574694092344562954466888826931087463507145512465506577802975542167456635224555763956520133324723112741833090389521889638959417580386320644108693480886579608925996338215190459826993010122431767343984393826487197759618771
p_high = hint
# print(p_high)
PR.<x> = PolynomialRing(Zmod(n))
f = p_high + x
x = f.small_roots(X=2^435, beta=0.4)[0]
p = p_high+int(x)
q = n//p
print(f"p = {p}")
print(f"q = {q}")
p = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179677630589032444985150800881889090713797496239571291907818169058929859395965304623825442220206712660451198754072531986630133689525911
q = 162585259972480477964240855936099163585362299488578311068842002571891718764319834825730036484383081273549236661473286892739224906812137330941622699836239606393084030874487072527724286268715004074797344316619876830720445250395986443767703356842297999006344406006724963545062388183647988548800359369190326996261
求 m m m
list = [pow(3, i) for i in range(64)]
w = pubkey[0]
m_len = len(bin(sum(list))) - 1
k_m = []
for i in range(63,50,-1):
k_m.append(pubkey[i]-w*list[i])
m = k_m[0]
for num in k_m[1:]:
m = gmpy2.gcd(m,num)
if isPrime(m) and m.bit_length() == m_len:
print("m =",m)
break
# m = 4522492601441914729446821257037
贪心算法求解e
S = en_e * gmpy2.invert(w,m)
M = list
e = ''
for i in range(len(M)-1,-1,-1):
if S >= M[i]:
e += '1'
S -= M[i]
else:
e += '0'
e = int(e[::-1],2)
print("e =",e)
# e = 15960663600754919507
最后解RSA
import gmpy2
from Crypto.Util.number import isPrime, long_to_bytes
p = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179677630589032444985150800881889090713797496239571291907818169058929859395965304623825442220206712660451198754072531986630133689525911
q = 162585259972480477964240855936099163585362299488578311068842002571891718764319834825730036484383081273549236661473286892739224906812137330941622699836239606393084030874487072527724286268715004074797344316619876830720445250395986443767703356842297999006344406006724963545062388183647988548800359369190326996261
c = 156879727064293983713540449709354153986555741467040286464656817265584766312996642691830194777204718013294370729900795379967954637233360644687807499775502507899321601376211142933572536311131955278039722631021587570212889988642265055045777870448827343999745781892044969377246509539272350727171791700388478710290244365826497917791913803035343900620641430005143841479362493138179077146820182826098057144121231954895739989984846588790277051812053349488382941698352320246217038444944941841831556417341663611407424355426767987304941762716818718024107781873815837487744195004393262412593608463400216124753724777502286239464
e = 15960663600754919507
d = gmpy2.invert(e,(p-1)*(q-1))
real_m = gmpy2.powmod(c,d,p*q)
print(long_to_bytes(real_m))
DASCTF{T81I_tPPS_6r7g_xlPi_OO3M_6vyV_Rkba}
SigninCrypto
题目
from random import *
from Crypto.Util.number import *
from Crypto.Cipher import DES3
from flag import flag
from key import key
from iv import iv
import os
import hashlib
import secrets
K1= key
hint1 = os.urandom(2) * 8
xor =bytes_to_long(hint1)^bytes_to_long(K1)
print(xor)
def Rand():
rseed = secrets.randbits(1024)
List1 = []
List2 = []
seed(rseed)
for i in range(624):
rand16 = getrandbits(16)
List1.append(rand16)
seed(rseed)
for i in range(312):
rand64 = getrandbits(64)
List2.append(rand64)
with open("task.txt", "w") as file:
for rand16 in List1:
file.write(hex(rand16)+ "\n")
for rand64 in List2:
file.write(hex((rand64 & 0xffff) | ((rand64 >> 32) & 0xffff) << 16) + "\n") #拼接
Rand()
K2 = long_to_bytes(getrandbits(64))
K3 = flag[:8]
KEY = K1 + K2 + K3
IV=iv
IV1=IV[:len(IV)//2]
IV2=IV[len(IV)//2:]
digest1 = hashlib.sha512(IV1).digest().hex()
digest2 = hashlib.sha512(IV2).digest().hex()
digest=digest1+digest2 # type(digest)=='str'
hint2=(bytes_to_long(IV)<<32)^bytes_to_long(os.urandom(8))
print(hex(bytes_to_long((digest.encode()))))
print(hint2)
mode = DES3.MODE_CBC
des3 = DES3.new(KEY, mode, IV)
pad_len = 8 - len(flag) % 8
padding = bytes([pad_len]) * pad_len
flag += padding
cipher = des3.encrypt(flag)
ciphertext=cipher.hex()
print(ciphertext)
# 334648638865560142973669981316964458403
# 0x62343937373634656339396239663236643437363738396663393438316230353665353733303939613830616662663633326463626431643139323130616333363363326631363235313661656632636265396134336361623833636165373964343533666537663934646239396462323666316236396232303539336438336234393737363465633939623966323664343736373839666339343831623035366535373330393961383061666266363332646362643164313932313061633336336332663136323531366165663263626539613433636162383363616537396434353366653766393464623939646232366631623639623230353933643833
# 22078953819177294945130027344
# a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1
分析一下题目,这个题重点是求KEY
和IV
.
KEY
被分成了3段,IV
被分成了2段.
先看一下 K 1 K1 K1.
K1= key
hint1 = os.urandom(2) * 8
xor =bytes_to_long(hint1)^bytes_to_long(K1)
print(xor)
这里解释一下os.urandom(2)
是生成2字节的随机数,os.urandom(2) * 8
将这个随机数重复8遍.
我们输出一下,
xor = 334648638865560142973669981316964458403
print(long_to_bytes(xor))
发现有一些片段是重复的.
猜测
h
i
n
t
1
hint1
hint1就是 b'\xfb\xc2*8
,那么
K
1
K1
K1就可以求出来了.
xor = 334648638865560142973669981316964458403
print(long_to_bytes(xor))
hint1 = b'\xfb\xc2'*8
print(long_to_bytes(bytes_to_long(hint1)^xor))
# b'dasctfda'
接着我们看 K 3 K3 K3
K3 = flag[:8]
K
3
K3
K3前7位就是 b'DASCTF{'
,第8位需要爆破一下.
再来看 I V IV IV
IV=iv
IV1=IV[:len(IV)//2]
IV2=IV[len(IV)//2:]
digest1 = hashlib.sha512(IV1).digest().hex()
digest2 = hashlib.sha512(IV2).digest().hex()
digest=digest1+digest2 # type(digest)=='str'
hint2=(bytes_to_long(IV)<<32)^bytes_to_long(os.urandom(8))
print(hex(bytes_to_long((digest.encode()))))
print(hint2)
(bytes_to_long(IV)<<32)
说明在异或的时候,IV
的高32位是不受影响的,所以我们直接打印出 long_to_bytes(hint2)
,得到IV1
.
hint2 = 22078953819177294945130027344
print(long_to_bytes(hint2))
# b'GWHT\xd9\x13\xbc\xcdu~\x99P'
IV1 = b'GWHT'
这里特别强调一下,digest
的类型是str
.(打印一下
t
y
p
e
(
d
i
g
e
s
t
)
type(digest)
type(digest)),那么知道IV1
和 diegest_encode
是可以求出IV2
的.
digest_encode = 0x62343937373634656339396239663236643437363738396663393438316230353665353733303939613830616662663633326463626431643139323130616333363363326631363235313661656632636265396134336361623833636165373964343533666537663934646239396462323666316236396232303539336438336234393737363465633939623966323664343736373839666339343831623035366535373330393961383061666266363332646362643164313932313061633336336332663136323531366165663263626539613433636162383363616537396434353366653766393464623939646232366631623639623230353933643833
digest1 = hashlib.sha512(IV1).digest().hex()
digest11 = bytes_to_long(digest1.encode())
# print(digest11.bit_length()) 1023
digest2 = digest_encode-(digest11<<1024)
print(digest2==digest11) # True
说明IV2
也是 b'GWHT'
.至此,IV
求出,IV=b'GWHTGWHT'
(这里讲一下,细心的人可能发现digest
是两个相同的数拼接而成,所以IV2==IV1
)
最后求K2
,生成K2
的方法是梅森旋转法
Mersenne Twister
算法有一个内部状态数据库,该数据库由624个32位无符号整数组成。在每次请求随机修改数字时,它都会提取并返回一个值,同时内部状态认为下次请求准备好。当算法消耗了所有 624 个状态之后,它会进行一次称为“扭曲”的操作,更新所有 624 个状态。
使用相同的种子对随机数生成器进行初始化,那么生成的随机数序列将是确定的,并且每次都是相同的。
再看一下随机数的生成机制:
通过生成32bit
的数进行拼接或者移位(大佬教的)
如果要生成16bit
的数,是先生成
32
b
i
t
32bit
32bit再取这个数的高16位
如果要生成64bit
的数,先生成两个32bit
的数x1,x2
,再进行拼接x1|x2
有了这些知识,我们就可以恢复初始状态,并预测下一个随机数(也就是 K 2 K2 K2).
在Rand()
中,通过List1
可以得到624个
32
b
i
t
32bit
32bit的随机数的高16
位.通过
L
i
s
t
2
List2
List2可以得到
624
624
624个
32
b
i
t
32bit
32bit的随机数的低
16
16
16位,这样初始状态就恢复了.
exp
from Crypto.Cipher import DES3
from Crypto.Util.number import *
from randcrack import RandCrack
f = open("task.txt","r")
List = []
for data in f:
List.append(eval(data))
List1 = List[:624] # 高16位
List2 = List[624:]
List3 = []
# 低16位
for data in List2:
List3.append(data & 0xffff)
List3.append((data>>16) & 0xffff)
# 恢复初始624个32bit的随机数
rc = []
for data1,data2 in zip(List1,List3):
rc.append((data1<<16)+data2)
# print(rc)
rc1 = RandCrack()
for i in rc:
rc1.submit(i)
K2 = long_to_bytes(rc1.predict_getrandbits(64))
# print(K2)
IV1 = b'GWHT'
IV2 = IV1
IV = IV1+IV2
K3_7 = b'DASCTF{'
K1 = b'dasctfda'
c = 'a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1'
c = bytes.fromhex(c)
for i in range(2**10):
KEY = K1 + K2 + K3_7 + long_to_bytes(i)
mode = DES3.MODE_CBC
des3 = DES3.new(KEY, mode, IV)
m = des3.decrypt(c)
if b'DASCTF' in m:
print(m)
break
DASCTF{8e5ee461-f4e1-4af2-8632-c9d62f4dc073}