base64是怎么编码的?
base64是怎么解码?
又是如何实现隐写的?

例题

攻防世界 - base64stego

import base64


ciperText = ""  # base64字串

maps = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
binary = ""
for l in ciperText.splitlines():
    plainCode = base64.b64encode(base64.b64decode(l)).decode().replace("=", "")[-1]
    cryptoCode = l.replace("=", "")[-1]
    t = abs(maps.index(plainCode) - maps.index(cryptoCode))
    if l.count("="):
        binary += bin(t)[2:].zfill(l.count("=") * 2)

print(binary)
flag = "".join([chr(int("0b{0}".format(binary[b:b+8]), 2)) for b in range(0, len(binary), 8)]).replace("\00", "")
print("flag{" + flag + "}")

原理

  • base64是怎么编码的?
  1. 字符对应ASCII转换成八位二进制( base64的基础单位是3 * 8bit的二进制,若是不够3 * 8bit则在后面添加0字节(padding)直至满足)(例如:字符A-->八位二进制01000001不够3 * 8即不够24位后面补0直到满足3 * 8即 01000001 00000000 00000000)
  2. 3 * 8bit的二进制转换成4 * 6bit的二进制(01000001 00000000 00000000-->010000 010000 000000 000000)
  3. 4 * 6bit的二进制转换成十进制(010000 010000 000000 000000-->16 16 0 0)(注意后面的两个0在下一步不会变成base64对照表里的A而是你自己加上去的要变成等号(=))
  4. 对照base64表把十进制转换成字符(16 16 0 0-->Q Q = = )

就是说3个字符的字符串base64编码之后会转成4个字符的base64编码

  • base64是怎么解码
  1. 检查base64编码后面有几个=
  2. 把字符串按照base64表转换成4*6的倍数位数二进制
  3. 删除counts('=') * 8的bit
  4. 按照6bit一组转成字符

关键就是,解码的时候,会删除counts('=') * 8的bit,而且我们只用6个bit表示一个等于号(000000),那么,意思就是我们可以控制counts('=') * 2bit的字符
看图片上的两个例子:

img

如图,那么我们就可以在加粗的0的位子用二进制隐写(改成其他的二进制数)。这样子做,不影响原文的还原(因为解码的时候加粗位置被改的数是要被删除的),唯一的区别就是,上图的QQ==中第二个Q会变化,QkM=的M会变化,所以base64可以用于隐写

练习

  • ✈️ [ACTF新生赛2020]base64