[BJDCTF 2nd]rsa1
题目链接(buu平台)
题解
首先拿到题目靶机。nc交互获取得到题目数据
得到的条件有
e
p^2+q^2
p-q
c
明显是一个rsa加密。要去求解这个题目。因为求解rsa嘛。我们本质上肯定是想通过最基础的rsa解密去求解的。也就是我们要获取到私钥d以及公钥n。
这边我们通过去求解p和q的值。来求解rsa加密。
根据已知信息
假设
p^2+q^2=a
p-q=b
其中a、b已知
即求解二元二次方程
求解方程可以使用z3-solver进行求解
安装方法如下
找到官网
下载对应系统的第三方库文件
例如我是windows系统,我下载的就是
z3_solver-4.8.8.0-py2.py3-none-win_amd64.whl
然后pip安装这个z3-solver库
pip install z3_solver-4.8.8.0-py2.py3-none-win_amd64.whl
然后求解出p和q的值进行一个基础的rsa解密就好了。
题解exp如下
import z3
import gmpy2
from Crypto.Util.number import *
#公钥e
e=11630623
#p^2+q^2
p2q2=159091823893455582874061921154612415267326476512949054956396980727282756099500423604620855106680518280081561541640137584218141965305223222299378169087637728170419037951685924289388185840842033127708318792414241966337535836497572877344724131756911624967860755193905135911797719211253029463146921655068409851682
#p-q
p_q=-1028057512734526688756255253926193308887656904740633132866508165158161555923213681694346079000723418169221377228338798941679856716917764591264729224439880
#密文c
c=c=16828607056351898528593346827961041518302251064718691085202163294074947863618526294699466675783765349214251854122505153854940088340991317516413847467861967618764774324129650766830916741676747137720500142976165361634620558308099053963312274170652756789297267286419176164695159543581037737967947118601658126996
#使用z3对二元二次方程进行求解
s=z3.Solver()
#定义两个变量
p,q=z3.Ints("p q")
#添加方程
s.add(p*p+q*q==p2q2)
s.add(p-q==p_q)
s.add(p>0)
arr=[]
#校验是否有解
if s.check()==z3.sat:
arr=s.model()
print(arr)
#得到p,q
q = 9418055170543903468662169278295577389409276234772590476185014016803075309886254123445652979884992724665244226628125328356664293030046148360676450649936611
p = 8389997657809376779905914024369384080521619330031957343318505851644913753963040441751306900884269306496022849399786529414984436313128383769411721425496731
#简单验证一下
assert(p*p+q*q==p2q2)
assert(p-q==p_q)
#rsa基础解密
n=p*q
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
flag=long_to_bytes(m)
print(flag)
EasyProgram
题目链接(buu平台)
拿到题目下载附件,得到两个文件
file.txt
用python读入字节流,判断长度为38.长度为38我们知道flag{}加上中间32位md5值就是一个标准的flag.也就先判断file.txt存放的是flag的密文
附件.txt
一个加密算法,大概是类似伪代码之类的。也比较容易看懂
get buf unsign s[256]
get buf t[256]
we have key:whoami
we have flag:????????????????????????????????
for i:0 to 256
set s[i]:i
for i:0 to 256
set t[i]:key[(i)mod(key.lenth)]
for i:0 to 256
set j:(j+s[i]+t[i])mod(256)
swap:s[i],s[j]
for m:0 to 38
set i:(i + 1)mod(256)
set j:(j + S[i])mod(256)
swap:s[i],s[j]
set x:(s[i] + (s[j]mod(256))mod(256))
set flag[m]:flag[m]^s[x]
fprint flagx to file
简单的把代码理一下,改成python的实现
key="whoami"
flag="flag{test_test_test_test_test_test_te}"
s=[]
t=[]
flag_enc=""
for i in range(256):
s.append(i)
for i in range(256):
t.append(ord(key[i%len(key)]))
j=0
for i in range(256):
j=(j+s[i]+t[i])%256
tmp=s[i]
s[i]=s[j]
s[j]=tmp
i=0
j=0
for m in range(38):
i=(i+1)%256
j=(j+s[i])%256
tmp=s[i]
s[i]=s[j]
s[j]=tmp
x=(s[i]+s[j]%256)%256
flag_enc+=chr(ord(flag[m])^s[x])
print(flag_enc)
简单分析一下,就是一个最简单的流密码,可以把前面的操作看作生成了一个密钥流。这个密钥流明显是固定的(也就是说和加密的明文无关)。那就很简单,异或解密就可以了。
题解exp如下:
f=open("file.txt","rb")
st=f.read()
print(len(st))
flag_enc=st
key="whoami"
s=[]
t=[]
flag=""
for i in range(256):
s.append(i)
for i in range(256):
t.append(ord(key[i%len(key)]))
j=0
for i in range(256):
j=(j+s[i]+t[i])%256
tmp=s[i]
s[i]=s[j]
s[j]=tmp
i=0
j=0
for m in range(38):
i=(i+1)%256
j=(j+s[i])%256
tmp=s[i]
s[i]=s[j]
s[j]=tmp
x=(s[i]+s[j]%256)%256
flag+=chr(flag_enc[m]^s[x])
print(flag)
[AFCTF2018]可怜的RSA
题目链接(buu平台)
拿到附件:
flag.enc
public.key
就明显是拿到两个附件,一个是RSA加密的密钥文件,还有一个是flag加密后的密文的文件。
这边的话一种就是常规的用openssl,个人不太喜欢用。python能解决的问题我一般就python解决了。这边用到python的Crypto库,是做CTF密码学非常常用的一个库。
pip install pycrypto
安装好这个Crypto库
然后导入Crypto.PublicKey.RSA
用RSA模块的import_key函数将我们的publickey读入,拿到RSA加密的公钥n和e的具体参数
from Crypto.PublicKey import RSA
f=open("public.key","r")
key=RSA.import_key(f.read())
f.close()
e=key.e
n=key.n
然后发现n可以分解,直接在线网站http://factordb.com/把n给分解了,得到公钥n的两个因子。
然后就是常规的RSA求解私钥
这边因为flag.enc是RSA的PKCS1_OAEP加密得来的。所以我们这边也是给生成一个私钥文件。
在做到这边的时候,如何导出一个私钥文件。找了一下百度上的方法。都是先generate后给参数分别赋值的。但是我发现我并不行,试了一下python3和python2下的Crypto库都得到一个报错
Exception has occurred: AttributeError
can't set attribute
也就是现在无法通过这么直接赋值了。
这种情况的话,可以去看下python调用的Crypto库里面的RSA模块的一个底层的实现。
发现有一个construct函数,传入一个rsa_components参数,是一个元组型的数据,也就是tuple类型的,分别是(n,e,d,p,q)
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
rsa_components=(n,e,int(d),p,q)
arsa=RSA.construct(rsa_components)
arsa.exportKey()
然后导出的私钥,对加密后的密文,使用PKCS1_OAEP模块进行解密即可。
题解exp如下
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
f=open("public.key","r")
key=RSA.import_key(f.read())
f.close()
e=key.e
n=key.n
import base64
from Crypto.Util.number import *
import gmpy2
p= 3133337
q=25478326064937419292200172136399497719081842914528228316455906211693118321971399936004729134841162974144246271486439695786036588117424611881955950996219646807378822278285638261582099108339438949573034101215141156156408742843820048066830863814362379885720395082318462850002901605689761876319151147352730090957556940842144299887394678743607766937828094478336401159449035878306853716216548374273462386508307367713112073004011383418967894930554067582453248981022011922883374442736848045920676341361871231787163441467533076890081721882179369168787287724769642665399992556052144845878600126283968890273067575342061776244939
print(p*q==n)
f=open("flag.enc","r")
c_base64=f.read().strip("\n")
c_bytes=base64.b64decode(c