1 声明
本文的base64部分参考了下面的文章
https://www.jianshu.com/p/48fe4dd3e5ce
2 背景
圣诞节前做了北京工业大学的CTF,其中有一道base64隐写的题目,这里记录一下原理,以供日后方便查看。
3 原理
- base64是怎么编码的?
- 字符对应ASCII转换成八位二进制( base64的基础单位是 38bit的二进制,若是不够38bit则在后面添加0字节(padding)直至满足)(例如:字符A–>八位二进制01000001不够38即不够24位后面补0直到满足38即 01000001 00000000 00000000)
- 38bit的二进制转换成46bit的二进制(01000001 00000000 00000000–>010000 010000 000000 000000)
- 4*6bit的二进制转换成十进制(010000 010000 000000 000000–>16 16 0 0)(注意后面的两个0在下一步不会变成base64对照表里的A而是你自己加上去的要变成等号(=))
- 对照base64表把十进制转换成字符(16 16 0 0–>Q Q = = )
就是说3个字符的字符串base64编码之后会转成4个字符的base64编码
- base64是怎么解码
- 检查base64编码后面有几个等于号
- 把字符串按照base64表转换成4*6的倍数位数二进制
- 删除等于号的个数*8的bit
- 按照6个bit一组转成字符
关键就是,解码的时候,会删除等于号的个数 8的bit,而且我们只用6个bit表示一个等于号(000000),那么,意思就是我们可以控制等于号2bit的字符
看图片上的两个例子:
如图,那么我们就可以在加粗的0的位子用二进制隐写(改成其他的二进制数)。这样子做,不影响原文的还原(因为解码的时候加粗位置被改的数是要被删除的),唯一的区别就是,上图的QQ==中第二个Q会变化,QkM=的M会变化,所以base64可以用于隐写
4 示例
4.1 解码
下面的代码是对 UX==(X取A到Z)进行base64解码(python2.7)
1 | import base64 |
显示的结果如下
1 | E:\App\py_workspace\venv\Scripts\python.exe E:/App/py_workspace/asdf.py |
看出来啥了没
如果我要发给你一个Q那么我发UZ==可以,但是发UY==也可以,
看代码↓
1 | # coding:UTF8 |
效果如下
1 | E:\App\py_workspace\venv\Scripts\python.exe E:/App/py_workspace/mybase64隐写.py |
4.2 加解密程序
附送大家一个输出hello,world的c语言程序
1 | #include<stdio.h> |
解密的脚本如下
1 | def get_base64_diff_value(s1, s2): |
效果↓
1 | E:\App\py_workspace\venv\Scripts\python.exe E:/App/py_workspace/Tools/base64隐写解密.py |
4.3 具体题目
SXMgdGhpcyBiYXNlPw==
题目描述:
解题思路:
题目base64解密之后的结果如下所示
然后,对它进行base64解密,得到的是莫扎特的一首音乐歌词,有兴趣的朋友可以听听看!
关于base64隐写的介绍,大家可以看我的另一篇文章
看完上面的文章后,我这里直接从上面文章中拿来脚本如下:
1 | def get_base64_diff_value(s1, s2): |
得到flag
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。