一:CTF五道题(三道必做,两道选做)
1.[BJDCTF 2020]base??
本题是自定义的base64加密表变表,可以创建一个数组来存放自定义的加密表,再将其转换为字符串放入key1中,接下来我们用字符串key2来存放标准加密表,再用一个字符串存放密文,寻找密文在换表中的下标并转换为标准表的密文,图片如下:
题目解出
2. [AFCTF 2018]BASE
本题给的文件巨大,需要循环进行base系列解密,直到解不出为止,代码如下
第二题通过
3.[LitCTF 2023]Is this only base?
根据提示,先进行栅栏解码,栏数为23
发现w型符合base64的特点
得到的结果是凯撒密码偏移的结果
第三题完成
4. [SWPUCTF 2021 新生赛]crypto6
观察给出的文本(由0-9的数字以及A-F的字母组成)可推知最终输出结果为base16代码;根据提示可知源代码进行的编码顺序应为base64-base32-base16
根据结果逆推初始代码:base16-base32-base64
第四题完成
5.[SWPUCTF 2021 新生赛]ez_caesar
先进行 base64解码
阅读源代码,得出凯撒密码的偏移量是 5,使用工具解密
第五题解出
二:base系列编码了解
Base16编码
Base16编码表格
Base16字符表: 0123456789ABCDEF
下标 | 编码值 | 下标 | 编码值 |
0 | 0 | 8 | 8 |
1 | 1 | 9 | 9 |
2 | 2 | 10 | A |
3 | 3 | 11 | B |
4 | 4 | 12 | C |
5 | 5 | 13 | D |
6 | 6 | 14 | E |
7 | 7 | 15 | F |
下标编码值下标编码值
0088
1199
2210A
3311B
4412C
5513D
6614E
7715F
Base16编码⽅式
1. 将数据(根据ASCII编码,UTF-8编码等)转成对应的⼆进制数
2. 然后将所有的⼆进制全部串起来,4个⼆进制位为⼀组,转化成对应⼗进制数。
3. 根据⼗进制数值找到Base16编码表⾥⾯对应的字符
base16是4个⽐特位表⽰⼀个字符,原码是1个字节(8个⽐特位)表⽰⼀个字符,也就是说原先如果使⽤ASCII编码后的⼀个字符,现在转化成两个字符。数据量是原先的2倍。
也就是LOVE加密后是4C4F5645
Base32编码
Base32编码表格
Base32字符表: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
Base32编码⽅式
- 将数据(根据ASCII编码,UTF-8编码等)转成对应的⼆进制数
- 然后将所有的⼆进制全部串起来,5个⼆进制位为⼀组,若不⾜5位则低位补0,转化成对应⼗进制数。
- 若不⾜40位,则补"="
⼀个"="相当于5位,补满40位为⽌。
例:
最后01不⾜5位,低位补全0。补为01000,也就是8然后这才35位,需要末尾补⼀个"="
所以LOVE⽤Base32编码后得到JRHVMRI=
Base32伪代码|实际环境
v3 = 0;
v4 = 0;
v28 = 0;
v5 = 0;
v25 = 0;
v6 = 0;
if ( v30 )
{
do
{
if ( !*(_BYTE *)(v6 + v2) ) // v2为字符串⾸地址,v6为0开始遍历
break;
++v6; v5 += 8;
++v3;
}
while ( v6 < v30 ); // 循环完,v5为将所有字符转换为⼆进制位、的位数
//
v28 = v3;
}
switch ( v5 % 40 ) // 这⾥对位数是否能整除40做判断,来判断是否添加'='
// v4等于多少就添加⼏个'='
{
case 8u:
v4 = 6;
goto LABEL_10; case 16u:
v4 = 4;
goto LABEL_10; case 24u:
v4 = 3;
goto LABEL_10; case 32u:
v4 = 1;
LABEL_10:
v25 = v4;
break; default: break;
}
v29 = (8 * v3 + 4) / 5; // 除以5,算⼀下转换后数据个数
// +4的原因是,向上取整,让余数也算⼀个数据
Base64编码
Base64编码表格
使⽤了ASCII编码中64个可打印的字符(⼤写字母A ~ Z,⼩写字母a ~ z,数字0~9以及"+","/") Base64字符表: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Base64编码⽅式
- 将数据(根据ASCII编码,UTF-8编码等)转成对应的⼆进制数
- 然后将所有的⼆进制全部串起来,6个⼆进制位为⼀组,若不⾜6位则低位补0,转化成对应⼗进制数。
- 若不⾜24位,则补"="
⼀个"=“想当于6个⼆进制位。例:
最后只有4位,低位补全0,则为111100然后3*6=18 不⾜24位,加上⼀个”=" LO加密后是TE8=
Base64伪代码|实际环境
当函数头是这种时候,⼤概率是Base64加密,然后根据字符集来确认
Base64url 编码
字符表中的 ‘+’ → ‘-’ , ‘/’ → ‘_’
总结
名称 | 下标数字的位个数 | 编码表字符串 | 位数不⾜是否会补全= | 编码后数据量变化 |
base16 | 4 | 数字0~ 9和字母A~F | 不会,位数刚好是4的倍数 | 由⼀个8位表⽰⼀个字符 变成 4位表⽰⼀个字符,数据量变为原来的2倍 |
base32 名称 | 下标数5字的位 | ⼤写字母A~ Z 和 数字2~7 编码表字符串 | 位数不⾜会是否会补 | 变为 8/5 倍 编码后数据量变化 |
个数 | ⼤写字母A~ Z,⼩写字母a~ z,数字0~9 | 全= | ||
base64 | 6 | 以及"+","/" | 会 | 变为 8/6=4/3 倍 |
Base加解密|Python实现
Base16加解密实现
Base16加解密(原始字符表)
import base64
original = 'wo tai nan le'
print("1 original: ",type(original),original)
print("2 original.encode('utf-8'): ",type(original.encode('utf-8')),original.encode('utf-8')) str_encode = base64.b16encode(original.encode('utf-8'))
print("3 str_encode: ",type(str_encode),str_encode)
print("4 str(str_encode,'utf-8'): ",type(str(str_encode,'utf-8')),str(str_encode,'utf-8')) str_decode = base64.b16decode(str_encode)
print("5 str_decode: ",type(str_decode),str_decode)
print(str(str_decode,'utf-8'))
输出结果为
关键代码:
base64.b16encode(<'bytes'>) #base16编码 base64.b16decode(<'bytes'>) #base16解码 |
base64.b16encode(X) 其中需要加密的类型为’bytes’
(其中16可⾃⾏替换为16 32 64)
同时,加密后的类型也为’bytes’类型
所以加密的时候需要将 str 类型先转换为 bytes 类型:
例如:origin是⼀个 str 类型,则 origin.encode('utf-8') 则为 bytes 类型
⽽将 bytes 类型先转换为 str 类型:
代码: str(origin,'utf-8') 其中origin是需要转换的 bytes 类型数据
Base16加解密(⾃定义字符表)
Base16的原始字符表为: 0123456789ABCDEF
倘若我们替换成 abcdef0123456789
⽤到两个⽅法
str.maketrans(intab, outtab) //⽤于创建字符映射的转换表 intab -- 字符串中被替代的字符组成的字符串。
outtab -- ⽤来替换的字符串。后者替换前者
#第三个参数此处不讨论
此处的str不可改
str.translate(table[, deletechars]) //根据参数table给出的表转换字符串的字符 table -- 翻译表,翻译表是通过maketrans⽅法转换⽽来。
deletechars -- 字符串中要过滤的字符列表。#第⼆个参数此处不讨论
此处的str为需要转换的字符串,⾃⾏根据⾃⼰字符串取的名称进⾏更换
实例:
intab = "like" outtab = "love"
biao = str.maketrans(intab, outtab)
origin = "I like you" print(origin.translate(biao))
加解密实例
import base64
origin = 'wo tai nan le!!'
biao1 = str.maketrans("0123456789ABCDEF","abcdef0123456789") str_encode = base64.b16encode(origin.encode('utf-8'))
encode = str(str_encode,'utf-8').translate(biao1) print(encode)
biao2 = str.maketrans("abcdef0123456789","0123456789ABCDEF") str_decode = base64.b16decode(encode.translate(biao2).encode('utf-8'))
print(str(str_decode,'utf-8'))
输出
1109ca1e0b03ca080b08ca060fcbcb
wo tai nan le!!
Base32加解密实现
同Base16加解密,将b16改为b32即可
Base64加解密实现
同Base16加解密,将b16改为b64即可