ctf
misc
国粹
脚本一:
# 导入PIL库中的Image模块
from PIL import Image
# 设置单元格的宽度和高度
ew, eh = 53, 73
# 打开题目图像文件,并获取其大小
table_pic = Image.open('题目.png')
ti_w, ti_h = table_pic.size
# 创建一个长度为42的列表,用于存储所有单元格的颜色值
color = [0] * 42
# 遍历所有单元格,提取每个单元格的颜色值
for i in range(1, 43):
pic = []
for y in range(eh):
for x in range(ew):
# 获取指定位置的像素值,并将其第一个元素(即红色通道的值)添加到pic列表中
pic.append(table_pic.getpixel((53*i + x, y))[0])
color[i-1] = pic
# 打开包含字母K的图像文件,并获取其大小
k_pic = Image.open('k.png')
k_w, k_h = k_pic.size
# 创建一个空列表,用于存储包含字母K的单元格在网格中的索引
flag_ind = []
# 遍历包含字母K的图像文件中的所有单元格
for i in range(k_w // 53):
pic = []
for y in range(eh):
for x in range(ew):
# 获取指定位置的像素值,并将其第一个元素(即红色通道的值)添加到pic列表中
pic.append(k_pic.getpixel((53*i + x, y))[0])
# 找到pic在color列表中的索引,即相应单元格的索引,并将其添加到flag_ind列表中
ind = color.index(pic)
flag_ind.append(ind)
# 打开包含字母A的图像文件,并获取其大小
a_pic = Image.open('a.png')
a_w, a_h = a_pic.size
# 创建一个空列表,用于存储包含字母A的单元格在网格中的索引
a_ind = []
# 遍历包含字母A的图像文件中的所有单元格
for i in range(a_w // 53):
pic = []
for y in range(eh):
for x in range(ew):
# 获取指定位置的像素值,并将其第一个元素(即红色通道的值)添加到pic列表中
pic.append(a_pic.getpixel((53*i + x, y))[0])
# 找到pic在color列表中的索引,即相应单元格的索引,并将其添加到a_ind列表中
ind = color.index(pic)
a_ind.append(ind)
# 创建一个新的灰度图像,大小为42x42像素,初始化为所有像素都设置为白色(即值为255)
new_pic = Image.new('L', (42, 42), 255)
# 遍历包含字母A的单元格在网格中的索引,将相应的像素设置为黑色(即值为0)
for i in range(len(a_ind)):
# 根据flag_ind和a_ind列表中的索引,设置相应位置的像素为黑色
new_pic.putpixel((flag_ind[i], a_ind[i]), 0)
# 显示生成的图像
new_pic.show()
题目.png:
a.png:
k.png:
这个脚本的思路就是将 题目.png 当成一个类似于字典的东西,将麻将的红色通道值来一一对应,然后用a.png和k.png来比对,红色通道值一样就把题目.png的所赋予麻将的值结合。最后根据比对好的索引去构成一个新的图片。
脚本二:
import matplotlib.pyplot as plt
data = [(1,4),(1,5),(1,10),(1,30),(2,3),(2,4),(2,5),(2,6),(2,10),(2,29),(2,30),(3,3),(3,4),(3,10),(3,16),(3,17),(3,22),(3,23),(3,24),(3,25),(3,29),(3,30),(4,2),(4,3),(4,4),(4,5),(4,10),(4,15),(4,16),(4,18),(4,21),(4,22),(4,24),(4,25),(4,29),(4,30),(5,3),(5,4),(5,10),(5,15),(5,17),(5,18),(5,19),(5,21),(5,22),(5,25),(5,28),(5,29),(6,3),(6,4),(6,10),(6,15),(6,16),(6,18),(6,19),(6,21),(6,22),(6,25),(6,29),(7,3),(7,4),(7,10),(7,11),(7,12),(7,13),(7,15),(7,18),(7,19),(7,22),(7,23),(7,24),(7,25),(7,29),(7,30),(8,3),(8,4),(8,11),(8,12),(8,15),(8,16),(8,17),(8,18),(8,19),(8,20),(8,25),(8,29),(8,30),(9,21),(9,22),(9,24),(9,25),(9,30),(9,31),(10,23),(10,24),(12,22),(12,23),(12,24),(12,25),(13,2),(13,3),(13,4),(13,5),(13,9),(13,10),(13,11),(13,12),(13,16),(13,17),(13,18),(13,19),(13,24),(13,25),(14,2),(14,5),(14,6),(14,9),(14,12),(14,19),(14,23),(14,24),(15,5),(15,9),(15,12),(15,18),(15,19),(15,22),(15,23),(16,4),(16,5),(16,9),(16,12),(16,17),(16,18),(16,23),(16,24),(17,3),(17,4),(17,9),(17,12),(17,16),(17,17),(17,24),(17,25),(18,3),(18,9),(18,12),(18,16),(18,25),(19,3),(19,4),(19,5),(19,6),(19,9),(19,10),(19,11),(19,12),(19,16),(19,17),(19,18),(19,19),(19,21),(19,22),(19,23),(19,24),(19,25),(20,10),(20,11),(22,3),(22,4),(22,5),(22,6),(22,10),(22,11),(22,12),(22,17),(22,18),(22,19),(22,24),(22,25),(23,3),(23,6),(23,7),(23,9),(23,10),(23,16),(23,17),(23,19),(23,20),(23,22),(23,23),(23,24),(23,25),(24,3),(24,6),(24,7),(24,9),(24,10),(24,16),(24,19),(24,20),(24,24),(24,25),(25,3),(25,6),(25,7),(25,10),(25,11),(25,12),(25,16),(25,19),(25,20),(25,24),(25,25),(26,3),(26,6),(26,7),(26,12),(26,13),(26,16),(26,19),(26,20),(26,24),(26,25),(27,3),(27,6),(27,7),(27,9),(27,12),(27,13),(27,16),(27,19),(27,20),(27,24),(27,25),(28,3),(28,4),(28,6),(28,9),(28,10),(28,11),(28,12),(28,16),(28,17),(28,19),(28,20),(28,24),(28,25),(29,4),(29,5),(29,17),(29,18),(29,19),(31,10),(31,11),(31,12),(31,13),(31,25),(31,31),(32,4),(32,5),(32,6),(32,10),(32,11),(32,12),(32,13),(32,17),(32,18),(32,19),(32,23),(32,24),(32,25),(32,26),(32,32),(33,3),(33,4),(33,6),(33,7),(33,12),(33,16),(33,17),(33,23),(33,24),(33,26),(33,32),(34,6),(34,7),(34,11),(34,16),(34,17),(34,23),(34,24),(34,26),(34,32),(35,6),(35,11),(35,12),(35,17),(35,18),(35,19),(35,23),(35,24),(35,25),(35,26),(35,33),(36,5),(36,12),(36,13),(36,19),(36,20),(36,26),(36,32),(37,4),(37,5),(37,13),(37,16),(37,19),(37,20),(37,25),(37,26),(37,32),(38,4),(38,5),(38,6),(38,7),(38,9),(38,10),(38,11),(38,12),(38,13),(38,16),(38,17),(38,18),(38,19),(38,24),(38,25),(38,31),(38,32),(39,23),(39,24),(39,31)
]
# 将 x 和 y 分别取出
x_data = [d[0] for d in data]
y_data = [d[1] for d in data]
# 绘制散点图
plt.scatter(x_data, y_data)
# 添加标题和坐标轴标签
plt.title("A simple scatter plot")
plt.xlabel("X-axis label")
plt.ylabel("Y-axis label")
# 显示图形
plt.show()
这个则是更直接了当的去对比,来获取坐标值,用构建散点图的方式去构造图形。
pyshell
题目nc 进去直接就是一个python的交互式编译窗口,他限制了长度,所以我们需要了解交互式编译将未存储变量放入那个值
__import__('os').system('cat /flag')
是一个非常危险的命令,它可以在某些情况下导致系统被攻击者控制或者文件被泄露,因此不应该在生产环境下使用。该命令将执行 cat /flag
命令,这意味着它将打印系统中名为 flag
的文件的内容。这个命令通常用于CTF比赛中,以获取flag的内容。
所以可以利用
__import__('os').system('cat /flag')
+ _ 的套餐来进行控制程序达到我们想要的结果。
crypto
在单表替换加密中,所有的加密方式几乎都有一个共性,那就是明密文一一对应。所以说,一般有以下两种方式来进行破解
对于多表替换加密来说,加密后的字母几乎不再保持原来的频率,所以我们一般只能通过寻找算法实现对应的弱点进行破解。
单表替换加密
在单表替换加密中,这个码表通常是预先定义好的,加密和解密过程中都需要使用相同的码表。这意味着如果攻击者能够获得加密使用的码表,他们就可以轻松地解密密文并获得明文。
base家族
base64码表:
另有“=”符号作为填充
base32:
另有“=”符号作为填充
base16码表:
Base16使用两个ASCII字符去编码原数据中的一个字节数据,所以Base16不可能用到填充符号“=”
base家族还有很多,大体了解一下,省的以后连一个简单base都不认识。
凯撒密码
凯撒密码(Caesar)加密时会将明文中的 每个字母 都按照其在字母表中的顺序向后(或向前)移动固定数目(循环移动)作为密文。例如,当偏移量是左移 3 的时候(解密时的密钥就是 3):
明文字母表:ABCDEFGHIJKLMNOPQRSTUVWXYZ
密文字母表:DEFGHIJKLMNOPQRSTUVWXYZABC
-
根据偏移量的不同,还存在若干特定的恺撒密码名称:
-
偏移量为 10:Avocat (A→K) 偏移量为 13:ROT13 偏移量为 -5:Cassis (K 6) 偏移量为 -6:Cassette (K 7)
此外,还有还有一种基于密钥的凯撒密码 Keyed Caesar。其基本原理是 利用一个密钥,将密钥的每一位转换为数字(一般转化为字母表对应顺序的数字),分别以这一数字为密钥加密明文的每一位字母。
密文:s0a6u3u1s0bv1a
密钥:guangtou
偏移:6,20,0,13,6,19,14,20
明文:y0u6u3h1y0uj1u
移位密码
与凯撒密码类似,区别在于移位密码不仅会处理字母,还会处理数字和特殊字符,常用 ASCII 码表进行移位。其破解方法也是遍历所有的可能性来得到可能的结果。
多表代换加密
在多表代换加密中,加密过程通常通过轮流使用不同的码表来进行。例如,第一个字符可能使用第一个码表进行替换,第二个字符可能使用第二个码表进行替换,以此类推。这种轮流使用不同的码表可以增加加密的安全性,因为攻击者需要同时猜测出所有使用的码表才能破解密文。
Playfair
- 选取一串英文字母,除去重复出现的字母,将剩下的字母逐个逐个加入 5 × 5 的矩阵内,剩下的空间由未加入的英文字母依 a-z 的顺序加入。注意,将 q 去除,或将 i 和 j 视作同一字。
- 将要加密的明文分成两个一组。若组内的字母相同,将 X(或 Q)加到该组的第一个字母后,重新分组。若剩下一个字,也加入 X 。
- 在每组中,找出两个字母在矩阵中的地方。
- 若两个字母不同行也不同列,在矩阵中找出另外两个字母(第一个字母对应行优先),使这四个字母成为一个长方形的四个角。
- 若两个字母同行,取这两个字母右方的字母(若字母在最右方则取最左方的字母)。
- 若两个字母同列,取这两个字母下方的字母(若字母在最下方则取最上方的字母)
以 playfair example 为密匙,得
P L A Y F
I R E X M
B C D G H
K N O Q S
T U V W Z
要加密的讯息为 Hide the gold in the tree stump
HI DE TH EG OL DI NT HE TR EX ES TU MP
就会得到
BM OD ZB XD NA BE KU DM UI XM MO UV IF
#制表(采用横向制表)
def chess_map(k):
map_k = ''
alp = 'abcdefghiklmnopqrstuvwxyz' #i j视为同一个字母,j去除
for i in k:
if i not in map_k:
map_k += i
for i in alp:
if i not in map_k:
map_k += i
s = []
for i in range(0,len(map_k),5):
s.append(map_k[i:i+5])
return s
#解密
def playfair_decode(c,k):
temp = ''
for i in k:
for j in i:
temp += j
dex = ''
for i in c:
x = temp.index(i)//5
y = temp.index(i)%5
dex += str(x)+ str(y)
m = ''
for i in range(0,len(dex),4):
if dex[i] ==dex[i+2]:#同行
m += k[int(dex[i])][(int(dex[i+1])-1)%5]+k[int(dex[i+2])][(int(dex[i+3])-1)%5]
#以第一个字母对应的明文优先
elif dex[i+1] == dex[i+3]:#同列
m += k[(int(dex[i])-1)%5][int(dex[i+1])]+k[(int(dex[i+2])-1)%5][int(dex[i+3])]
#以第一个字母对应的明文优先
else:
m += k[int(dex[i])][int(dex[i+3])]+k[int(dex[i+2])][int(dex[i+1])]
#以第一个字母对应的行优先
#出现两个字母相同的,即同行同列的怎么办???
return m
key = chess_map('playfair'.lower())#密钥
c = 'lswpigtqtklbsZ'.lower()#密文
print(playfair_decode(c,key))
Polybius
Polybius 密码又称为棋盘密码,其一般是将给定的明文加密为两两组合的数字,其常用密码表
举个例子,明文 HELLO,加密后就是 23 15 31 31 34。
另一种密码表
注意,这里字母的顺序被打乱了。
举个例子,HELLO,使用这个表格加密,就是 DD XF AG AG DF。
Vigenere 维吉尼亚密码
维吉尼亚密码(Vigenere)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。
下面给出一个例子
明文:come greatwall
密钥:crypto
首先,对密钥进行填充使其长度与明文长度一样。
其次,查表得密文
明文:come greatwall
密钥:crypto
密文:efkt zferrltzn
工具
- 已知密钥
- Python 的 pycipher 库
- 在线解密 Vigenère cipher
- CAP4
- 未知密钥
其它类型加密
培根密码
培根密码使用两种不同的字体,代表 A 和 B,结合加密表进行加解密。
可以看到,培根密码主要有以下特点
- 只有两种字符
- 每一段的长度为 5
- 加密内容会有特殊的字体之分,亦或者大小写之分。
栅栏密码
栅栏密码把要加密的明文分成 N 个一组,然后把每组的第 1 个字连起来,形成一段无规律的话。这里给出一个例子
明文:THERE IS A CIPHER
去掉空格后变为
THEREISACIPHER
分成两栏,两个一组得到
TH ER EI SA CI PH ER
先取出第一个字母,再取出第二个字母
TEESCPE
HRIAIHR
连在一起就是
TEESCPEHRIAIHR
上述明文也可以分为 2 栏。
THEREIS ACIPHER
组合得到密文
TAHCEIRPEHIESR
曲路密码
曲路密码(Curve Cipher)是一种换位密码,需要事先双方约定密钥(也就是曲路路径)。下面给出一个例子
明文:The quick brown fox jumps over the lazy dog
填入 5 行 7 列表(事先约定填充的行列数)
加密的回路线(事先约定填充的行列数)
密文:gesfc inpho dtmwu qoury zejre hbxva lookT
块加密
又叫对称加密。
所谓块加密就是每次加密一块明文,常见的加密算法有
- IDEA 加密
- DES 加密
- AES 加密
其实,我们也可以把块加密理解一种特殊的替代密码,但是其每次替代的是一大块。而正是由于一大块,明文空间巨大,而且对于不同的密钥,我们无法做一个表进行对应相应的密文,因此必须得有 复杂 的加解密算法来加解密明密文。
基本策略
在分组密码设计时,充分使用了 Shannon 提出的两大策略:混淆与扩散两大策略。
混淆
混淆,Confusion,将密文与密钥之间的统计关系变得尽可能复杂,使得攻击者即使获取了密文的一些统计特性,也无法推测密钥。一般使用复杂的非线性变换可以得到很好的混淆效果,常见的方法如下
- S 盒
- 乘法
扩散
扩散,Diffusion,使得明文中的每一位影响密文中的许多位。常见的方法有
- 线性变换
- 置换
- 移位,循环移位
数学很好才能学,这个先放放。
非对称加密
在非对称密码中,加密者与解密者所使用的密钥并不一样,典型的有 RSA 加密,背包加密,椭圆曲线加密。
RSA 算法的可靠性由极大整数因数分解的难度决定。换言之,对一极大整数做因数分解愈困难,RSA 算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用 RSA 加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。如今,只有短的 RSA 密钥才可能被强力方式解破。到 2017 年为止,还没有任何可靠的攻击 RSA 算法的方式。
基本原理
公钥与私钥的产生
- 随机选择两个不同大质数 p 和 q,计算 N=p×q
- 根据欧拉函数,求得 φ(N)=φ§φ(q)=(p−1)(q−1)
- 选择一个小于 φ(N) 的整数 e�,使 e 和 φ(N)互质。并求得 e 关于 φ(N) 的模反元素,命名为 d,有 ed≡1(modφ(N))
- 将 p 和 q 的记录销毁
此时,(N,e)是公钥,(N,d) 是私钥。
常见对称密码在 Crypto.Cipher 库下,主要有:DES 3DES AES RC4 Salsa20` `非对称密码在 Crypto.PublicKey 库下,主要有:RSA ECC DSA` `哈希密码在 Crypto.Hash 库下,常用的有:MD5 SHA-1 SHA-128 SHA-256` `随机数在 Crypto.Random 库下` `实用小工具在 Crypto.Util 库下` `数字签名在 Crypto.Signature 库下