挺久没有做过CTF了,明天就要打比赛了,临时抱佛脚,撸两道rsa,找找手感。

公钥文件泄露

题目给了两个文件:pub.key和flag.enc:

​ pub.key

-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+
/AvKr1rzQczdAgMBAAE=
-----END PUBLIC KEY-----

​ flag.enc(乱码)

ZF:9Mw 骓骼)P恂黮?沕悴[嘟??

解题思路挺多的,这个没啥好说的(虽然因为很久没有做过,卡了很久)

  1. 只想简单解题的话,直接找个在线解密的解密的网站(我就不提供了,自己找吧),然后把这两个文件放上去解密就行了。

  2. 稍微复杂点的化,就是用openssl可以查看到公钥(n,e),大数分解n,得到p,q,然后写个python脚本

    openssl rsa -pubin -in pub.key -text
    

    写个脚本,将上面的modulus里的的字符做个分割,组成16进制数。

    from rsa import PublicKey, transform, core, common
    import rsa
    import gmpy2"""第一种方法"""temp = []
    temp = hex("00:aa:08".split(':'))
    n = ''
    for i in temp:n += i
    n = eval(n)
    print(n)
    # 将n进行大数分解,得到p,q
    p = 285960468890451637935629440372639283459
    q = 304008741604601924494328155975272418463
    e = 65537
    phi = (p-1)*(q-1)  # 欧拉函数
    d = gmpy2.invert(e,phi) #计算模逆元d
    key = rsa.PrivateKey(n,e,int(d),p,q)   # 有了n,e,d,p,q之后 使用rsa模块生成私钥
    with open('./flag.enc','rb+') as f:f = f.read()print(rsa.decrypt(f,key))  # 解密文件""" 第二中方法:直接使用rsa模块去查看n,e """
    whit open("./pub.key","rb+") as k, open('./flag.enc','rb+') as f:k = k.read()public_key = PublicKey.load_pkcs1_openssl_pem(k)   #通过rsa模块的内容去读取公钥的信息print(public_key)    # 这里会输出一个 n 和 e 的元组# 将n进行大数分解,得到p,qp = 285960468890451637935629440372639283459q = 304008741604601924494328155975272418463e = 65537key = rsa.PrivateKey(n, e, int(d), p, q)f = f.read()print(rsa.decrypt(f,key))
    """
    # 在使用第二种方法的是后,其实是有个坑的。因为我自己很久没有做rsa了。
    # 很多东西都要重新开始学,这个脚本最初也是照着网上的脚本写的(网上的脚本贴贴在下面)
    # 他用的是core.decrypt_int()方法去解密的。这没有什么问题,只是需要做个数据格式转换。
    # 但是 PublicKey.load_pkcs1(PUBLIC_KEY) 这个地方就有坑了。
    # rsa使用的密钥文件有两种格式:
    # 第一种: -----BEGIN PUBLIC KEY-----.........-----END PUBLIC KEY-----
    # 第二中-----BEGIN RSA PUBLIC KEY-----.........-----END RSA PUBLIC KEY-----
    # PublicKey.load_pkcs1()方法都的是第二种密钥格式
    # PublicKey.load_pkcs1_openssl_pem() 方法的的是第一种密钥格式
    # 而且:
    #
    # 两种方法返回的数据是不同的!
    # 两种方法返回的数据是不同的!
    # 两种方法返回的数据是不同的!
    #
    # 重要的事情说三遍(你细品我现在的心情)
    #
    """
    

    脚本在这里摘自 作者:窗户

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    import sys
    #rsa
    from rsa import PublicKey, common, transform, core
    def f(cipher, PUBLIC_KEY):public_key = PublicKey.load_pkcs1(PUBLIC_KEY)encrypted = transform.bytes2int(cipher)decrypted = core.decrypt_int(encrypted, public_key.e, public_key.n)text = transform.int2bytes(decrypted) if len(text) > 0 and text[0] == '\x01':pos = text.find('\x00')if pos > 0:return text[pos+1:]else:return None
    fn = sys.stdin.readline()[:-1]
    public_key = sys.stdin.readline()[:-1]
    x = f(open(fn).read(), open(public_key).read())
    print x
    

Baby_RSA(我也不知道应该算什么分类)

题目直接给了一个加密脚本。或不多说,先上脚本:(原脚本里面没有任何注释,大部分的东西都在注释里了)

## 看着上面一堆的导入库,然后用到的却不多,头秃import sympy  # 这个是解题的核心库,pip装一下就好了
import random
from gmpy2 import gcd, invert   # gmpy2,没啥好说的,rsa加解密的核心库
from Crypto.Util.number import getPrime, isPrime, getRandomNBitInteger, bytes_to_long, long_to_bytes
# Crypto 这个库有点恶心人。网上大部分教程都是直接 pip install pycryptodemo 完事了
# 然后你会发现,屁,照样报错,解决办法是:
# 你去python库安装的目录的Python38\Lib\site-packages
# (找不到的话CMD,where python,就能去到python的根目录里)
# 把 crypto 目录改成 Crypto 就能用了
# 原因我也不知道,还没有去查过库
from z3 import *flag = b"nsfocus{xxxx}"      # 这个flag的样式是很重要(记号1)
base = 65537# 这个函数全程没有用到过,我不知道他是干嘛用的,迷惑我们的?迷茫
def GCD(A):B = 1for i in range(1, len(A)):B = gcd(A[i-1], A[i])return B# 取 p 的函数,挺有意思的
def gen_p():P = [0 for i in range(16)]# 获取了一个随机的质数赋给 P[0] ,而后的每个个值都是前一个质数的下一个质素P[0] = getPrime(128)for i in range(1, 17):             # 做题的的时候眼抽了,没看到这里重新更新了P[]的大小P[i] = sympy.nextprime(P[i-1])  # 还很蒙蔽的说下面循环给17不是超界了# sympy.nextprime() 获取参数的下一个质数# 我很自然的想到了 获取前一个质数方法,然后发现真的有,这是这个题目的解题核心print("P_p :", P[9]) ##### 注意 这个P[9],这样我们就能把整个P[]都给不全了n = 1for i in range(17):n *= P[i]p = getPrime(1024)factor = pow(p, base, n)# 看到这里,有没有发现点什么?# 没错,就是在这个地方做了 rsa加密,加密了p。一个简单的欧拉函数(phi)变形的加密# 数学解题思路在下面print("P_factor :", factor)##### 注意 这里返回的是 p 的下一个质数return sympy.nextprime(p)   ##### 注意 这里返回的是 p 的下一个质数##### 注意 这里返回的是 p 的下一个质数##### 你没想错,我又踩坑了
# 取 Q 的函数,这个就真的有意思了。
def gen_q():sub_Q = getPrime(1024)Q_1 = getPrime(1024)Q_2 = getPrime(1024)# 上面去了三个质数,没啥好说的,下面的这个表达式#做个记号,后面要用(记号2)Q = sub_Q ** Q_2 % Q_1     ##### 没错就是这里,整个题目最精妙的地方  # 下面的这些都没啥好说的print("Q_1: ", Q_1)print("Q_2: ", Q_2)print("sub_Q: ", sub_Q)return sympy.nextprime(Q)      # 这个地方返回的也是 Q 的下一个 质数if __name__ == "__main__":_E = base_P = gen_p()_Q = gen_q()# 这个地方是用来保证 _E 和 phi(欧拉函数)互质用的(方便求d)assert (gcd(E, (_P - 1) * (_Q - 1)) == 1)M = bytes_to_long(flag)   # 做了个数据类型转换,方便加密# 最终的加密_C = pow(M, _E, P * Q)              ### 这个地方小坑, P 是 _P, Q 是 _Q### 我当时傻乎乎以为是上面的 return 里面的p和qprint("Ciphertext = ", _C)# 下面是一大串数据,看看就好了
'''
P_p : 206027926847308612719677572554991143421
P_factor : 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839
Q_1:  103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521
Q_2:  151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743
sub_Q:  168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651
Ciphertext =  3456235890998996195610328576070818608212146115114054814560270509307541871219901924317906285783345502450407903297515749909925247057656479099156326718535149969298044687730717978909742604675188350201879798460569721955402966098556911054579289216533244883556427607787129063524341478675272236515424795594246542809803123825660181435151517009926989152291239580046450083599706908982941859840129662960907854690675582551816049328631412344203956716526620975585430081122484860480186571618841845367637670136996691613216081512920967200668918375537812973064141095933513440342389661883780888908448851245758659782134089407794948873910
'''

ok,看到这里,基本上代码都读懂了,那我们就开始填坑了。

第一个坑 —— get_p() 函数:
def gen_p():P = [0 for i in range(16)]P[0] = getPrime(128)for i in range(1, 17):               P[i] = sympy.nextprime(P[i-1])n = 1print("P_p :", P[9]) for i in range(17):n *= P[i]p = getPrime(1024)factor = pow(p, base, n)print("P_factor :", factor)                              return sympy.nextprime(p)

上面也说了这是一个简单的欧拉函数的加密。

首先,已知 P[9],也就是P_p,我们就能给整个P[]数组给初始化。所以 n 的值也就能够计算出来了。

import sympy
import gmpy2
P = []
P[9] = P_p
for i in range(8,-1,-1):P[i] = sympy.prevprime(P[i+1])
for i in range(10,17):P[i] = sympy.nextprime(P[i-1])
n = 1
for i in range(1,17):n *= P[i]

接下来就到了欧拉函数部分了,已知n,e,要求d,最简单的方法就是通过欧拉函数。那么,欧拉函数是多少?

提醒一下,碰到简单n,e题目的时候,我们通过将将n分解曾p,q两个质数,然后用 phi = (p-1)*(q-1) 来计算。那这个地方呢?也去分解n?

其实,出题的时候就已经给你分好了。P[]数组里面的值都是质数!

而 n = P[1] * p[2] * …*P[16]

所以 phi(n) = phi(P[1]) * phi(P[2]) * … * phi(P[16])

所以 phi(n) = (P[1] - 1)*(P[2] -1)*(P[3] - 1)* … * (P[16] - 1)

所以 欧拉函数也有了,p,不久放出来了吗!(咳,有点味道)

phi = 1
for i in range(1,17):phi *= (P[i] - 1)
d = gmpy2.invert(base, phi)
p = pow(factor, d, n)
return sympy.nextprime(p)

OK,接下来第二个坑(天坑)

get_q()函数
def gen_q():sub_Q = getPrime(1024)Q_1 = getPrime(1024)Q_2 = getPrime(1024)Q = sub_Q ** Q_2 % Q_1print("Q_1: ", Q_1)print("Q_2: ", Q_2)print("sub_Q: ", sub_Q)return sympy.nextprime(Q)

看到上面的算法,你第一件想到的事情是什么?我想到的是sub_Q,Q_1,Q_2的结果都给了,跑不久完事了。如果你也是这样想的,那恭喜你,和我一样掉坑了,等到宇宙爆炸的都不一定能拿到结果。

让我们来看看(记号2),这里的运算时乘方,不是乘法,注意 是乘方,乘方,乘方。

一个1024位的数字做1024为数值次的乘方。怎么算?拿头算?

而这个地方精妙的就是后面的取模了。这就在告诉我们,Q你是拿不到了,但Q肯定是 Q_1 > Q > 0 之间的质数。

没了。

所以,到了这里,就是在变相的告诉你,最后的加密用到的q。而且q要么很小,靠近0,要么很大,靠近Q_1。

那思路不久清晰了吗:

​ p 已知了,Q_1已知,q自己去爆破 (用sympy.nextprime() 方法和sympy.prevprime()方法) ,e 已知了。

所以代码可以撸起来了。

import gmpy2
import sympy
from Crypto.Util.number import long_to_bytes
p = return sympy.nextprime(p)
q = Q_1        # 或者 q = 1
c = Ciphertext
Q_2 = 1
while True:n = p * qphi = (p-1) * (q-1)d = gmpy2.invert(e, phi)m = pow(c, d, n)m = long_to_bytes(m).decode('utf-8','ignore')print(m)q = sympy.prevprime(q)        # q = sympy.nextprime(q)   和前面的q=1配套使用

这样就可以爆破出结果了,不过还有一个问题,就是它没有终止条件。所以,这个时候就要用到(记号1)的flag格式了

# 只需要在 m = long_to_bytes(m).decode('utf-8','ignore')之后的任意位置加一个if判断就行了
if "nsfocus" in m:break

为了高效的爆出结果,我们肯定是选在两头都跑(1和Q_1),所以可以加个多线程上去。不过我比较菜,不会多线程,所以我选择开两个文件,嘿嘿,技术不够,脚本来凑。

完整脚本:

import sympy
import gmpy2
from Crypto.Util.number import long_to_bytese = 65537
P = [0 for i in range(17)]
P_p = 206027926847308612719677572554991143421
P[9] = P_p
P_factor = 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839n = P[9]
phi = P[9] - 1
for i in range(8,0,-1):P[i] = sympy.prevprime(P[i+1])n *= P[i]phi *= (P[i] - 1)for i in range(10,17,1):P[i] = sympy.nextprime(P[i-1])n *= P[i]phi *= (P[i] - 1)d = gmpy2.invert(e,phi)final_p = pow(P_factor, d, n)
final_p = sympy.nextprime(final_p)Q_1 = 103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521final_q = 1     #final_q = Q_1 Ciphertext =  3456235890998996195610328576070818608212146115114054814560270509307541871219901924317906285783345502450407903297515749909925247057656479099156326718535149969298044687730717978909742604675188350201879798460569721955402966098556911054579289216533244883556427607787129063524341478675272236515424795594246542809803123825660181435151517009926989152291239580046450083599706908982941859840129662960907854690675582551816049328631412344203956716526620975585430081122484860480186571618841845367637670136996691613216081512920967200668918375537812973064141095933513440342389661883780888908448851245758659782134089407794948873910while True:n = final_p * final_qphi = (final_p - 1) * (final_q - 1)try:d = gmpy2.invert(e,phi)m = pow(Ciphertext, d, n)m = long_to_bytes(m).decode('utf-8',"ignore")if "nsfocus" in m:print("m: ",m)breakexcept:passfinal_q = sympy.nextprime(final_q) # final_q = sympy.prevprime(final_q)

其实,这题目就真的是在考数学。一手拓展欧几里得算法求逆元,然后同模余的运算法则。会了这一题,应该算是rsa算法有了初步的认知了。

先上解题代码:

import gmpy2
from gmpy2 import gcd
from Crypto.Util.number import long_to_bytes
n =  17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121gift =  2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104
c =   11896048663970780362228781837489466486466282266282525774268696785272105376496162776613405022882264737932390195829622289249358353406571295574018064222013763168773667801755802797093469517945242168621127603773017861402501708822613876791515803039151959944370904767218422806768104905816096919472743978664055791890321098068209891550854674116923626647321385265228978238829509815935768090750750110601100943820432504952197382099637084090991156423394140353352175855468352060270942119322431162691631220150197779269032493785754953460073099974345959080880071039856065496031922388307631138393107747419702153992404456267795192911174e_orign = 54722
e = 27361for k in range(1,8):d = gmpy2.invert(e,k*gift)m = gmpy2.powmod( c, d, n)m = gmpy2.iroot(m,2)m = long_to_bytes(m[0]).decode('utf-8','ignore')print('m : ',m)

先自己试着去理解一以下把,解析后面再补。我困了。该睡觉了。

2021宁波市第四届网络安全大赛(练习平台)RSA部分相关推荐

  1. 2022宁波市第五届网络安全大赛(初赛Misc部分)

    听说线下决赛有菠萝包吃? 解题情况:5题解4,一个三血,哆哆嗦嗦进决赛 BlackAndWhite 打开附件,发现是黑色和白色照片,猜测代表2进制,一共336张 脚本如下 white = open(' ...

  2. 2022宁波市第五届网络安全大赛(训练赛Misc部分)

    好久没打CTF了,浅报个比赛玩一玩,全靠队友带飞, 手动@web大手子:Lxxx师傅 @全栈选手:21r000师傅 @本人是fw:Beizi师傅 Search evidence 在某银行在近的一次项目 ...

  3. 2021年江西省网络安全大赛初赛MISC:extractall(循环解压+斐波那契脑洞)

    目录 解题思路 总结 解题思路 在附件里面的文件长这样: 首先点开hint.txt 发现,直接告诉了解压包密码是前一个解压包的名字. (这句话用南昌话说更带味) 解压之后,发现还是有压缩包,于是这可能 ...

  4. 宁波市第三届网络安全大赛-WriteUp(Misc)

    文章目录 友情链接 内心OS Misc | 完成 | 第一 Misc | 完成 | BBQ Misc | 完成 | 看图说话 Misc | 未完成 | 等等我 Misc | 未完成 | 抓我把 最后十 ...

  5. [2021首届“陇剑杯”网络安全大赛 决赛]内存取证writeup

    决赛不能联网-手上有只有vol2.6,这道题完全死了 文章目录 [2021首届"陇剑杯"网络安全大赛 决赛]内存取证 writeup 产品密钥 匿名邮箱 远控后门 数据清除时间 [ ...

  6. [2021首届“陇剑杯”网络安全大赛] webshell

    [2021首届"陇剑杯"网络安全大赛] webshell 题目描述 单位网站被黑客挂马,请您从流量中分析出webshell,进行回答: 1.黑客登录系统使用的密码是___Admin ...

  7. 2021第一届网刃杯网络安全大赛-老练的黑客

    2021第一届网刃杯网络安全大赛-老练的黑客 难度系数:4.0 题目描述:一黑客成功入侵某核电站且获得了操作员站控制权,该操作员站可控制离心机的转速,当离心机的转速持续高于5000时将导致设备损坏,为 ...

  8. 陇原战“疫“2021网络安全大赛 Web eaaasyphp

    eaaasyphp 文章目录 eaaasyphp 读取phpinfo 打fastcgi 恶意的ftp服务 构造pop链 参考链接 题目给出了源码 读取phpinfo 尝试反序列化读取phpinfo 但 ...

  9. 数据库2021“安恒·泰山杯”山东省网络安全大赛测试赛部分题目write up

    数据库2021"安恒·泰山杯"山东省网络安全大赛测试赛部分题目write up 2021"安恒·泰山杯"山东省网络安全大赛测试赛部分题目wp web1 admi ...

最新文章

  1. tcp协议缓冲区溢出_关于TCP 粘包拆包,你了解吗?
  2. haproxy 作为反向代理被攻击
  3. java对象序列化克隆_Java8基础知识(三)对象克隆与序列化
  4. cobertura覆盖率_Cobertura和Maven:集成和单元测试的代码覆盖率
  5. 您已到达6300千米深度,速度8 公里/秒,正在穿过地心 [置顶]
  6. oracle 临时文件 大文件,Oracle中临时文件File#和Db_files关系
  7. Daily Scrum02 12.03
  8. deprecations - 极不赞成的写法
  9. iOS面试 swift篇
  10. 容灾~~~~~~~~~~~~~~~~~~~~
  11. 用 函数 输入并计算平均分等
  12. 解决面具magisk刷入模块卡开机问题
  13. sql查询大于平均得分的球员的名字和得分,并追加显示平均得分的列
  14. 嵌入式软件开发为什么需要DevOps?
  15. “四”才是中国人的吉祥数字!
  16. 快递代领平台-用例图
  17. 看漫画MHGmhgui,Python爬虫之神奇的eval,附赠一个压缩模块
  18. DoS 与 MITM 攻击解说
  19. uni-app图片本地路径/网络路径转base64流 压缩
  20. 2020年焊工(高级)考试内容及焊工(高级)考试总结

热门文章

  1. 2022电大国家开放大学网上形考任务-企业集团财务管理非免费(非答案)
  2. 一个清包网友的装修清单3--给广大TX参考!清包路漫漫啊!~~~
  3. 攀爬机器人 蝎子_洛洛历险记中五种机器人的原型,一个是蝎子,有一个不是生物...
  4. C# 数组内元素合并转换成以指定字符连接的字符串
  5. Docker三剑客docker-machine ,docker-compose,docker-swam
  6. 类和对象(一)this指针详解
  7. 如何简单使用纯CSS3模仿时钟的指针转动
  8. IFR报告称新冠疫情后的恢复对“机器人技术”的需求很高
  9. ThingsBoard 使用
  10. Android问题集锦之一:adb devices 出现unauthorized错误