0x00: 前言

Base64编码的作用:

  • 将一些特殊的字符转换成常见的字符。特殊的字符可能是不可见字符或者是大于ascii码127的,将其变成常见的字符(在base64中为a~z A~Z 0~9 + /)。
  • Base64特别适合在某些网络协议下快速传输。

在学习Base64隐写之前,得先熟悉Base64编码与解码的过程。

0x01: Base64的编码过程

Base64编码后的字符为”a~z A~Z 0~9 + /“共计64个,每个需要6个比特位进行存储。原本,ASCII编码字符每个字符占8个比特位。Base64编码则是把原来每单位8个比特位的字符序列划分成每单位6个比特位,然后按单位转换成上述中的64个字符。

Base64编码表

举个栗子~:将字符串"tolele"进行Base64编码。

  1. 根据ASCII编码进行转换:tolele <==> 01110100 01101111 01101100 01100101 01101100 01100101
  2. 重新按6bit进行划分:011101 000110 111101 101100 011001 010110 110001 100101
  3. 根据Base64编码表进行转码:dG9sZWxl

检验一下是没问题的:

通过这种方式编码,当字符数为3的倍数时才会刚好可以转换成若干个Base64编码字符。那当字符数不为3的倍数时,该怎么办呢?解决方法就是往后面以8bit为单位填充0。

这时,有两种情况:

  1. 字符数为3n+1:此情况最后会多出2个比特位,我们可以填充2个单位的0(即16个比特位的0),这时会有多余的18个比特位。前6个比特位按表格进行转码,其余的每6个bit位转换成'='。
  2. 字符数为3n+2:此情况会多出4个比特位,填充1个单位的0,这样就多余12个比特位,为6的整数倍。后续和1中类似。

图像总是比话语更能说明内容:

检验一下:

0x02: Base64的解码过程:

很显然,解码过程就是编码的逆过程。

拿上面"tole"的Base64编码"dG9sZQ=="进行举例:

  1. 先把填充的'='去掉:dG9sZQ
  2. 根据Base64编码表进行转码:dG9sZQ <==> 011101 000110 111101 101100 011001 010000
  3. 从前往后,以每8个比特位为单位进行ASCII转换成字符。最后面会有4个'0'多余,直接去掉就行。

0x03: Base64隐写原理:

可以留意一下解码过程中的第三步,会将多余的比特位去掉(因为凑不到8位)。那么,这说明了:这多余的比特位即使我们随意的改变值也不会影响解码后的结果,因为它会被丢弃掉。

测试一下:还是上面的例子,最后是Q,为010000。后面的4个0在解码时会被丢弃掉的,那我们使其变成010101,变成了V。解码后的结果会改变吗?

可见,这个改变并不会对解码结果造成影响。

这样,为了隐写某些数据,我们就可以将数据写入这里。但每个Base64编码最多多余4个比特位,为了隐藏较大的数据,我们常常需要多个比特位。提取时,我们可以将每个多余的比特位截取出来,按一定的顺序组合,从而得到我们的隐藏数据。

0x04: 例题实践

Buuctf的base64隐写:

https://buuoj.cn/challenges#[ACTF%E6%96%B0%E7%94%9F%E8%B5%9B2020]base64%E9%9A%90%E5%86%99

打开关键的txt文件一看,大量的base64编码,base64隐写跑不了了:

这里直接用大佬的脚本了,python2执行是没问题的,至于python3的话……


# -*- coding: cp936 -*-

b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

with open('1.txt', 'rb') as f:
bin_str = ''
for line in f.readlines():
stegb64 = ''.join(line.split())
rowb64 = ''.join(stegb64.decode('base64').encode('base64').split())

offset = abs(b64chars.index(stegb64.replace('=','')[-1])-b64chars.index(rowb64.replace('=','')[-1]))
equalnum = stegb64.count('=') #no equalnum no offset

if equalnum:
bin_str += bin(offset)[2:].zfill(equalnum * 2)

print ''.join([chr(int(bin_str[i:i + 8], 2)) for i in xrange(0, len(bin_str), 8)]) #8 位一组

0x05: 感慨

“您这flag挺能藏的呀~”


tolele

2022-05-14

