buu(前三页第三弹) RSA习题与相关知识总结

  首先先描述一下题目:题目一共有四行数据,前两行数据中每行数据包含两个元素,两行数据中第一个元素都相同,第二个元素不同由元素相同可以想到共模攻击由此可以得出: 各字母都分析出来了,那么直接上解题脚本即可: gmpy2.gcdext(a,b) : 【扩展欧几里得算法的内置函数】

  Return a 3-element tuple (g,s,t) such that

  g == gcd(a,b) and g == as + bt

  【返回一个 3 元素元组 (g,s,t),使得 g == gcd(a,b) 和 g == as + bt】

  最后得到flag{r3a_C0mmoN_moD@_4ttack} 天知道这题我看了多久,我一直没看到题目给的 e,我说怎么大家就用 n,c1,c2 就能求出来了,所以说信息一定要看全,一定要划到最后面 和上一题好像啊!那话不多说直接套用以上解题脚本运行后还是发现有一些不一样的,因为直接套用得不到flag,哪里出问题了?打印libnum.n2s(int(m))和m的结果: 大佬们的见解:

  在这里插入图片描述

  在这里插入图片描述显然第一位所说 “ m的开头为1,而这样是不可能转换为可见字节 ”,这一说法有点问题。上面一题m开头就为1,得到了flag,m开头为1,所以一串数字开头为1是可以转字节的,所以大家别被误导了既然不能转字节,那么就试试转ascii码吧,转化代码如下: 最终得到flag{whenwethinkitispossible} 至今为止数字串转flag有2种方法(一种不行就试另一种):

  1.转字节

  2.转ascii码(在m长度不大的情况下,就如本题,既然能转ascii码,那么大胆猜测还有一种可能是能按照26个英文字母进行转换,前提也是m长度不大)这里简单说一下上面提到的16进制转字符串,十六进制数的一个基本特点:它由十六个数码:数字0~9加上字母A-F组成,所以说纯数字转字符串一般不考虑16进制转化 (注:此题有两种解法,一种是直接用在线网站分解n ,得到p,q,特别简单且快速,比较暴力。但,我喜欢!、

  另一种便是一步步分析下来,求p,q ,以下讲解如何分析得到flag)

  首先这里遇到了两个没见过的函数 ----> Fraction() 和 Derivative() Fraction(a,b) 相当于 a / b (a 除 b)

  Derivative(a,b),前一个参数表示求导的内容,后一个参数表示求导的主体

  Derivative(arctan § ,p)的意思是以p为主体对 arctan§ 求导,得到1/(1 + p^2),同理Derivative(arth(q),q) 得到 1/(1 - q^2)

  最后

  Fraction(1,Derivative(arctanc ( p ) ,p)) = 1 + p^2,Fraction(1,Derivative(arth(q),q) = 1 - q^2

  得到关系式: z = p^2 +q^2,又 n = p * q,进一步得到关系式 : (p + q) ^ 2 = z + 2n

  (p - q) ^ 2 = z - 2n

  用代码解出p,q

  得到flag{Advanced_mathematics_is_too_hard!!!} 又了解了两个新函数: Fraction(a,b) 相当于 a / b (a 除 b)

  Derivative(a,b),前一个参数表示求导的内容,后一个参数表示求导的主体

  对于有n的,多尝试能否暴力分解得p,q (先告知:此题有简便方法,即 直接将 P_n 和 Q_n 进行分解,得到两组 p,q(即用线上网站将n 分解得到p,q)将p,q带入生成factor2的代码中,即可得到 P,Q,之后就是常规的rsa解密了。以下是更详细深入的解析)

  这题与 buu [GWCTF 2019]BabyRSA 1 比较像,分四个模块,第一个模块告诉我们生成素数的方法(对后面的分析没什么实质性关系)第二个模块即生成 P 的过程(gen_p): 告诉了我们 n = p * q , phi = (p-1) * (q-1) = p * q - (p+q) + 1 = n - (p+q) + 1

  ==>n = p * q , phi = n - (p+q) + 1

  ==>p + q = n - phi + 1

  ==>(p - q)^2 = (p+q)^2 - 4 * n

  ==>p - q = [(p-q)^2] ^0.5

  ==>p = [(p + q) + (p - q)] // 2

  ==>q = (p + q) - p

  由上过程便可得出p,q,从而求出factor2,注意 p<q,若求出来的不符合则调换下位置求P代码: 第三个模块即生成 Q 的过程(gen_q),和上面生成 P 的过程很像, 不过此时已知的是 n = p * q , e * d = 1 mod phi

  ==>e * d - 1 = k * phi = k * (p - 1) * (q-1)

  ==>(e * d - 1) // p * q < (e * d - 1) // [p * q - (p + q) + 1] = k

  求 Q 代码如下: 第四个模块则是告诉我们关于rsa的基础运算过程,想必这个大家都清楚,也不过多赘述了以下是完整代码: 最后flag{Ju3t_@_31mp13_que3t10n} 总之通过这题对rsa又有了更深的理解,对某些的模块的运用也更加熟练看大佬的wp,原来 k 还能这么求,真的想不到k的详细解析: 这里是引不等式两边的分母一个pq,一个pq-(p+q)+1相差并不大,并且还是整除,所以估计(ed-1)//pq和(ed-1)//(pq-(p+q)+1)差值不到1用

  在这里插入图片描述

  然后这里两次整除后,后面小数部分应该都省略掉了

  在这里插入图片描述

  打开的 rsa_16m 文件 :

  在这里插入图片描述

  在这里插入图片描述

  在这里插入图片描述

  (在此我只想说神人才找得到 c 的位置) ,这位置是真的难找啊

  首先打开 description.md 文件,得到:在这里插入图片描述

  翻译下来: 当您需要真正安全的通信时,您可以使用带有 4096 位密钥的 RSA。

  我想要真正非常安全的通信来传输核发射代码(是的,物联网无处不在),所以我使用带有16777216位密钥的RSA。俄罗斯人肯定无法考虑这一点!

  文件md5 : 1049a0c83a2e34760363b4ad9778753f

  从所有以上的题目描述可以得知的已知条件有:n,c,e已知,且 n,c 特别大,e = 0x10001 = 65537又 c = m^e mod n

  所以当 m^e 严重小于 n 的时候,c 很可能就是 m^e,所以对 c 开 e 次方即可得到 m

  以下是解题代码(将 rsa_16m 文件 和 代码文件 放在同一个文件夹中): 得到flag{(I)NSA_W0uld_bE_pr0uD} (在此我只想说神人才找得到 C 的位置) 这位置是真的难找啊,找不到也许就放弃了若 n ,c 特别特别大,考虑以上方法(又了解了一种rsa题型) 在这里插入图片描述

  题目四个文件,分别如下:

  rsa.py

  HUB1

  HUB2

  README.txt

  素数生成算法太麻烦了,有没有取巧的方法呢?

  诶,这里好像有个不错的想法哟。

  看起来节约了不少时间呢,嘿嘿嘿……

  顺便问问,应该大家都知道base64吧,用来编码还是很方便的呢!

  从代码中可以知道,HUB文件中的数值分别对应:N,e,和6个密文c,其中两组文件中N相同,e,c不同,由此可以想到共模攻击 共模攻击知识回顾

  共模攻击,也称同模攻击

  共模攻击利用的大前提是,RSA体系在生成密钥的过程中使用了相同的模数n

  在CTF题目中,就是 同一明文,同一n,不同e,进行加密

  m,n相同;e,c不同,且e1和e2互质

  常规题: (c1 ^ s1 * c2 ^ s2)%n == m , gcd(e1,e2) == 1

  变形题:gcd(e1,e2) != 1

  假设 gcd(e1,e2) == x

  (c1 ^ s1 * c2 ^ s2)%n == m1^x%n = m

  m = m1^x%n

  m = m1^x + kn

  由此我们可以想到 buu RSAROLL(滚动拼接)这一题,都是多组c,每组求出后拼接到一起由此直接上脚本: 得到一大串

  MKhDOQ==

  Zm9y

  dGhl

  Zmlyc3Q=

  NjI=

  dmFsdWVzLg==

  …(此处省略)

  看起来很像 base64,但又不是寻常的 base64,看了大佬的wp,知道是用 base64隐写术 解密

  base64隐写术:

  在这里插入图片描述

  脚本:

  得到flag{7c86d8f7d6de33a87f7f9d6b005ce640} 在写代码过程中,发现 long_to_bytes(m) 与 binascii.unhexlify(hex(m)[2:]).decode() 有些不同 long_to_bytes(m):在这里插入图片描述 2.binascii.unhexlify(hex(m)[2:]).decode() :在这里插入图片描述

  二者所得结果排版不同,对这题来说用 binascii.unhexlify(hex(m)[2:]).decode() 更合适,因为更适合进行分隔以后遇到解出来得到类似以上的结果的题目,考虑隐写术 给了4个文件

  在这里插入图片描述

  首先这种出现pubkey的题都很熟悉,那么可以用惯用的套路来求解其中的n,e第一步:在kali中分别使用命令(也可用在线解公钥网站得到n,e): openssl rsa -pubin -text -modulus -in warmup -in pubkey1.pem

  openssl rsa -pubin -text -modulus -in warmup -in pubkey2.pem

  分别得到:在这里插入图片描述

  在这里插入图片描述

  由此可以得出:e不同,n相同,想到了共模攻击

  e1 = 2333

  e2 = 23333

  n = 0x75A8B8AA2AD2950E9AED4BE34618DFBEABB8CBA832685CC94F45173330100624846CCF90F3C2DB75BA5AF4B39CAEF1175AB9F898794EAC6082A4F766F7CB280B16F6980B38DDA811761324D619513B3CBE65877ACF51FC70405A8347C121207E71F8E6FCAE39647ED2231D306DD53849257BC306E997A502867012249D1691F5DC11D6AF06539F3F808939343DDE09301A761AE12C1C969076C502BC5A971E10ABCB366547BC94373F37A57DDC43858DB29BAAAAAD0E6867885EA3757403008C164E9C7AFA39B3C65089A151DDD8C06C64271086F9255ADB8ACF82182F8FA252930A187961635BC2A85C761330F85C896314B3FDAE4EFEF7E0A8C93B8854BFC3

  然而共模攻击还要知道密文c的值,文件中myflag便是对应的密文(这种应该可以说是约定俗成了:公钥对应n和e ,私钥对应n和d ,flag对应密文c或明文m)在rsa中对于类似base64编码的密文,我们可以用以下方式进行解码: 由此可写出完整代码: 得到 flag{23re_SDxF_y78hu_5rFgS} 在kali中打开公钥或私钥文件用以下命令: openssl rsa -pubin -text -modulus -in warmup -in pubkey1.pem

  RSA中遇到类似base46的字符串用以下代码进行转码: c1 = bytes_to_long(base64.b64decode(f1))

  给了两个文件:

  在这里插入图片描述

  public.key:

  flag0.enc(用记事本打开):

  首先利用 public.key 解出 n, e 也可利用在线解公钥网站得出n,e在这里插入图片描述此处密文c的求解有些特殊(并不是base64相关解码),此种情况记住即可以下为解题代码: 在这里插入图片描述

  两个文件,都用记事本打开,记住用记事本打开

  pub.key:

  flag.enc:

  显然第一个文件即时普通的公钥(n,e)解密文件,第二个文件是密文c解密文件,与

  buu [AFCTF2018]可怜的RSA 1 和 buu [HDCTF2019]together 1 很像公钥解密按套路来,可以用线上工具,也可以用脚本

  1.线上公钥解析网站:

  在这里插入图片描述 2.代码解密(将代码文件和 pub.key文件 放同一个文件夹):

  得到: n = 86934482296048119190666062003494800588905656017203025617216654058378322103517

  e = 65537

  n 分解得 p,q: p = 285960468890451637935629440372639283459

  q = 304008741604601924494328155975272418463

  最终便是求密文了,遇到此种一段乱码的直接用python脚本(记住就好,不必深究,挺简单的,记住将代码文件和 flag.enc文件 放同一个文件夹): 最终得到密文c: c = 29666689760194689065394649908301285751747553295673979512822807815563732622178

  自此,所有未知数都已求出,完整代码如下: 得到 flag{decrypt_256} 至今为止已知m数值转flag有2种方法(一种不行就试另一种):

  1.转字节

  2.转ascii码(在m长度不大的情况下,就如本题,既然能转ascii码,那么大胆猜测还有一种可能是能按照26个英文字母进行转换,前提也是m长度不大)

  这里简单说一下16进制转字符串,十六进制数的一个基本特点:它由十六个数码:数字0~9加上字母A-F组成,所以说纯数字转字符串一般不考虑16进制转化

  新收获的两个函数:

  Fraction(a,b) 相当于 a / b (a 除 b)

  Derivative(a,b),前一个参数表示求导的内容,后一个参数表示求导的主体

  < a >

  已知 n , phi 如何求p,q(注:n = p * q , phi = (p-1) * (q-1)):

  两个方程,两个未知数,很容易解:

  告诉了我们 n = p * q , phi = (p-1) * (q-1) = p * q - (p+q) + 1 = n - (p+q) + 1

  ==>n = p * q , phi = n - (p+q) + 1

  ==>p + q = n - phi + 1

  ==>(p - q)^2 = (p+q)^2 - 4 * n

  ==>p - q = [(p-q)^2] ^0.5

  ==>p = [(p + q) + (p - q)] // 2

  ==>q = (p + q) - p

  < b >

  已知 n,e * d ,如何求 p,q(注:n = p * q,e * d = 1 mod phi):

  此时已知的是 n = p * q , e * d = 1 mod phi,那么我们便将已知转化为 n,phi

  ==>e * d - 1 = k * phi = k * (p - 1) * (q-1)

  ==> k = (e * d - 1) // [p * q - (p + q) + 1] > (e * d - 1) // p * q

  k = ((e * d-1) // n)+1

  phi = (e * d- 1) // k

  k的详细解析:

  这里不等式两边的分母一个pq,一个pq-(p+q)+1相差并不大,并且还是整除,所以估计(ed-1)//pq和(ed-1)//(pq-(p+q)+1)差值不到1用:

  k = ((e * d-1) // n)+1

  phi = (e * d- 1) // k

  然后这里两次整除后,后面小数部分应该都省略掉了

  对于求公钥私钥的套路我们已了解,那么接下来我们来总结此种题型下求密文的方法(至今知道的有三种): 1.密文出现一段乱码的用以下代码打开:

  2.密文出现一串类似base64的字符串的有一下两种:

  (1)第一种:

  (2)第二种(此种情况可在使用第一种方式下得不到答案的情况下使用,很特殊的一种方式):