目录
cr4-poor-rsa
best_rsa
RSA_gcd
RSA256
wtc_rsa_bbq
Handicraft_RSA
给文件添加压缩包后缀,压缩得到得到
先进行公钥解析,得到n、e。http://www.hiencode.com/pub_asys.html
分解n得到p、q
接着就是计算d,得到私钥,解码flag.b64并用key解密得到flag,脚本如下:
import base64
import gmpy2
import rsa
e = 65537
n = 833810193564967701912362955539789451139872863794534923259743419423089229206473091408403560311191545764221310666338878019
p = 863653476616376575308866344984576466644942572246900013156919
q = 965445304326998194798282228842484732438457170595999523426901
phi_n = (p-1)*(q-1)
d = gmpy2.invert(e,phi_n)
key = rsa.PrivateKey(n,e,d,p,q)#生成私钥
with open('C:\\Users\\lenovo\\Desktop\\flag.b64') as file:
f = file.read()
c = base64.b64decode(f)
flag = rsa.decrypt(c,key).decode()
print(flag)
解压出来,先从公钥文件中获得n、e,看看是哪种类型的题
from Crypto.PublicKey import RSA
publickey1 = RSA.importKey(open("C:\\Users\\lenovo\\Desktop\\publickey1.pem","rb").read())
publickey2 = RSA.importKey(open("C:\\Users\\lenovo\\Desktop\\publickey2.pem","rb").read())
#从公钥文件中得到n、e
n1 = publickey1.n
e1 = publickey1.e
n2 = publickey2.n
e2 = publickey2.e
print(n1)
print(e1)
print(n2)
print(e2)
e不同,n相同,大概就是共模攻击了,接着同样也从密文文件中获得c,再利用共模攻击脚本解出flag,整体代码如下:
from Crypto.PublicKey import RSA
from Crypto.Util.number import *
import gmpy2
publickey1 = RSA.importKey(open(r'C:\Users\lenovo\Desktop\publickey1.pem','rb').read())
publickey2 = RSA.importKey(open(r'C:\Users\lenovo\Desktop\publickey2.pem','rb').read())
#从公钥文件中得到n、e
n1 = publickey1.n
e1 = publickey1.e
n2 = publickey2.n
e2 = publickey2.e
#从密文文件中得到c
c1 = bytes_to_long(open(r'C:\Users\lenovo\Desktop\cipher1.txt','rb').read())
c2 = bytes_to_long(open(r'C:\Users\lenovo\Desktop\cipher2.txt','rb').read())
#共模攻击
s = gmpy2.gcdext(e1,e2)
m1 = pow(c1,s[1],n1)
m2 = pow(c2,s[2],n1)
m = (m1*m2)%n1
print(long_to_bytes(m))
解压得到两个文件,分别有n、e、c,且e相同,观察题目gcd,想到有两个n的时候应该考虑它们的公因数,若存在公因数,且公因数是素数,则这个公因数就是公共的p:
from gmpy2 import *
print(gcd(n1,n2))
print(is_prime(gcd(n1,n2)))
p = 138376604533530412400239558340424700312412702699022481119357799054715877829291635290832719835033140580690053865677079316241919169166375123691917675235979462772103681398725285808551041924624882840901583892858174270714471366531758975241868470938138238307005782651296179579961869801841395682782645916848523771439
接着用常规方法解出两个m,相连接就得到了flag,整体代码如下:
from gmpy2 import *
from Crypto.Util.number import *
e = 65537
n1 = 23220619839642624127208804329329079289273497927351564011985292026254914394833691542552890810511751239656361686073628273309390314881604580204429708461587512500636158161303419916259271078173864800267063540526943181173708108324471815782985626723198144643256432774984884880698594364583949485749575467318173034467846143380574145455195152793742611717169602237969286580028662721065495380192815175057945420182742366791661416822623915523868590710387635935179876275147056396018527260488459333051132720558953142984038635223793992651637708150494964785475065404568844039983381403909341302098773533325080910057845573898984314246089
c1 = 9700614748413503291260966231863562117502096284616216707445276355274869086619796527618473213422509996843430296526594113572675840559345077344419098900818709577642324900405582499683604786981144099878021784567540654040833912063141709913653416394888766281465200682852378794478801329251224801006820925858507273130504236563822120838520746270280731121442839412258397191963036040553539697846535038841541209050503061001070909725806574230090246041891486506980939294245537252610944799573920844235221096956391095716111629998594075762507345430945523492775915790828078000453705320783486744734994213028476446922815870053311973844961
n2 = 22642739016943309717184794898017950186520467348317322177556419830195164079827782890660385734113396507640392461790899249329899658620250506845740531699023854206947331021605746078358967885852989786535093914459120629747240179425838485974008209140597947135295304382318570454491064938082423309363452665886141604328435366646426917928023608108470382196753292656828513681562077468846105122812084765257799070754405638149508107463233633350462138751758913036373169668828888213323429656344812014480962916088695910177763839393954730732312224100718431146133548897031060554005592930347226526561939922660855047026581292571487960929911
c2 = 20513108670823938405207629835395350087127287494963553421797351726233221750526355985253069487753150978011340115173042210284965521215128799369083065796356395285905154260709263197195828765397189267866348946188652752076472172155755940282615212228370367042435203584159326078238921502151083768908742480756781277358357734545694917591921150127540286087770229112383605858821811640935475859936319249757754722093551370392083736485637225052738864742947137890363135709796410008845576985297696922681043649916650599349320818901512835007050425460872675857974069927846620905981374869166202896905600343223640296138423898703137236463508
print(gcd(n1,n2))
print(is_prime(gcd(n1,n2)))
p = 138376604533530412400239558340424700312412702699022481119357799054715877829291635290832719835033140580690053865677079316241919169166375123691917675235979462772103681398725285808551041924624882840901583892858174270714471366531758975241868470938138238307005782651296179579961869801841395682782645916848523771439
q1 = n1 // p
q2 = n2 // p
phi_n1 = (p-1)*(q1-1)
phi_n2 = (p-1)*(q2-1)
d1 = invert(e,phi_n1)
d2 = invert(e,phi_n2)
m1 = pow(c1,d1,n1)
m2 = pow(c2,d2,n2)
flag = long_to_bytes(m1) + long_to_bytes(m2)
print(flag)
还是公钥私钥加密类型,直接上代码了:
from Crypto.PublicKey import RSA
from Crypto.Util.number import *
from gmpy2 import *
publickey = RSA.importKey(open(r'C:\Users\lenovo\Desktop\gy.key','rb').read())
n = publickey.n
e = publickey.e
print(n)
print(e)
c = bytes_to_long(open(r'C:\Users\lenovo\Desktop\fllllllag.txt','rb').read())
print(c)
p = 273821108020968288372911424519201044333
q = 280385007186315115828483000867559983517#分解n得到
phi_n = (p-1)*(q-1)
d = invert(e,phi_n)
m = pow(c,d,n)
print(long_to_bytes(m))
得到flag:flag{_2o!9_CTF_ECUN_},去提交却错了,又看了题目说的提交形式flag{XXX},没有下划线,所以把下划线去掉再试一下,了。
用记事本打开看看, 一堆乱码,末尾有key.pem,故猜测是公钥私钥类型,解压出来加上.zip后缀,接着压缩得到,
直接上代码:
from Crypto.PublicKey import RSA
from Crypto.Util.number import *
from gmpy2 import *
publickey = RSA.importKey(open(r'C:\Users\lenovo\Desktop\key.pem','rb').read())
n = publickey.n
e = publickey.e
print(n)
print(e)
c = bytes_to_long(open(r'C:\Users\lenovo\Desktop\cipher.bin','rb').read())
print(c)
p = (2**4244)*699549860111847-1
q = (2**4244)*699549860111847+1#在线网站分解n,2**4244别写成2^4244
phi_n = (p-1)*(q-1)
d = invert(e,phi_n)
m = pow(c,d,n)
print(long_to_bytes(m))
下载附件,用记事本打开一堆乱码,看不出有用的信息,用010打开看看,也没啥用,不管了,直接加.zip后缀,打开果然有了些眉目,解压出来再次加上后缀并压缩,得到加密脚本以及一个文件
#!/usr/bin/python
from Crypto.Util.number import *
from Crypto.PublicKey import RSA
from secret import s, FLAG
def gen_prime(s):
while True:
r = getPrime(s)
R = [r]
t = int(5 * s / 2) + 1
for i in range(0, t):
R.append(r + getRandomRange(0, 4 * s ** 2))
p = reduce(lambda a, b: a * b, R, 2) + 1
if isPrime(p):
if len(bin(p)[2:]) == 1024:
return p
while True:
p = gen_prime(s)
q = gen_prime(s)
n = p * q
e = 65537
d = inverse(e, (p-1)*(q-1))
if len(bin(n)[2:]) == 2048:
break
msg = FLAG
key = RSA.construct((long(n), long(e), long(d), long(p), long(p)))
for _ in xrange(s):
enc = key.encrypt(msg, 0)[0]
msg = enc
print key.publickey().exportKey()
print '-' * 76
print enc.encode('base64')
print '-' * 76
对照着加密脚本,可以知道output文件里头是公钥形式的n、e,下面是enc进行base64编码后的内容。通过公钥解析可以得到n、e,利用在线分解对n分解应该可以得到p、q,就c不知道,故猜测加密脚本里的enc应该是c通过某种转化来的。
加密过程看不太懂,只知道最后对msg即flag加密了s次,看了大佬们的wp知道,s不大,可以进行爆破(根据gen_prime函数,最后返回一个1024位的素数,说明s不会很大),代码如下:
from Crypto.Util.number import *
from gmpy2 import *
import base64
e = 65537
n = 21702007965967851183912845012669844623756908507890324243024055496763943595946688940552416734878197459043831494232875785620294668737665396025897150541283087580428261036967329585399916163401369611036124501098728512558174430431806459204349427025717455575024289926516646738721697827263582054632714414433009171634156535642801472435174298248730890036345522414464312932752899972440365978028349224554681969090140541620264972373596402565696085035645624229615500129915303416150964709569033763686335344334340374467597281565279826664494938820964323794098815428802817709142950181265208976166531957235913949338642042322944000000001
p = 139457081371053313087662621808811891689477698775602541222732432884929677435971504758581219546068100871560676389156360422970589688848020499752936702307974617390996217688749392344211044595211963580524376876607487048719085184308509979502505202804812382023512342185380439620200563119485952705668730322944000000001
q = 155617827023249833340719354421664777126919280716316528121008762838820577123085292134385394346751341309377546683859340593439660968379640585296350265350950535158375685103003837903550191128377455111656903429282868722284520586387794090131818535032744071918282383650099890243578253423157468632973312000000000000001
phi_n = (p-1)*(q-1)
d = invert(e,phi_n)
enc = "eER0JNIcZYx/t+7lnRvv8s8zyMw8dYspZlne0MQUatQNcnDL/wnHtkAoNdCalQkpcbnZeAz4qeMX5GBmsO+BXyAKDueMA4uy3fw2k/dqFSsZFiB7I9M0oEkqUja52IMpkGDJ2eXGj9WHe4mqkniIayS42o4p9b0Qlz754qqRgkuaKzPWkZPKynULAtFXF39zm6dPI/jUA2BEo5WBoPzsCzwRmdr6QmJXTsau5BAQC5qdIkmCNq7+NLY1fjOmSEF/W+mdQvcwYPbe2zezroCiLiPNZnoABfmPbWAcASVU6M0YxvnXsh2YjkyLFf4cJSgroM3Aw4fVz3PPSsAQyCFKBA=="
c = bytes_to_long(base64.b64decode(enc))
s = 0
while True:
c = pow(c,d,n)
if(b'flag' in long_to_bytes(c)):
print(long_to_bytes(c))
print(s)
break
s+=1
s = 19,说明加密了20次