前言
懒狗一个,最近打比赛才知道还有base64隐写,有很多大师傅已经记录了原理,这里简单写一下。
base64
base64编码就是用64个ascii字符作为基础来编码二进制内容的一种编码方式。编码后的数据是一个字符串, 包含的字符为: A-Za-z0-9+/
共 64 个字符,=
是填充字符.
编码与解码
编码
编码时,将要编码的内容转换为二进制数据(一个字符对应8位二进制),每6位作为一组,从索引表中找到对应的字符
编码的文本字节数是3的倍数时,刚好可以编码成4个字符
编码的文本字节数不是3的倍数时,剩下1个字符时
编码的文本字节数不是3的倍数时,剩下2个字符时
这就是base编码方式
解码
- 首先把填充字符
=
去掉 - 每个字符查表转换为对应的6位索引,得到一串二进制字符串
- 接着从左到右,每8位一组,多余位丢掉,转为对应的字符
base64隐写原理
base64之所以可以隐藏信息,便是在于在解密过程中,在解码的第3步中,会有部分数据被丢弃(即不会影响解码结果),这些数据正是在编码过程中补的0。也就是说,如果在编码过程中不全用0填充,而是用其他的数据填充,仍然可以正常编码解码,因此这些位置可以用于隐写。
解开隐写的方法就是将这些不影响解码结果的位提取出来组成二进制串(一行 base64 最多有 2 个等号, 也就是有 22 位的可隐写位.),然后转换成ASCII字符串。这就是为什么出base64隐写时会有很多大段 base64 的原因*
这里借用下Tr0y师傅的图
例如第三幅图,将最后两位改成01、10、11其实都不会对结果产生任何影响
aGU=
aGV=
aGW=
aGX=
base64解码后全为
he
需要注意的是等号的那部分 0 不能用于隐写,因为修改那里的二进制值会导致等号数量变化, 解码的第 1 步会受影响. 自然也就破坏了源字符串。
base64隐写解密脚本
def get_base64_diff_value(s1, s2):
base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
res = 0
for i in xrange(len(s2)):
if s1[i] != s2[i]:
return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))