Base64隐写的更多相关文章

  1. 记XDCTF的misc之旅---base64隐写

    bWFpbigpe2ludCBpLG5bXT17KCgoMSA8PDEpPDwgKDE8PDEpPDwoMTw8Cm==ICAgICAgIDEpPDwoMTw8KDE+PjEpKSkrKCgxPDwx ...

  2. base64文件隐写脚本

    base64文件隐写脚本 base64 可以在文件中隐藏信息,记录一下提取脚本 ''' base64文件隐写脚本 import re import base64 b64chars = 'ABCDEFG ...

  3. base64stego 还不懂base64的隐写,详解15行代码带你领略

    网上写了好多关于xctf MISC新手篇的base64Stego隐写的教程,但大都不太清楚,基本上都是讲了一段隐写原理,直接上代码了.但是代码是这道题的关键,代码讲了如何解码这个隐写的完整流程,这次我 ...

  4. python2/3中 将base64数据写成图片,并将图片数据转为16进制数据的方法、bytes/string的区别

    1.python2将base64数据写成图片,并将数据转为16进制字符串的方法 import binascii img = u'R0lGODlhagAeAIcAAAAAAAAARAAAiAAAzABE ...

  5. CTF-练习平台-Misc之 图片又隐写

    八.图片又隐写 修改后缀名为zip,打开解压出两个文件 解压发现有密码,用WinHex打开发现文件头是zip的,所以出来把后缀名改为zip,再用工具爆破 最后得到解压密码,解压后是一个图片,改后缀名为 ...

  6. 记一道CTF隐写题解答过程

      0x00 前言 由于我是这几天才开始接触隐写这种东西,所以作为新手我想记录一下刚刚所学.这道CTF所需的知识点包括了图片的内容隐藏,mp3隐写,base64解密,当铺解密,可能用到的工具包括bin ...

  7. 深入理解JPEG图像格式Jphide隐写

    0x00 隐写原理 Jphide是基于最低有效位LSB的JPEG格式图像隐写算法,使用JPEG图像作为载体是因为相比其他图像格式更不容易发现隐藏信息,因为JPEG图像在DCT变换域上进行隐藏比空间域隐 ...

  8. 隐写技巧——利用JPEG文件格式隐藏payload

    0x00 前言 继续对图片隐写技巧的学习,这次是对JPEG文件格式的学习和理解.同PNG文件的格式对比,JPEG文件相对简单,读取其中隐藏payload的方式大同小异,两者区别在于文件格式不同,可供利 ...

  9. LSB最低有效位隐写入门

    LSB也就是最低有效位 (Least Significant Bit) 被替换成传递的信息字节.对原图影响很小. 这题可以算是隐写工具[wbStego]的使用入门练习题吧. 第一步,告诉你工具是支持在 ...

随机推荐

  1. Spark学习摘记 —— RDD转化操作API归纳

    本文参考 在阅读了<Spark快速大数据分析>动物书后,大概了解到了spark常用的api,不过书中并没有给予所有api具体的示例,而且现在spark的最新版本已经上升到了2.4.5,动物 ...

  2. leetcode_两数相加

    给你两个 非空 的链表,表示两个非负的整数.它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字. 请你将两个数相加,并以相同形式返回一个表示和的链表. 你可以假设除了数字 0 ...

  3. C与C++的区别之函数调用堆栈

    函数调用栈 1.函数参数带入(入调用方函数的栈,从右向左入栈) int fun(int a); int fun(int a, int b); int fun(int a, int b, int c); ...

  4. 带你玩转prefetch, preload, dns-prefetch,defer和async

    现代浏览器性能优化-JS篇 众所周知,JS的加载和执行会阻塞浏览器渲染,所以目前业界普遍推荐把script放到</body>之前,以解决js执行时找不到dom等问题.但随着现代浏览器的普及 ...

  5. 常用 adb 命令总结

    1. 显示当前运行的全部模拟器:    adb devices    2.  安装应用程序:      adb install -r 应用程序.apk    3.  获取模拟器中的文件:      a ...

  6. 【Android开发】【布局】各种TabLayout样式

    Demo

  7. 大数据学习之路之ambari配置(三)

    添加了虚拟机内存空间 重装ambari

  8. Android:setOnItemClickListener cannot be used with a spinner报错

    错误原因: Spinner对象不支持使用setOnItemClickListener方法监听点击事项 解决方法: 使用setOnItemSelectedListener方法代替setOnItemCli ...

  9. java基础-多线程-线程组

    线程组 * Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制. * 默认情况下,所有的线程都属于主线程组.  * public fi ...

  10. node的两种随起随用静态服务器搭建

      一. anywhere Anywhere是一个随启随用的静态服务器,它可以随时随地将你的当前目录变成一个静态文件服务器的根目录. 1.确定电脑上安装了node.js 2.在当前所在项目文件夹下输入 ...