攻防世界-crypto-Decode_The_File(base64隐写)
题目来源:RCTF-2015
题目描述:暂无
附件下载后,是一个文本文件,里面有658行base64编码。
原理
先将附件中每行base64编码进行解码,得到一个Python脚本。但其实信息并非隐藏在解码后的数据中,而是隐藏在编码中。首先介绍,当需要编码的数据剩下1或2字节时,编码与解码过程如下:
可以看到,即使ai≠0,解码过程也能正确进行;从而可以使用ai传递一些信息。因此,只要我们将编码中的ai提取出来,就可以解出flag。
base64 隐写
关键是base64解码的时候
1.检查base64编码后面有几个等于号
2.把字符串按照base64表转换成6的倍数位数二进制
3. 删除等于号的个数*8个bit (等于号不在base64规定的范围内,只是为了补足长度,所以解码时要删除)
4.按照6个bit一组转成字符
此处的关键就是,解码的时候,会删除等于号的个数*8的bit,且我们只用6个bit表示一个等于号(xxxxxx),那么意思就是我们可以控制 等于号个数*2 bit的字符。
解题
实现的Python脚本如下:
from base64 import b64decode from string import uppercase,lowercase,digits from Crypto.Util.number import long_to_bytes def solve(): with open('encode','r') as f: codes=f.read() Lc=codes.split('\n')[:-1] base=uppercase+lowercase+digits+'+/' re2=[] for code in Lc: if '==' in code: re2.append(bin(base.find(code[-3]))[2:].rjust(6,'0')[2:]) elif '=' in code: re2.append(bin(base.find(code[-2]))[2:].rjust(6,'0')[4:]) ret=''.join(re2) return long_to_bytes(long(ret[:ret.rfind('1')+1],2)) if __name__=='__main__': print solve()
以文本文件的第二行(IyAJCQkJRG9jdW1lbnRhdGlvbgkJCQkgICAgI0==)为例
我们解释re2.append(bin(base.find(code[-3]))[2:].rjust(6,'0')[2:])的意思
code[-3] 返回倒数第3个字符,就是==前面的字符,即0
base.find(code[-3]) 返回字符0在base64编码表中对应的数字52(大写字母、小写字母、数字、+、/分别对应0-63)
bin(base.find(code[-3]) 返回52对应的二进制'0b110100'
bin(base.find(code[-3]))[2:] 从字符'0b110100'中取出从第3位开始的字符,即'110100'(这一步目的是去掉前面的0b,只留下二进制数字)
bin(base.find(code[-3]))[2:].rjust(6,'0') 即将原字符串右对齐,并使用'0'填充至长度为6形成一个新字符串,这里原字符串本来就是6位所以结果还是'110100',需要注意的是,原字符串是由0-64的十进制数字进行二进制转化而来,所以原字符串的位数应该为1-6位,最高也不会超过6位
bin(base.find(code[-3]))[2:].rjust(6,'0')[2:] 从6位二进制数中取出来后4位(从第3位开始直到最后1位)
re2.append() 最后将结果 放进列表中
程序运行结果如下:
$ python solve.py
ROIS{base_GA_caN_b3_d1ffeR3nT}
参考
官方wp
https://www.cnblogs.com/coming1890/p/13540370.html