前言
base编码是一种常见的编码方式,常见的有base64、base32、base16,最近在做题时碰到了一道base隐写的misc题目,于是上网学习了一下base的编码方式以及隐写原理
base64编码方式
Base64就是一种基于64个可打印字符来表示二进制数据的方法,具体的64个字符分别是A-Za-z0-9+/以及占位符=
base64编码首先将原字符串的每一个字符转换为8位的二进制ascii码,将所有的8位二进制数拼接后按照6个一组进行重组,再将每一组转换为10进制,去base64的索引表中寻找对应编码字符,以下图为例
原字符串为hel,将ascii码转化为二进制后一共3*8=24位,再6个一组,故编码后为aGVs四位字符。
但在实际过程中,并不是所有的字符串转化后长度都是6的倍数,这时就需要用0来补充未满的位数,并使用=来当作占位符,使最终的长度为8的倍数
base64解码方式
在对base64进行解码时,会将需要解码的字符串每四个分为一组(在有占位符=的情况下,待解码的内容长度总是4的倍数)
当末尾是=
时,则将等于号去掉,并将最后一个字符的后两位二进制数去掉,剩下的二进制数长度即为8的倍数,再进行解码
当末尾是==
时,则将两个等于号去掉,并将最后一个字符的后四位二进制数去掉,剩下的二进制数长度即为8的倍数,再进行解码
base64隐写原理
在存在占位符=
的情况下,会将部分位的二进制数丢弃,而这些被丢弃的位中可以插入隐写的信息,即在那些用0补充的位上插入别的信息,同时又不影响base解码
可知base64编码中,末尾=
的个数只可能是0个、1个、2个,而0个的时候无法隐写,故我们需要考虑末尾有1个或2个等号的情况
base64隐写例题:[GXYCTF2019]SXMgdGhpcyBiYXNlPw==
buu上有题目,附件可自行下载,
将附件中的base64编码正常解码后会得到一大堆英文语句,虽然有含义但是没有跟flag相关的信息,于是我们要考虑是否存在base64隐写,可用工具进行简单判断,把其中一句用base64解码后再编码
可以看到,解码后再编码的结果和原先不一样,则本题存在base64隐写,原本的00填充位一定隐藏了别的信息,我们可以取出所有隐写位的信息,全部拼接起来后8个一组计算10进制,再当作ascii码转化为字符串
import base64
table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
file = open("flag.txt")
flag=''
tmpbin=''
for line in file.readlines():
line=line.strip('\n')
if(line[-1]=='='):
if(line[-2]=='='):
i=table.index(line[-3])
b=bin(i)[2:]
b=b.zfill(6)
print(line)
print(b)
print(b[-4:]+'\n')
tmpbin+=b[-4:]
else:
i = table.index(line[-2])
b = bin(i)[2:]
b = b.zfill(6)
print(line)
print(b)
print(b[-2:]+'\n')
tmpbin+=b[-2:]
length= len(tmpbin)/8
for i in range(int(length)):
flag+=chr(int(tmpbin[i*8:i*8+8],2))
print(flag)
base32隐写
与base64隐写原理相同,通过改变填充位的0来隐藏信息,以下为base32的编码表,由于只有32个字符,故base32在编码时为5位一组来编码,末尾的=
个数有可能为0个、1个、3个、4个、6个,下面直接给出脚本
import base64
table='ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
file = open("xjj.txt")
flag=''
tmpbin=''
for line in file.readlines():
line=line.strip('\n')
if(line[-1]=='='):
if(line[-3]=='='):
if(line[-4]=='='):
if (line[-6] == '='):
i=table.index(line[-7])
b = bin(i)[2:]
b = b.zfill(5)
tmpbin+=b[-2:]
print(line)
print(b)
else:
i = table.index(line[-5])
b = bin(i)[2:]
b = b.zfill(5)
tmpbin += b[-4:]
print(line)
print(b)
else:
i = table.index(line[-4])
b = bin(i)[2:]
b = b.zfill(5)
tmpbin += b[-1:]
print(line)
print(b)
else:
i = table.index(line[-2])
b = bin(i)[2:]
b = b.zfill(5)
tmpbin += b[-3:]
print(line)
print(b)
length= len(tmpbin)/8
for i in range(int(length)):
flag+=chr(int(tmpbin[i*8:i*8+8],2))
print(tmpbin)
print(flag)