CTF_Notes_0x2
0x01 RSA
1 | A=(((y%x)**5)%(x%y))**2019+y**316+(y+1)/x |
p,q能够分解得到。
最开始还想用z3库来解,但是解不出来。
wp里面的最优解法就是爆破。
exp:
1 | import gmpy2 as gp |
0x02 Feistival
My friend Ridwan is interested into ciphers lately. He sent me the encrypted flag. Can you help me decrypt?
1 | # enc.py |
算法生成的字符串是由两端拼接成的。其中
0x03 Tony Stark Needs Help
The Ten rings have announced a war against Tony Stark and James Rhodes. Ten Rings have deployed many of their soldiers and also launched many missiles. They also gave a threat of launching a nuclear missile. James Rhodes is trying to defend all kind of attack on the city and Tony Stark is looking for the base of Ten Rings to catch the Mandarin. After searching for a while, Tony Stark found the base. But the Mandarin left the base by then. Though Tony couldn't capture Mandarin in the base, but he found a very important letter.
After reading the letter, Tony understood that, he only have 1 hour to save the city from nuclear attack as there was a broadcast from Ten Rings three hours ago. And he also found a encryption programs in the computers of the base.So, now he need a decryption script to stop the nuclear attack. Can you help him to save the city by creating a decryption program?
1 | # encryptor.py |
1 | Hey Actor, |
根据题目,两段密文分别为:
1 | 6G:653 |
密钥是多个中的一个。
1 | a=b'IihsIb_7[^7is<inH][l_^D`Ib_;[n7iu' |
无视x的生成,和分段移位所带来的重叠的结果。但放到加密程序后的结果与密文有出入。具体在:
题目密文:IihsIb_7[7is<inH][l_D`Ib_;[n7iu
反向加密:IihsIb_7[7is<inH][l_D`Ib_;[n7iq
可看到最后一个字符出问题,改成y就可以了。
0x04 Tony Stark Needs Help Again
1 | import base64 |
加密算法过程是先用了一个凯撒,然后HashMap替换,然后是一个很迷惑的加密:
1 | for i in arr1: |
然后再来一个HashMap替换,最后逆序base64。其他步骤都好说,就在这一步加密卡着了。索性把所有可能的情况打印出来,然后一个一个套。
MuHH(AH@H[_G@t'AM_w+&&_K1&L_A&&_TH3_Av3nG
这个是最后的解,套加密算法都是对的,但题目就不给过……无语。
0x05 easypyc
1 | # uncompyle6 version 3.5.0 |
魔改的RC4,需要在RC4解密的基础上,把经过ccccccccc
函数加密的密文逆回去:
1 | for(i =31;i>=1;i--){ |
而后需要得到密钥序列,具体是把密钥流生成算法求出来:
1 | [23,104,57,207,150,242,66,87,81,213,140,172,131,48,106,172,132,173,66,76,58,116,176,222,31,6,52,221,73,137,4,186] |
之后就可以编写 exp 了。
exp:
1 |
|
0x06 RSA & what
简简单单共模,得到:
THIS FLAG IS HIDDEN. CAN YOU FIND IT OUT? DO YOU KNOW BASE64? YoungC THINK YOU ARE NOT THAT FAMILIAR WITH BASE64. Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. The term Base64 originates from a specific MIME content transfer encoding. The particular set of 64 characters chosen to represent the 64 place-values for the base varies between implementations. The general strategy is to choose 64 characters that are both members of a subset common to most encodings, and also printable. This combination leaves the data unlikely to be modified in transit through information systems, such as E-mail, that were traditionally not 8-bit clean.[1] For example, "MIMEs" Base64 implementation uses A8CZ, a8Cz, and 08C9 for the first 62 values. Other variations share this property but differ in the symbols chosen for the last two values; an example is UTF-7.
这里用到了base64隐写。
base64解码:
- 首先把填充字符
=
去掉 - 每个字符查表转换为对应的6位索引,得到一串二进制字符串
- 接着从左到右,每8位一组,多余位丢掉,转为对应的字符
base64隐写原理 base64之所以可以隐藏信息,便是在于在解密过程中,在解码的第3步中,会有部分数据被丢弃(即不会影响解码结果),这些数据正是在编码过程中补的0。也就是说,如果在编码过程中不全用0填充,而是用其他的数据填充,仍然可以正常编码解码,因此这些位置可以用于隐写。
解开隐写的方法就是将这些不影响解码结果的位提取出来组成二进制串(一行 base64 最多有 2 个等号, 也就是有 22 位的可隐写位.),然后转换成ASCII字符串。这就是为什么出base64隐写时会有很多大段 base64 的原因
exp:
1 | #--------base64隐写-------- |
0x07 babyRSA
1 | import sympy |
Q可以直接给出来,P是通过P[9]getprime得到后面的部分,然后while循环-2判断是否为素数得到前面的部分。
exp:
1 | from Crypto_box import * |
0x08 you_raise_me_up
1 | from Crypto.Util.number import * |
离散对数求解,需要用到sympy库。
exp:
1 | from Crypto_box import * |
0x09 坏蛋是雷宾
老牌刺客之王混进了女王的住所。一天,女王得到了一个匿名举报,说她的侍卫里有一个刺客,叫做Rabin,而他的信息就在一份文件里,文件中有附带一个Pk,是523798549,密文是162853095,校验码二进制值是110001,根据说明是放在明文后一起加密的,明文与密文长度相同。加密算法和这位老牌刺客同名。快拯救女王,答案是求得的明文,进行32位md5小写哈希字符串,提交即可。 注意:得到的 flag 请包上 flag{} 提交
Rabin算法是基于RSA的扩展。
生成:
加密:
解密:
根据中国剩余定理求模n的平方根:
exp:
1 | from Crypto_box import * |
分析校验码得到第一个是明文,转10进制再md5就是flag。
0x0a EzRSA
1 | from gmpy2 import lcm , powmod , invert , gcd , mpz |
给出了p-1和q-1的最小公倍数,如何求解呢?
考虑到如下公式:
代入题目就是:
gift位数2045,n位数2048,因此gcd位数为3,也即gcd是[4,8]内的数,这样就方便列举了。
同时要注意到e=54722=27361*2,所以加密要变换一下:
exp:
1 | from Crypto_box import * |
0x0b Polybius
密文:ouauuuoooeeaaiaeauieuooeeiea hint:VGhlIGxlbmd0aCBvZiB0aGlzIHBsYWludGV4dDogMTQ= flag:解出明文后,请加上BJD{}
b64解密hint:The length of this plaintext: 14
考虑到密文有28位,加密方式应为棋盘密码,aeiou是其位置坐标,但aeiou排列顺序位置,所以要列举。
exp:
1 | import itertools |
0x0c d3factor
1 | from Crypto.Util.number import bytes_to_long, getPrime |
题目包含如下几个参数:
参数 | 大小(bit) |
---|---|
p,q | 256bit prime |
N | 512bit |
d1,d2 | 2000bit prime(d1-d2=1000bit) |
e1,e2 | 2000bit |
结合题目,有两个值得注意的地方:
- d1,d2相差1000bit,可能以|d1-d2|过小构成攻击。
- N的产生方式:
,不同于常见的p*q,也可能构成攻击。
所以可以归纳出两个关键词:|p1-p2| small,n p r q
通过之前归纳的关键词,能查到很多有关
A STUDY ON CRYPT ANALYSIS OF RSA,Chapter 4: RSA with modulus
论文中提到的第一种
对等式
这种攻击在题目情景下是不能成立的,因为:
d1与d2是RSA下两个私钥,且满足
引理:
设
的所有解
这种攻击方式在此题情景下成立,因为
攻击思想概括:
由
假设方程中
计算
攻击流程:
求解模
多项式 。sagemath中使用small_roots求解多项式小值根,以及因子分解问题。其中要设置三个量:X,表示求解根的上界;beta、epsilon,可以利用论文中
的求法得到(其实随便写一个就行)。x=|d1-d2|,代入
求g求p,q,进而用常规rsa求解
exp:
1 | from Crypto_box import * |
# 0x0d babyrsa
1 | p4=146068806215073497344459876631371603884129554507314987227041386431864296983800292232765852493230146632246223391161616274352995602128509562953556195654254929572680238155614318159006433172894208760309766144817665852858474274746295434459658946786114485553768622540321693696983334739989582184316792317376817587284066141025953893816735983622448994863347051427279673308801466174898201800602688359956097373676655607179834345973775227535147398518523539179261883968140504230643073698857288314127486345168652339309386405706576632120711116391426300160476076254612138216623537070845645803721685414583459545099925250474009703135469241079408739336592005949980987466671054020054633554508243871664072158338203090563533576053886607251476483441992750608537110739543678599105838456537686029895264928334606913181627024815548789841726411333636163152202116487198575625907392074866811580053962217284776220330628233642351622897902940633662074194963147661868086182955886918339487179905557899816215131118989868243555958033477834658657082003718410617182774845820310639577794302769424451100567749840744304334325501306470124397022077759031911677326433654909824518845224227308515695216456907499080502091628962571645468099748573164070147303131348996440422701533681 |
前面一个低解密指数爆破,一个简单的factor顺利解出,最后一步卡住了:
这道题最大的难点在于
exp:
1 | c=[gp.powmod(c1,s1,q1),gp.powmod(c2,s2,q2)] |
0x0e 认清形势,建立信心
1 | from Crypto.Util.number import * |
需要用到两个等式求解
exp:
1 | from Crypto_box import * |
0x0f ezRSA
1 | from Crypto.Util.number import getStrongPrime |
复原前面的bits
观察可得到:pq前124bit是相同的。并且由于:
这一步的主要思想是:pq的900~300位由于异或了600个1,故其每一位都是相反的,也即:p的第i位是1,则q的第i位是0;反之亦然。
可以证明:如果相同位的1与0互换,其乘积会比原先的n大。
1 | import gmpy2 |
简单copper即可复原剩下的 bits
1 | from Crypto.Util.number import * |