先简单介绍一下base64解密:
(图片来源见水印,侵删)
base64使用 a-zA-Z0-9+/ 等64个字符来替换掉所有字符,同时使用 = 来替换掉空格,既然一共有64个字符,那么每个字符只需要6位即可表示出来,对应表如下:
例如,原本的3个字节的数据经过编码后需要4个字节来表示:3*8 = 4*6;可以看出,只有二进制位数恰好是8和6的倍数才可以刚好用这64位表示。
那如果位数不是8和6的公倍数怎么办呢?——方法就是在二进制数串后面加0,一直到二进制位数变成6的倍数,然后在编码后的字符串后面添加 1 个或 2 个等号”=”, 表示所添加的零值字节数。参考下图:
解密过程是这样的:
首先把已经加密的字符串后面的等号(=)去掉,然后从左到右,每8位一组,剩余的不足8位的丢掉,再每组二进制串按照转换表转换成相应字符。
以上图为例:
VHIweQ== 变成 VHIweQ(01010100 | 01110010 | 00110000 | 01111001 | 0000)变成 01010100 | 01110010 | 00110000 | 01111001 | 变成 Tr0y
从上面的解密过程中可以看出,多余的4位(标红的4个0)在解密的时候并没有用到,也就是说,无论后四位是0000还是0001,解密结果都没有改变,这就提供了一个可以隐藏信息的地方。如下图;
那么,怎么判断有没有信息被隐藏进去了呢?
假设我们已经把后四位0000变成了0001,现在我们得到的加密后的字符串是VHIweR==,利用python中base64的解密函数直接解密后得到Tr0y,然后用base64的加密函数加密,得到的是VHIweQ==;
这时候我们就可以发现,按照正常加密流程加密得到的VHIweQ==,跟原始的字符串VHIweR==是不一样的,这就说明有信息被隐藏在了里面。
得到的一个加密文本是stego.txt:
把所有文本解密后发现得到一段话,并没有什么有用信息,参考题目,考虑base64隐写,附上脚本:(适用于python2情况)
其中
def get_base64_diff_value(s1, s2):
base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
res = 0
for i in xrange(len(s1)):
if s1[i] != s2[i]:
return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))
return res
def solve_stego():
with open('D:/stego.txt', 'rb') as f:
file_lines = f.readlines()
bin_str = ''
for line in file_lines:
steg_line = line.replace('\n', '')
norm_line = line.replace('\n', '').decode('base64').encode('base64').replace('\n', '')
diff = get_base64_diff_value(steg_line, norm_line)
pads_num = steg_line.count('=')
if diff:
#print bin(diff)
bin_str += bin(diff)[2:].zfill(pads_num * 2)
else:
bin_str += '0' * pads_num * 2
res_str = ''
for i in xrange(0, len(bin_str), 8):
res_str += chr(int(bin_str[i:i+8], 2))
print res_str
solve_stego()
运行后得到: