CTF-MISC学习指南

Base64隐写

想了解base64的隐写首先就得知道它是怎么编码解码的

编码

编码时,将要编码的内容转换为二进制数据(一个字符对应8位二进制),每6位作为一组,从索引表中找到对应的字符,的位置补0,最后不足四位的补=

解码

编码时补充了0增加等号,解码时去除等号并对应删除编码时补充的0,正因为这一点,使隐写成为可能。

上述所说的补位0所在的位置,加入我们修改为其他二进制数,而不是默认的全0,在做base64解码的时候,是不会影响解码结果的,因为这些补位0所在的位置,解码时都会被删除,所以不影响解码结果。

所以我们想要隐藏信息的话,就可以利用这些补位0所在的位置,base64编码后的字符串,如果有1个等号,就有两个bit的补位0可隐写,如果有2个等号,就有四个bit的补位0可隐写;如果没有等号,就没有补位0可隐写。

贴脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import re
import base64

b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

# ccc.txt为待解密的base64隐写字符串所在的文件
f = open('base64.txt','r')
base64str = f.readline()

# pattern2用于匹配两个等号情况时,等号前的一个字符
# pattern2用于匹配一个等号情况时,等号前的一个字符
pattern2 = r'(\S)==$'
pattern1 = r'(\S)=$'

# 提取后的隐写二进制字符加入binstring中
binstring = ''

# 逐行读取待解密的base64隐写字符串,逐行处理
while(base64str):
# 先匹配两个等号的情况,如果匹配不上,再配置一个等号的情况
# 如果无等号,则没有隐藏,无需处理
if re.compile(pattern2).findall(base64str):
# mstr为等号前的一个字符,该字符为隐写二进制信息所在的字符
mstr = re.compile(pattern2).findall(base64str)[0]
# 确认mstr字符对应的base64二进制数,赋值给mbin
mbin = bin(b64chars.find(mstr))
# mbin格式如0b100,mbin[0:2]为0b
# mbin[2:].zfill(6)为将0b后面的二进制数前面补0,使0b后面的长度为6
mbin2 = mbin[0:2] + mbin[2:].zfill(6)
# 两个等号情况隐写了4位二进制数,所以提取mbin2的后4bit
# 赋值给stegobin,这就是隐藏的二进制信息
stegobin = mbin2[-4:]
binstring += stegobin
elif re.compile(pattern1).findall(base64str):
mstr = re.compile(pattern1).findall(base64str)[0]
mbin = bin(b64chars.find(mstr))
mbin2 = mbin[0:2] + mbin[2:].zfill(6)
# 一个等号情况隐写了2位二进制数,所以提取mbin2的后2bit
stegobin = mbin2[-2:]
binstring += stegobin
base64str = f.readline()

# stegobin将各行隐藏的二进制字符拼接在一起
# 从第0位开始,8bit、8bit处理,所以range的步进为8
for i in range(0,len(binstring),8):
# int(xxx,2),将二进制字符串转换为10进制的整数,再用chr()转为字符
print(chr(int(binstring[i:i+8],2)),end='')