一.第14届蓝桥杯网安春秋赛Crypto题
CyberChef
题目:
题目中给出了一个CyberChef的html,打开后发现在
Recipe处有两个:To Base 64 和 ROT13 Amount 3
Input :flag{----}(你需要求出这个flag值)
Output :CpakC3wnB2L3Q2IlBb02QGT1OWT4QGDwBpMmBV01PmXbCmBzQcP1CWg9
分析可知,该密文是先由 Base 64 编码,然后再由 ROT13 Amount 3进行编码得出的,所以我们只需反过来先进行 ROT13 解码,再由 Base 64 解码,即可获得flag
先进行 ROT13 解码时,由于不知道 Amount 的值,所以只能一个一个尝试,在进行到 Amount 23 时,就会发现 Output 的前四位为 Zmxh ,依据以往对于 Base 编码 的认识,可知这个就是 flag 的密文,最后再进行 Base 64 解码 即可获得flag
RSA
题目:
#!python3.9
from Crypto.Util.number import *
from flag import flag
import gmpy2
import random
random.seed(123456)
m = bytes_to_long(flag)
e1 = random.randint(100000000, 999999999)
e2 = 65537
n = 7265521127830448713067411832186939510560957540642195787738901620268897564963900603849624938868472135068795683478994264434459545615489055678687748127470957
c1 = pow(m,e1,n)
c2 = pow(m,e2,n)
print(c1)
print(c2)
# 3315026215410356401822612597933850774333471554653501609476726308255829187036771889305156951657972976515685121382853979526632479380900600042319433533497363
# 1188105647021006315444157379624581671965264301631019818847700108837497109352704297426176854648450245702004723738154094931880004264638539450721642553435120
根据题目可知,此为RSA的共模攻击,所以直接使用代码解决即可
先求出e1
random.seed(123456)
e1 = random.randint(100000000,999999999)
print(e1)
最后直接使用代码即可获得flag
import gmpy2
from Crypto.Util.number import getPrime, long_to_bytes
e1 = 965035544
n=7265521127830448713067411832186939510560957540642195787738901620268897564963900603849624938868472135068795683478994264434459545615489055678687748127470957
e2 = 65537
c1= 3315026215410356401822612597933850774333471554653501609476726308255829187036771889305156951657972976515685121382853979526632479380900600042319433533497363
c2 = 1188105647021006315444157379624581671965264301631019818847700108837497109352704297426176854648450245702004723738154094931880004264638539450721642553435120
_, s1, s2 = gmpy2.gcdext(e1, e2)
m = pow(c1, s1, n) * pow(c2, s2, n) % n
print(long_to_bytes(m))
二.NewStar WEEK 2
滴啤
题目:
from Crypto.Util.number import *
import gmpy2
from flag import flag
def gen_prime(number):
p = getPrime(number//2)
q = getPrime(number//2)
return p,q
m = bytes_to_long(flag.encode())
p,q = gen_prime(1024)
print(p*q)
e = 65537
d = gmpy2.invert(e,(p-1)*(q-1))
print(d%(p-1))
print(pow(m,e,p*q))
# 93172788492926438327710592564562854206438712390394636149385608321800134934361353794206624031396988124455847768883785503795521389178814791213054124361007887496351504099772757164211666778414800698976335767027868761735533195880182982358937211282541379697714874313863354097646233575265223978310932841461535936931
# 307467153394842898333761625034462907680907310539113349710634557900919735848784017007186630645110812431448648273172817619775466967145608769260573615221635
# 52777705692327501332528487168340175436832109866218597778822262268417075157567880409483079452903528883040715097136293765188858187142103081639134055997552543213589467751037524482578093572244313928030341356359989531451789166815462417484822009937089058352982739611755717666799278271494933382716633553199739292089
根据题干所给的信息可知此题为dp泄露,所以直接使用代码解决
import libnum
import gmpy2
n = 93172788492926438327710592564562854206438712390394636149385608321800134934361353794206624031396988124455847768883785503795521389178814791213054124361007887496351504099772757164211666778414800698976335767027868761735533195880182982358937211282541379697714874313863354097646233575265223978310932841461535936931
c = 52777705692327501332528487168340175436832109866218597778822262268417075157567880409483079452903528883040715097136293765188858187142103081639134055997552543213589467751037524482578093572244313928030341356359989531451789166815462417484822009937089058352982739611755717666799278271494933382716633553199739292089
dp = 307467153394842898333761625034462907680907310539113349710634557900919735848784017007186630645110812431448648273172817619775466967145608769260573615221635
e = 65537
#遍历,爆破出p
#dp*e-1=(p-1)*[k2*(q-1)-k1]
#i=[k2*(q-1)-k1]
for i in range(1,e):
p = (dp*e-1)//i + 1
if n%p==0:
q=n//p
break
print(p)
print(q)
phi_n= (p-1)*(q-1)
d=gmpy2.invert(e,phi_n)
m=pow(c,d,n)
print(m)
flag=libnum.n2s(int(m)).decode()
print(flag)
不止一个pi
题目:
from flag import flag
from Crypto.Util.number import *
import gmpy2
p = getPrime(1024)
q = getPrime(1024)
n = p**3*q**2
print("q = ",q)
print("p = ",p)
m = bytes_to_long(flag.encode())
c = pow(m,65537,n)
print("c = ",c)
# q = 115478867870347527660680329271012852043845868401928361076102779938370270670897498759391844282137149013845956612257534640259997979275610235395706473965973203544920469416283181677660262509481282536465796731401967694683575843183509430017972506752901270887444490905891490955975762524187534052478173966117471143713
# p = 171790960371317244087615913047696670778115765201883835525456016207966048658582417842936925149582378305610304505530997833147251832289276125084339614808085356814202236463900384335878760177630501950384919794386619363394169016560485152083893183420911295712446925318391793822371390439655160077212739260871923935217
# c = 4459183928324369762397671605317600157512712503694330767938490496225669985050002776253470841193156951087663107866714426230222002399666306287642591077990897883174134404896800482234781531592939043551832049756571987010173667074168282355520711905659013076509353523088583347373358980842707686611157050425584598825151399870268083867269912139634929397957514376826145870752116583185351576051776627208882377413433140577461314504762388617595282085102271510792305560608934353515552201553674287954987323321512852114353266359364282603487098916608302944694600227628787791876600901537888110093703612414836676571562487005330299996908873589228072982641114844761980143047920770114535924959765518365614709272297666231481655857243004072049094078525569460293381479558148506346966064906164209362147313371962567040047084516510135054571080612077333228195608109065475260832580192321853906138811139036658485688320161530131239854003996457871663456850196483520239675981391047452381998620386899101820782421605287708727667663038905378115235163773867508258208867367314108701855709002634592329976912239956212490788262396106230191754680813790425433763427315230330459349320412354189010684525105318610102936715203529222491642807382215023468936755584632849348996666528981269240867612068382243822300418856599418223875522408986596925018975565057696218423036459144392625166761522424721268971676010427096379610266649911939139451989246194525553533699831110568146220347603627745407449761792135898110139743498767543521297525802809254842518002190381508964357001211353997061417710783337
根据题目可知,该题考察的是RSA的欧拉函数变形,因为 n = p ** 3 * q ** 2,所以相应的phi_n=(p-1) * (q-1) * p ** 2 * q,稍微改下代码即可获得flag
from Crypto.Util.number import *
p = 171790960371317244087615913047696670778115765201883835525456016207966048658582417842936925149582378305610304505530997833147251832289276125084339614808085356814202236463900384335878760177630501950384919794386619363394169016560485152083893183420911295712446925318391793822371390439655160077212739260871923935217
q = 115478867870347527660680329271012852043845868401928361076102779938370270670897498759391844282137149013845956612257534640259997979275610235395706473965973203544920469416283181677660262509481282536465796731401967694683575843183509430017972506752901270887444490905891490955975762524187534052478173966117471143713
e = 65537
c = 4459183928324369762397671605317600157512712503694330767938490496225669985050002776253470841193156951087663107866714426230222002399666306287642591077990897883174134404896800482234781531592939043551832049756571987010173667074168282355520711905659013076509353523088583347373358980842707686611157050425584598825151399870268083867269912139634929397957514376826145870752116583185351576051776627208882377413433140577461314504762388617595282085102271510792305560608934353515552201553674287954987323321512852114353266359364282603487098916608302944694600227628787791876600901537888110093703612414836676571562487005330299996908873589228072982641114844761980143047920770114535924959765518365614709272297666231481655857243004072049094078525569460293381479558148506346966064906164209362147313371962567040047084516510135054571080612077333228195608109065475260832580192321853906138811139036658485688320161530131239854003996457871663456850196483520239675981391047452381998620386899101820782421605287708727667663038905378115235163773867508258208867367314108701855709002634592329976912239956212490788262396106230191754680813790425433763427315230330459349320412354189010684525105318610102936715203529222491642807382215023468936755584632849348996666528981269240867612068382243822300418856599418223875522408986596925018975565057696218423036459144392625166761522424721268971676010427096379610266649911939139451989246194525553533699831110568146220347603627745407449761792135898110139743498767543521297525802809254842518002190381508964357001211353997061417710783337
n = p**3*q**2
#欧拉函数
phi_n=(p-1)*(q-1)*p**2*q
#求逆元
d=inverse(e,phi_n)
print(d)
m=c^d%n
m=pow(c,d,n)
print(long_to_bytes(m))
halfcandecode
题目:
from Crypto.Util.number import *
import gmpy2
from flag import flag
import os
from hashlib import md5
def gen_prime(number):
p = getPrime(number // 2)
q = gmpy2.next_prime(p)
return p * q
def md5_hash(m):
return md5(m.encode()).hexdigest()
e = 65537
n = gen_prime(1024)
m1 = bytes_to_long(flag[:len(flag) // 2].encode() + os.urandom(8))
c1 = pow(m1, e, n)
m2 = flag[len(flag) // 2:]
with open("out.txt","w") as f:
f.write(str(n) + '\n')
f.write(str(c1) + '\n')
for t in m2:
f.write(str(md5_hash(t))+'\n')
113021375625152132650190712599981988437204747209058903684387817901743950240396649608148052382567758817980625681440722581705541952712770770893410244646286485083142929097056891857721084849003860977390188797648441292666187101736281034814846427200984062294497391471725496839508139522313741138689378936638290593969
43054766235531111372528859352567995977948625157340673795619075138183683929001986100833866227688081563803862977936680822407924897357491201356413493645515962458854570731176193055259779564051991277092941379392700065150286936607784073707448630150405898083000157174927733260198355690620639487049523345380364948649
4a8a08f09d37b73795649038408b5f33
03c7c0ace395d80182db07ae2c30f034
e1671797c52e15f763380b45e841ec32
b14a7b8059d9c055954c92674ce60032
e358efa489f58062f10dd7316b65649e
cfcd208495d565ef66e7dff9f98764da
b14a7b8059d9c055954c92674ce60032
8fa14cdd754f91cc6554c9e71929cce7
0cc175b9c0f1b6a831c399e269772661
4a8a08f09d37b73795649038408b5f33
e358efa489f58062f10dd7316b65649e
cfcd208495d565ef66e7dff9f98764da
4b43b0aee35624cd95b910189b3dc231
cbb184dd8e05c9709e5dcaedaa0495cf
根据已知信息可知,n,c,还有hash,依据题目所给的可知q,p很接近,所以直接对n开根号取下一个素数作为p,然后用Hash爆破代码即可获得flag
from Crypto.Util.number import *
import gmpy2
import hashlib
from tqdm import *
n = 113021375625152132650190712599981988437204747209058903684387817901743950240396649608148052382567758817980625681440722581705541952712770770893410244646286485083142929097056891857721084849003860977390188797648441292666187101736281034814846427200984062294497391471725496839508139522313741138689378936638290593969
c = 43054766235531111372528859352567995977948625157340673795619075138183683929001986100833866227688081563803862977936680822407924897357491201356413493645515962458854570731176193055259779564051991277092941379392700065150286936607784073707448630150405898083000157174927733260198355690620639487049523345380364948649
HASH = ["4a8a08f09d37b73795649038408b5f33","03c7c0ace395d80182db07ae2c30f034","e1671797c52e15f763380b45e841ec32","b14a7b8059d9c055954c92674ce60032","e358efa489f58062f10dd7316b65649e","cfcd208495d565ef66e7dff9f98764da","b14a7b8059d9c055954c92674ce60032","8fa14cdd754f91cc6554c9e71929cce7","0cc175b9c0f1b6a831c399e269772661","4a8a08f09d37b73795649038408b5f33","e358efa489f58062f10dd7316b65649e","cfcd208495d565ef66e7dff9f98764da","4b43b0aee35624cd95b910189b3dc231","cbb184dd8e05c9709e5dcaedaa0495cf"]
t = gmpy2.iroot(n,2)[0]
p = gmpy2.next_prime(t)
q = n // p
e = 65537
d = gmpy2.invert(e,(p-1)*(q-1))
m = pow(c,d,n)
flag1 = long_to_bytes(m)[:-8]
flag2 = ""
for i in trange(len(HASH)):
for j in range(32,128):
hash = hashlib.md5(chr(j).encode()).hexdigest()
if hash == HASH[i]:
flag2 += chr(j)
flag = flag1+ flag2.encode()
print(flag)
Rotate Xor
题目:
from secret import flag
from os import urandom
from pwn import xor
from Cryptodome.Util.number import *
k1 = getPrime(64)
k2 = getPrime(64)
ROUND = 12
ciphertext = xor(flag, long_to_bytes(k1))
def round_rotate_left(num, step):
return ((num) << step | num >> (64-step)) & 0xffffffffffffffff
def encrypt_key(key):
for _ in range(ROUND):
key = round_rotate_left(key, 3) ^ k2
return key
print('ciphertext =', ciphertext)
print('enc_k1 =', encrypt_key(k1))
print('k2 =', k2)
# ciphertext = b'\x8dSyy\xd2\xce\xe2\xd2\x98\x0fth\x9a\xc6\x8e\xbc\xde`zl\xc0\x85\xe0\xe4\xdfQlc'
# enc_k1 = 7318833940520128665
# k2 = 9982833494309156947
根据提醒 旋转异或我闭着眼, flag我看不见,,然后分析题目可知,本题先让 k1和flag进行一次XOR 生成密文,随后定义一个 左移的函数 ,并且让 k1左移3位和k2进行XOR,循环12次 生成encrypt_key
要破解这个加密的话,只需按照这个加密过程逆序右移破解,使用代码即可获得flag
注意:return ((num) >> step | num << (64 - step)) & 0xffffffffffffffff
以及先进行异或运算再进行循环
from pwn import xor
from Crypto.Util.number import *
ciphertext = b'\x8dSyy\xd2\xce\xe2\xd2\x98\x0fth\x9a\xc6\x8e\xbc\xde`zl\xc0\x85\xe0\xe4\xdfQlc'
enc_k1 = 7318833940520128665
k2 = 9982833494309156947
ROUND = 12
def round_rotate_right(num, step):
return ((num) >> step | num << (64 - step)) & 0xffffffffffffffff
for _ in range(ROUND):
# 对 enc_k1 进行反向位操作,首先是异或操作
enc_k1 ^= k2
# 然后进行右循环移位 3 位
enc_k1 = round_rotate_right(enc_k1, 3)
flag = xor(ciphertext, long_to_bytes(enc_k1))
print(flag)
partial decrypt
题目:
from secret import flag
from Crypto.Util.number import *
m = bytes_to_long(flag)
e = 65537
p = getPrime(512)
q = getPrime(512)
n = p*q
c = pow(m,e,n)
dp = inverse(e, (p-1))
dq = inverse(e, (q-1))
m1 = pow(c,dp, p)
m2 = pow(c,dq, q)
q_inv = inverse(q, p)
h = (q_inv*(m1-m2)) % p
print('m2 =', m2)
print('h =', h)
print('q =', q)
# m2 = 4816725107096625408335954912986735584642230604517017890897348901815741632668751378729851753037917164989698483856004115922538576470127778342121497852554884
# h = 4180720137090447835816240697100630525624574275
# q = 7325294399829061614283539157853382831627804571792179477843187097003503398904074108324900986946175657737035770512213530293277111992799331251231223710406931
根据提醒 解密, 但是只解密一半,然后观察题目 dp,dq泄露 ,联想有关的三大公式:
m
1
≡
c
d
p
(
m
o
d
p
)
m_1\equiv c^dp \pmod p
m1≡cdp(modp)
m 2 ≡ c d q ( m o d q ) m_2\equiv c^dq \pmod q m2≡cdq(modq)
m ≡ ( ( ( m 1 − m 2 ) q − 1 ( m o d p ) ) q + m 2 ) ( m o d n ) m\equiv(((m_1-m_2) q^-1 \pmod p)q+m_2)\pmod n m≡(((m1−m2)q−1(modp))q+m2)(modn)
观察这三个公式,我们很明显发现 h与第三个公式的前半段一模一样 再看开头的提醒说只解密一半,所以直接尝试 m=hq+m2 即可获得flag
from Crypto.Util.number import *
m2 = 4816725107096625408335954912986735584642230604517017890897348901815741632668751378729851753037917164989698483856004115922538576470127778342121497852554884
h = 4180720137090447835816240697100630525624574275
q = 7325294399829061614283539157853382831627804571792179477843187097003503398904074108324900986946175657737035770512213530293277111992799331251231223710406931
m = h * q + m2
print(long_to_bytes(m))
broadcast
题目:
ps:以下代码没什么用
from secret import flag
from Cryptodome.Util.number import *
menu = '''
Welcome to RSA Broadcasting system
please select your option:
1. brocast the flag
2. exit
'''
e = 17
def broadcast_the_flag():
p = getPrime(256)
q = getPrime(256)
n=p*q
m = bytes_to_long(flag)
c = pow(m,e,n)
print('n =', n)
print('c =', c)
print('e =', e)
while True:
print(menu)
opt = input('> ')
try:
opt = int(opt)
if opt == 1:
broadcast_the_flag()
elif opt == 2:
break
else:
print('invalid option')
except:
print('oh no, something wrong!')
还有一个靶机,但是在连接靶机后发现
n = 5808436198040972207287812683662181770450052801125182713659713216147764132020743514644563640895521383517450364057565145080086906395979229392257556132942637
c = 641274636240116184348281947412643943932469655427656762907409135471182053306036746146546624052249170879119536912973664641654873487359179035413197715821352
e =
17
观察这个题目可知 n 难以破解,所以考虑靶机特性,因为是对同一个明文加密,所以我们可以截获到多组信息。联想到中国剩余定理,直接nc对这个靶机进行爆破(需要安装相关的函数库)(参考了一位大佬的爆破代码),即可获得flag
from pwn import *
from tqdm import *
from sympy.ntheory.modular import *
from Crypto.Util.number import *
import gmpy2
host = 'node5.buuoj.cn' #ip地址
port = 26177 #端口
sh = remote(host,port) #建立连接
N = []
C = []
for i in trange(17):
data = sh.recvuntil(b">")
# print(data.decode())
sh.sendline(b"1")
n = sh.recvline().decode().split('=')[-1]
N.append(eval(n))
c = sh.recvline().decode().split('=')[-1]
C.append(eval(c))
if len(N) >= 17:
M = crt(N,C)
for j in M:
m = gmpy2.iroot(int(j),17)[0]
flag = long_to_bytes(m)
if b"flag" in flag:
print(flag)
break
break