记录上半年打的新生赛,一场记忆犹新的crypto入门赛
Crypto
Sign1n_Revenge
1 | from Crypto.Util.number import * |
crypto部分的签到题啦,简单分析一下题目的意思,首先是对几个函数进行分析,先把输出的结果加到514位,然后将每一位作一个加i加1再模10的操作,再将前两位去掉,将剩下的512位作倒置,然后输出
这样的话,我们对其进行逆向的分析,就可以得到原先的二进制数,分析的代码如下所示
1 |
|
然后解出我们的二进制代码,我们将后面的0都去掉,剩下前面的
1 | 11001100110110001100001011001110111101100111000001110000011010100110111011000010110011001100100001110000010110101100001001110010110010101100101001011010011010001100101001101110110010100101101001110000011000100110110001100000010110100110111011001100011000101100010001110000110011001100110001100110011010000110101001100100110010001111101 |
我们还需要在前面补充两位的二进制数,再将其bytes_to_long即可
经过尝试,我们补充两个0,最后获得了flag
1 | flag{8857afd8-a9ee-4e7e-8160-7f1b8ff3452d} |
Sign1n[签到]
跟上面一题的思路是一样的,得到flag即可
1 | flag{8857afd8-a9ee-4e7e-8160-7f1b8ff3452d} |
happy_to_solve1
1 | from Crypto.Util.number import * |
这题主要是一个happyprime函数,生成两个512位的素数,有一定的联系,这题与之前做的一题几乎一模一样,直接套用脚本即可
1 | import gmpy2 |
然后我们就可以得到flag
1 | XYCTF{3f22f4efe3bbbc71bbcc999a0a622a1a23303cdc} |
happy_to_solve2
1 | import random |
这题的两个素数较大,且不太能进行分解,于是我们观察生成两个素数的函数,发现第一个素数由123组成,第二个素数由567组成,于是想到根据乘积末尾部分来反推两个素数,由于存在多解性,我们利用dfs来求解
1 | m="697906506747097082736076931509594586899561519277373830451275402914416296858960649459482027106166486723487162428522597262774248272216088755005277069446993003521270487750989061229071167729138628583207229945902389632065500739730301375338674342457656803764567184544685006193130563116558641331897204457729877920989968662546183628637193220770495938729301979912328865798266631957128761871326655572836258178871966196973138373358029531478246243442559418904559585334351259080578222274926069834941166567112522869638854253933559832822899069320370733424453856240903784235604251466010104012061821038897933884352804297256364409157501116832788696434711523621632436970698827611375698724661553712549209133526623456888111161142213830821361143023186927163314212097199831985368310770663850851571934739809387798422381702174820982531508641022827776262236373967579266271031713520262606203067411268482553539580686495739014567368858613520107678565628269250835478345171330669316220473129104495659093134763261751546990704365966783697780787341963138501" |
求解出来由很多组解,我们再去对照前面的位数,最后获得了两个素数
然后我们再使用RSA解密即可,求出逆元,求出d,在正向求解即可
1 | from gmpy2 import * |
解出flag
1 | XYCTF{7f4b2241951976ce5ef6df44503209059997e5085d1bc21f6bef4d9effb29fd0} |
happy_to_solve3
1 | import gmpy2 |
论文题
我们还是使用我们的连分数攻击去完成,将下面的底换一下就可以了
1 | from Crypto.Util.number import * |
得到结果:
1 | 202935305174706906986376186864051444100197589482194720650385604617995167023220940138899902073948844285283834058445151666398192104922822110762965750590312021079147170573038600118139119881722125346545331027913695559130179278058419339157557267195396326664433859683010193688491694572425231599139974726246205888138 |
然后我们再一一检验就可以了,找到第三个是符合条件的
1 | N = 262520792590557046276663232446026434827811478251833823563978322470880473096166170973396967071440576532100045206129176936699321058518888771220060450723297988984995658582283884954240129867538637146924315603797818982078845855992582229939200744016516540207525916858674450616913948112117516831530578235916528257187 |
输出我们的flag
1 | XYCTF{68f1880cdafd99fbf9a156946cb39dd86477886f1d115636e149e12c16f99af0} |
factor1
1 | import gmpy2 |
这道题刚开始一直在考虑求e的逆元那一步,感觉有点问题,后来我用了低指数加密破解
简单来说就是将逆元后面的那一串式子看成n的3次,然后对e和n的三次做连分数攻击就可以了
1 | import gmpy2 |
连分数破解完之后,我们得到了很多组可能的结果,我们一组一组进行验证,最后求出p1,p2,q1,q2,然后就可以解出答案了
1 | import gmpy2 |
运行程序,得到flag
1 | XYCTF{a83211a70e18145a59671c08ddc67ba4} |
factor3
1 | from Crypto.Util.number import * |
这题跟factor1是一样的,先是用wiener attack,再穷举求出d就可以了,再作异或操作即得到flag
1 | import gmpy2 |
解出所有的可能
1 | 494518390582436635999115147756676313570637682518235195828939117782099618734167908630788943568232122157772909140885391963441876427590731524706959546524212914108888799081844320513851526790475333924396837458796755678072486028072639014677580265244176441153444956871730684233063789931539669072735599696830757690822185323538738397827461580678488181113667710378657058297572328491762536595872579603698945272140918157163640403488075948987156585480146162739943419183496337465468187233821931312507662218106713861638334075899266373256620752680354704533272722692596941861606161634082613228896420520465402725359166156632884432690715903666803067996854084671477445131853993177110154928274312496230096270510089973592664248613332000290545537840595645944390047611474888693558676781309912289044962293014118087259307560444929227407113819165713213046898243995956550944640168932947118400215917515277554126694376415569909534496134700668701465649938 |
然后一个一个试,求出逆元d,d需要满足是320位二进制,即93位十进制
1 | d=2109723047551375043305134722302342646596769444055829710618826161103186815230448177424794300667429 |
然后就进行d的平方操作,再和c作异或就可以了,得到flag
1 | XYCTF{I_love_to_read_the_crypto_paper_and_try_to_ak_them} |
babyRSAMAX
1 | from Crypto.Util.number import * |
先是利用生成n的漏洞,破解出p和q
1 | p=236438400477521597922950445153796265199072404577183190953114805170522875904551780358338769440558816351105253794964040981919231484098097671084895302287425479 |
然后我们就可以解出e了,利用求逆元的方式,求出e
1 | from gmpy2 import * |
求解出
1 | b'XYCTF{e==4096}' |
说明我们已经求解出了e的值为4096
然后再进一步,但是我们发现,下一个mod似乎没有整数解,因为e和phi不互素(具体参考e与phi不互素的情况_e和phi不互素-CSDN博客)
我们使用有限域上的解的方式,用sage环境分别解出p和q的有限域,然后再用CRT把两个解合起来,查找是否存在字符XYCTF即可
1 | [(236438400477521597922950445153796265199072404577183190953114805170522875904551780358338769404214275971858584747720119200208117068403781208566503489403215434, 1), (36344540379246669047243921781711114415694316462518391812884210045, 1)] |
代码:
1 | res1=[(236438400477521597922950445153796265199072404577183190953114805170522875904551780358338769404214275971858584747720119200208117068403781208566503489403215434, 1), (36344540379246669047243921781711114415694316462518391812884210045, 1)] |
输出结果
1 | XYCTF{Rabin_is_so_biggggg!} |
Complex_dlp
1 | from Crypto.Util.number import * |
这道题根据hint,首先考虑将复数域转化成实数域,方法就是将两边同时乘上对应的共轭复数,这样两边就变成整数了
1 | p =1127236854942215744482170859284245684922507818478439319428888584898927520579579027 |
然后就很简单了,用sage求一下离散对数,在转一下long_to_bytes就搞定了
求出flag是
1 | XYCTF{___c0mp13x_d1p_15_3@5y_f0r_y0u___} |
反方向的密码 相思
1 | from Crypto.Util.number import * |
这题的主要思路是,利用coppersmith来进行高低位的攻击,因为我们知道,flag的前几位必然是XYCTF{,所以相当于前面的m的位数已经知道了,包括最后的位数,也是可以确定的,所以我们就直接猜测flag的位数,然后逐一验证,看是否有正确的m。
验算到38时终于出现了答案,说明flag的长度是38
对应的m的值为58964190787951927773278389967057377362495121527440001979648729026891046689
我们将其long_to_bytes即可,得到最后的flag
1 | XYCTF{!__d3ng__hu0__1@n__3h@n__Chu__!} |
fakeRSA
1 | from Crypto.Util.number import * |
这题是用jordan型正定矩阵来解决(根据hint)
n*n
型来进行计算,将原jordan矩阵填充到3*3
型
我们先求出第二组和第三组解,根据前面的公式就可以得出来
1 | b2 = vector(GF(p),[1431995965813617415860695748430644570118959991271395110995534704629241309597572003500157255135707,1011565891130611736600822618382801465506651972373410962205810570075870804325974377971089090196019,784497518859893244278116222363814433595961164446277297084989532659832474887622082585456138030246]) |
在解出前三组解之后,我们就可以列出最后的表达式了
1 | a = matrix(GF(p), [a0, a1, a2]) |
这样就解出了最后的结果
1 | XYCTF{y0u_finally_f0und_t3h_s3cr3ts!!} |
x0r
1 | from Crypto.Cipher import AES |
这题的话就是一个AES加密体制,AES加密的特点就是对称加密,就是说每次加密,明文都是一样的,所以我们可以通过明文去破解,输出的是128位密码,但是我们测试iv = os.urandom(16)
发现生成的iv是32位的,所以我们将前32位当成iv输入,后面的96位当作message输入,这样就能解出公钥
公钥是:58594354467b31663363626332312d663735362d346132382d613030372d6436653838633735653631667d0a04040404
然后我们对其进行逆向解密即可,获得flag
1 | XYCTF{1f3cbc21-f756-4a28-a007-d6e88c75e61f} |
重生之我要当oi爷(未解决)
1 | def f(a, b, p): |
Complex_rsa
1 | from Crypto.Util.number import * |
首先就是根据我们给出的条件,将我们的p和q都计算出来,这个不难
然后根据我们在复数域上的欧拉函数,我们可以得到:
但是我们可以升次,通过升次去找到我们可能的解
1 | from Crypto.Util.number import * |
这样就可以找出我们所有可能的解
然后用我们的CRT进行遍历,找出带flag头的就可以了
1 | from Crypto.Util.number import * |
这样就得到了我们的flag
1 | flag{Complex_is_so_fun_and_I_think_you_know_Sylvester!} |
Random_rr(未解决)
1 | from Crypto.Util.number import * |
反方向的密码 情难(未解决)
1 | import hashlib |
easy_ecc
1 | from Crypto.Util.number import * |
这题的话,我们首先将椭圆曲线转化成标准曲线,转化脚本在学习资料中已经给出。转完之后,我们尝试用hellman进行解密,发现报错,提示该点在奇异曲线上,于是我们选用奇异曲线的解密脚本来进行攻击,脚本如下所示。(实际上并不一定需要转化成标准曲线)
1 | A=1098066776930223927329092382214459309226361965213 |
使用sage,这样就解出了我们的sercet值,再带回到原式中,获得最后的flag
1 | XYCTF{ec9a6e17537e81b7f593f65f7e2ca5d575e6b34c504c24e4afb40c1e9dc4be0d} |
LCG_and_HNP(未解决)
1 | from Crypto.Util.number import * |
铜匠
1 | from Crypto.Util.number import * |
这题就是一个coppersmith练习,只不过第一个形式貌似是对d的高位攻击,平时没有怎么见过
1 | from Crypto.Util.number import * |
这样就可以解出来了
1 | XYCTF{___y0u_k0nW_h0w_t0_s01v3_c0pP3r_th15_15_y0r_fl@9_hahahaha!!!___} |
new_LCG(未解决)
1 | from Crypto.Util.number import * |
Reverse
聪明的信使
一眼古典密码,直接打开ida,按f5,对字符串进行解密就可以了
1 | flag{Y0u_KnOw_Crypt0_14_v3ry_Imp0rt@nt!} |
喵喵喵的flag碎了一地
在程序开头处找到第一处flag,说第二处flag在function中,我们很容易找到,然后根据提示,就可以知道第三处跟function互相引用(xref)了,所以找到对应的function718,是在一个数字下,读出flag即可
1 | XYCTF{My_fl@g_h4s_br0ken_4parT_Bu7_Y0u_c@n_f1x_1t!} |
Misc
熊博士
1 | CBXGU{ORF_BV_NVR_BLF_CRZL_QQ} |
看出来是古典加密,根据前五位XYCTF就可以推断出加密方式了,是两个位置上的ascii码加起来永远不变,容易得出flag
1 | XYCTF{liu_ye_mei_you_xiao_jj} |
签到
第一题!直接发给公众号获得flag
1 | XYCTF{WELCOME_TO_XYCTF} |
EZ_Base1024*2
base2048在线解密:
Encode and Decode Base2048 Online Tool
得出结果
1 | XYCTF{84ca3a6e-3508-4e34-a5e0-7d0f03084181} |
真>签到
有手就会,把附件放进01编辑器中,读取前面的flag就可以了
读取flag
1 | XYCTF{59bd0e77d13c_1406b23219e_f91cf3a_153e8ea4_77508ba} |
Osint1
这题给了一个滨海新区的照片,本来因为是天津市的,但是不是,后来在百度识图在一个网址上找到了用户的ip为江苏,再进一步查询发现该地点在江苏省南通市海安区,在滨海东路上,外面的海是黄海。
得到flag:
1 | xyctf{江苏省|南通市|滨海东路|黄海} |