[WUSTCTF2020]B@se
题目给出的提示是base编码,尝试base64行不通,看了大佬wp说是base64变表,下面是脚本运行后的结果
flag{base64_1s_v3ry_e@sy_and_fuN}
[网鼎杯 2020 青龙组]you_raise_me_up
直接运行报错,说的是语法无效,大佬是这么写的:
从附件的代码我们可以找到关键字:flag(c = pow(m, bytes_to_long(flag), n))
很明显这里的n不是质数,那么这道题就不是rsa了,查了一下这道题是离散对数问题
那么根据离散对数的原理
c = pow(m, bytes_to_long(flag), n)
mflag ≡ c (mod n)
求解离散对数可以使用python的sympy库,其中的discrete_log函数(sympy是一个Python的科学计算库,用一套强大的符号计算体系完成诸如多项式求值、求极限、解方程、求积分、微分方程、级数展开、矩阵运算等等计算问题。)
解题脚本:
点击查看代码
from sympy.ntheory import discrete_log
import binascii
n = 2 ** 512
m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
flag_dec = discrete_log(n,c,m) #得到flag的十进制值
flag_hex=hex(flag_dec)
print(flag_hex)
print(binascii.a2b_hex(flag_hex[2:]))
跑一跑把flag计算出来就好啦。
点击查看代码
part1=1
for i in range(1,2021):
part1*=i;
print(str(part1)[0:8])
part2=520**1314+2333**666
print(str(part2)[0:8])
#(-80538738812075974)³+80435758145817515³+12602123297335631³=42
x=80538738812075974
y=80435758145817515
z=12602123297335631
part3=str(x+y+z)[0:8]
print(part3)
part4=520*1314
print(part4)
p1=hex(38609695)[2:]
p2=hex(67358675)[2:]
p3=hex(17357662)[2:]
p4=hex(683280)[2:]
print(p1,p2,p3,p4)
点击查看代码
#Python3
# Solution.py
from base64 import *
s = ""
with open('flag_encode.txt', 'r') as file:
s = bytes(file.read(),'ascii')
file.close()
lis1 = [s]
lis2 = []
lis3 = []
lis4 = []
while(1):
for a in lis1:
ok = 0
try:
lis2.append(b64decode(a).decode('ascii'))
ok = 1
except:
pass
try:
lis2.append(b32decode(a).decode('ascii'))
ok = 1
except:
pass
try:
lis2.append(b16decode(a).decode('ascii'))
ok = 1
except:
pass
if not ok:
lis3.append(a)
if not len(lis2):
break
lis1=lis2.copy()
lis2.clear()
for a in range(0,len(lis3)):
ok = 1
for b in lis3[a]:
if ord(b)>126 or ord(b)<32:
ok = 0
break
if ok:
lis4.append(lis3[a])
print(lis4)
flag{U_5h0u1d_Us3_T00l5}
[UTCTF2020]basic-crypto
打开文件,二进制转文本
base 64
凯撒密码
词频分析
congratulations! you have finished the beginner cryptography challenge. here is a flag for all your hard efforts: utflag{n0w_th4ts_wh4t_i_c4ll_crypt0}. you will find that a lot of cryptography is just building off this sort of basic knowledge, and it really is not so bad after all. hope you enjoyed the challenge!
utflag{n0w_th4ts_wh4t_i_c4ll_crypt0}
救世捷径
看了大佬的wp,提到了:dijstra算法,下面是大佬对算法的介绍
二、解题思路
txt文件中每行的前两个数字作为无向图的顶点,第三个数字是两顶点之间的距离,最后的字符串是两顶点之间的内容,将起点到终点最短路径经过的边上的内容组合起来便是flag。
单源点最短路径算法:dijstra算法。
一些想到哪是哪的tips写在这里咯:
1.一些前期的初始化和数据处理
1)初始化各点之间的距离为“无穷远”(在程序中用一个比较大的数代替这个无穷远的概念),一般可以直观地想出用2727的二维数组存这些距离值(Python中是用list套list作为过去高级语言中二维数组的那种存在……而且要注意要初始化把list里面都放上东西才行!),之后我们就操作索引是1-26的那些元素,浪费掉位置0处的空间,但可以恰好对应顶点1-26,清晰明了~
2)按行读取题目txt文件中的内容,用的是readlines(),得到的数据形式是每行作为一个元素组成的list。然后用strip()去掉行尾的换行符’\n’,再用split(’ ')将每行内容按空格分割组成新的list,方便后面在程序中的调用。
3)因为在2)步中已经分割出了每行的元素,就可以用2)步中的数据去初始化1)步中2727的list中的数据,把已知的那些两点之间的距离放入即可,具体写法见程序代码。
2.实现dijstra算法的函数
1)初始化一个长度是27,元素全是0xffff(代表距离很远)的list,用于记录当前顶点(索引与顶点序号一致是1-26)对于顶点1的最短距离。
2)初始化一个长度为27,元素全是0的list,元素值用于记录当前顶点(索引与顶点序号一致是1-26)是否已经找到了距离顶点1的最短路径,确定了最短路径就置该顶点序号对应索引值的元素为1。后面将这里元素值是1的顶点称为“已经确定的集合”。每次更新完各顶点到顶点1的距离后,找到最短的一个,将该顶点位置元素置1,该顶点就不再参与后续的遍历。
3)初始化一个长度为27,元素全是1的list,用于记录当前顶点到顶点1的最短路径的前驱顶点,用于最后回溯路径。
过程:
首先找到和顶点1直连的顶点,找到这些顶点中距离顶点1最短的一个顶点,将该顶点加入“已经确定的集合“,遍历该顶点的邻接顶点,更新顶点1到各个邻接顶点的最短距离。再找到现在与顶点1距离最短的顶点(在”已经确定的集合“中的顶点就不再遍历),再去遍历该顶点的邻接顶点,更新顶点1到这些邻接顶点的最短距离,从中找到距离最短的顶点加入“已经确定的集合”,再遍历该顶点的邻接顶点,更新这些顶点与顶点1的最短距离,找到与顶点1距离最短的顶点……以此循环直至所有顶点都加入“确定的集合”。
核心思想:
每次循环都找到当前距离顶点1最近的一个顶点,判断路径中经过该顶点后再到达与其邻接的其他顶点的距离,是否比之前存储的这些顶点到顶点1的距离更短,如果更短就更新对应顶点到顶点1的最短距离,更新完后再找到与顶点1距离最短的顶点重复上述操作。
需要用脚本:
点击查看代码
graph=[]
for i in range(27):
graph.append([]) #在一个list中放27个list,索引0-26
for i in range(27):
for j in range(27):
graph[i].append(0xffff) #先将图中各个顶点之间的距离初始化为一个比较大的数
f=open('./Downloads/dij.txt','r').readlines() #按行读取,每行内容是list中的一个元素,全部内容组成一个整体的list
#这里需要先手动将txt文件中的最后一行换行去掉否则会多一个'\n'
#print(f)
li=[]
for x in f:
li.append(x.strip().split(' ')) #strip()删除字符串前后空格,这里是去掉了最后的换行符'\n',然后再按' '分割每行的每个元素,原本在同一子list中的一行元素也彼此独立出来
#print(li)
for x in li:
graph[int(x[0])][int(x[1])]=int(x[2])
graph[int(x[1])][int(x[0])]=int(x[2])
def try_dijstra():
min_d=[0xffff for i in range(27)] #记录点i到起点1的最短距离
route=[1 for i in range(27)] #记录前驱顶点
isSure=[0 for i in range(27)] #记录各点到起点距离是否已经确定
for i in range(2,27):
min_d[i]=graph[i][1] #初始化一下能直连1的顶点和1的距离
min_d[1]=0
isSure[1]=1
for i in range(26):
min=0xfffff
temp=-1
for j in range(2,27): # 找到当前离顶点1最近的顶点加入已经确定的“顶点阵营”
if isSure[j]==0 and min>min_d[j]:
min=min_d[j]
temp=j
isSure[temp]=1
for j in range(2,27):# 判断从顶点1开始,在经过该顶点后,再到达其邻接顶点的距离,是否比其邻接顶点原本到顶点1的距离更近,如果更近就更新最短距离
if min_d[j]>min_d[temp]+graph[temp][j]:
min_d[j]=min_d[temp]+graph[temp][j]
route[j]=temp
return (route,min_d)
route,min_d=try_dijstra()
print(min_d[26]) #最短距离
print(route) #前驱顶点
passv=[] #存放顶点之间的“内容”(内容最后要组成flag
for i in range(27):
passv.append([]) # 还是在一个list中放27个list
for i in range(27):
for j in range(27):
passv[i].append(0) #需要将内部list中初始化出27个“位置”否则会报错索引越界
for x in li:
passv[int(x[0])][int(x[1])]=x[3]
passv[int(x[1])][int(x[0])]=x[3]
y=26
l=[]
while y!=1:
print(y) #输出终点到起点的最短路径经过的顶点
l.append(passv[y][route[y]]) #y到其前驱顶点route[y]之间的内容
y=route[y]
print()
l=l[::-1]
for i in range(len(l)):
print(l[i],end='')
'''
339
[1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 5, 5, 5, 4, 4, 4, 6, 6, 6, 25, 9, 11, 12, 6, 18, 22, 25]
26 25 22 12 5 2
FLAG{WEIVKASJVLSJCHFSJVHJSDEV}
'''
[HDCTF2019]together
下载好文件后,有4个文件,其中两个为公匙,将两个公匙进行分解:
得到两个n值和e值,我们仔细观察,不难发现两个值其实是相同的,那么此题就为一道共模攻击的题目:
共模攻击:
c1 = m^e1 mod n =>c1^s1 = m^(e1*s1) mod n
c2 = m^e2 mod n =>c2^s2 = m^(e2*s2) mod n
两者相乘,通过扩展欧几里得定理,我们可知e1与e2互质,必存在s1和s2使e1s1+e2s2=1
由此可求出相对应的s1和s2.
m=(c1s1+c2s2)%n
我们通过最后的两个等号判断为base解码,而出现大写字母则为base64,但是我们用base64解码后却不能得到我们想要的两个c值,因为解码后是字符串,需要我们将字符串转化为数字。
运行脚本:
点击查看代码
n1=14853081277902411240991719582265437298941606850989432655928075747449227799832389574251190347654658701773951599098366248661597113015221566041305501996451638624389417055956926238595947885740084994809382932733556986107653499144588614105694518150594105711438983069306254763078820574239989253573144558449346681620784979079971559976102366527270867527423001083169127402157598183442923364480383742653117285643026319914244072975557200353546060352744263637867557162046429886176035616570590229646013789737629785488326501654202429466891022723268768841320111152381619260637023031430545168618446134188815113100443559425057634959299
e1=0x091d
#print(e1)
n2=14853081277902411240991719582265437298941606850989432655928075747449227799832389574251190347654658701773951599098366248661597113015221566041305501996451638624389417055956926238595947885740084994809382932733556986107653499144588614105694518150594105711438983069306254763078820574239989253573144558449346681620784979079971559976102366527270867527423001083169127402157598183442923364480383742653117285643026319914244072975557200353546060352744263637867557162046429886176035616570590229646013789737629785488326501654202429466891022723268768841320111152381619260637023031430545168618446134188815113100443559425057634959299
e2=0x5b25
#print(e2)
f1='R3Noy6r3WLItytAmb4FmHEygoilucEEZbO9ZYXx5JN03HNpBLDx7fXd2fl+UL5+11RCs/y0qlTGURWWDtG66eNLzGwNpAKiVj6I7RtUJl2Pcm3NvFeAFwI9UsVREyh7zIV6sI9ZP8l/2GVDorLAz5ULW+f0OINGhJmZm8FL/aDnlfTElhQ87LPicWpXYoMtyr6WrxjK6Ontn8BqCt0EjQ7TeXZhxIH9VTPWjDmFdmOqaqdVIT+LZemTgLNESwM5nn4g5S3aFDFwj1YiDYl0/+8etvKfOrfoKOwR0CxsRHagwdUUTES8EcHLmMGCxCkDZn3SzmmA6Nb3lgLeSgG8P1A=='
f2='O+rRCXI3aTB6P1rYIOPUdalUp6ujpwEq4I20CoWA+HIL8xxGtqY6N5gpr0guZv9ZgOEAMFnBxOqMdVNnB9GgnhmXtt1ZWydPqIcHvlfwpd/Lyd0XSjXnjaz3P3vOQvR71cD/uXyBA0XPzmnTIMgEhuGJVFm8min0L/2qI7wg/Z7w1+4mOmi655JIXeCiG23ukDv6l9bZuqfGvWCa1KKXWDP31nLbp0ZN2obUs6jEAa1qVTaX6M4My+sks+0VvHATrAUuCrmMwVEivqIJ/nS6ymGVERN6Ohnzyr168knEBKOVj0FAOx3YLfppMM+XbOGHeqdKJRLpMvqFXDMGQInT3w=='
import base64
from Crypto.Util.number import *
c1=bytes_to_long(base64.b64decode(f1))
c2=bytes_to_long(base64.b64decode(f2))
import gmpy2
S=gmpy2.gcdext(e1,e2)
s1=S[1]
s2=S[2]
print(s1)
print(s2)
m=(gmpy2.powmod(c1,s1,n1)*gmpy2.powmod(c2,s2,n1))%n1
print(long_to_bytes(m))
[NPUCTF2020]Classical Cipher
里面有一个txt文本,一张加了密的图片,在txt文本中,有图片的密码,直接放上去是不对的
用ctf工具梭一下,下面那个有点像密码:
注意格式,图片密码为:the_key_is_atbash
打开的图片是这样的:
有猪圈密码,还有
古埃及象形文字
flag{classicalcode}
[BJDCTF2020]Polybius
是波利比奥斯方阵密码
会发现(2,4)这个坐标既可以表示i 也可以表示 j因此破解的时候这里又会多两种情况.
base64 解密提示后告诉一共有14个字符长度,结合题目polybius 猜测这是波利比奥斯方阵密码.
但是a,e,o,i,u这五个字符的代表顺序却不知道,因此可能有54321种情况,在结合刚才所说的i,j同时占一个位置,所以情况数要再乘上2,将这些情况全部都打印出来,然后去找有真实语义的句子就可以了.
点击查看代码
import itertools
s="aeoiu"
sumresult=[]
numsumresult=[]
ciper="ouauuuoooeeaaiaeauieuooeeiea"
for i in itertools.permutations(s,5):#找出所有全排列
sumresult.append("".join(i))
for i in sumresult:
temp=""
for j in ciper:
temp+=str(i.index(j)+1)
numsumresult.append(temp)
for i in numsumresult:
ans_=""
for j in range(0, len(i),2):
xx=(int(i[j])-1)*5+int(i[j+1])+96
if xx>ord('i'):
xx+=1
ans_+=chr(xx)
print(ans_)
flag{flagispolybius}
四面八方
以为是文本加密之字母的加密方式,结果不是,看了大佬的wp,是四方密码
四方密码介绍:
四方密码用4个5×5的矩阵来加密。每个矩阵都有25个字母(通常会取消Q或将I,J视作同一样,或改进为6×6的矩阵,加入10个数字)。
首先选择两个英文字作密匙,例如example和keyword。对于每一个密匙,将重复出现的字母去除,即example要转成exampl,然后将每个字母顺序放入矩阵,再将余下的字母顺序放入矩阵,便得出加密矩阵。
将这两个加密矩阵放在左上角和右下角,余下的两个角放a到z顺序的矩阵:
a b c d e E X A M P
f g h i j L B C D F
k l m n o G H I J K
p r s t u N O R S T
v w x y z U V W Y Z
K E Y W O a b c d e
R D A B C f g h i j
F G H I J k l m n o
L M N P S p r s t u
T U V X Z v w x y z
加密的步骤:
两个字母一组地分开讯息:(例如hello world变成he ll ow or ld)
找出第一个字母在左上角矩阵的位置
a b c d e E X A M P
f g h i j L B C D F
k l m n o G H I J K
p r s t u N O R S T
v w x y z U V W Y Z
K E Y W O a b c d e
R D A B C f g h i j
F G H I J k l m n o
L M N P S p r s t u
T U V X Z v w x y z
同样道理,找第二个字母在右下角矩阵的位置:
a b c d e E X A M P
f g h i j L B C D F
k l m n o G H I J K
p r s t u N O R S T
v w x y z U V W Y Z
K E Y W O a b c d e
R D A B C f g h i j
F G H I J k l m n o
L M N P S p r s t u
T U V X Z v w x y z
找右上角矩阵中,和第一个字母同行,第二个字母同列的字母:
a b c d e E X A M P
f g h i j L B C D F
k l m n o G H I J K
p r s t u N O R S T
v w x y z U V W Y Z
K E Y W O a b c d e
R D A B C f g h i j
F G H I J k l m n o
L M N P S p r s t u
T U V X Z v w x y z
找左下角矩阵中,和第一个字母同列,第二个字母同行的字母:
a b c d e E X A M P
f g h i j L B C D F
k l m n o G H I J K
p r s t u N O R S T
v w x y z U V W Y Z
K E Y W O a b c d e
R D A B C f g h i j
F G H I J k l m n o
L M N P S p r s t u
T U V X Z v w x y z
这两个字母就是加密过的讯息。
hello world的加密结果:
he lp me ob iw an ke no bi
FY GM KY HO BX MF KK KI MD
四方密码在线工具
将ypuogaodsuccessfum分成了ypuog aod successfum(确实有点难想)
查找有意义字符串的网站:https://quipqiup.com/
flag{youngandsuccessful}