美文网首页
Base64隐写原理和提取脚本

Base64隐写原理和提取脚本

作者: A04 | 来源:发表于2019-11-01 00:12 被阅读0次

一、Base64编解码过程
  base64编码,是把字符对应的ascii码转换成8bit二进制数,把这些字符串转换后的二进制数,通过补0,使得整个二进制字符串是6的倍数,可能需要补16个0,也可能只需要补8个0;再将这串长度是6的倍数的二进制字符串,每6位二进制数,按照base64的字符表,转换为对应的字符,末尾补16个0的情况,会有两个6位全0的二进制字符串,这两个转换为=;末尾补8个0的情况,会有一个6位全0的二进制字符串,这一个转换为=。

编码前:A
转二进制:01000001
补0使长度为6的倍数:01000001 00000000 00000000
6bit为单位分割:010000 010000 000000 000000
base64字符表转换:QQ==

编码前:AB
转二进制:01000001 01000010
补0使长度为6的倍数:01000001 01000010 00000000
6bit为单位分割:010000 010100 001000 000000
base64字符表转换:QUI=

base64字符表:每个字符序号的二进制数,即为该字符base64编解码时对应的6位二进制数;
如字符a,在字符表中排26(序号从0开始),对应的二进制数为011010。
b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

  base64解码,将base64字符串的每个字符,按照base64字符表转换为二进制数,每个等号转换为6个0,将这个二进制字符串,每8位二进制数,按照ascii表,转换为对应的字符;如果base64字符串结尾为一个等号,则二进制字符串的最后8个0,直接去掉,因为是编码的时候补充的;如果base64字符串结尾为两个等号,则二进制字符串的最后16个0,直接去掉;

二、Base64隐写的原理
  编码时补充了0增加等号,解码时去除等号并对应删除编码时补充的0,正因为这一点,使隐写成为可能。

编码前:A
转二进制:01000001
补0使长度为6的倍数:01000001 00000000 00000000
6bit为单位分割:010000 010000 000000 000000  
(第2个6位二进制字符串010000,的后4个0,是属于补位0,解码时会被删除)

编码前:AB
转二进制:01000001 01000010
补0使长度为6的倍数:01000001 01000010 00000000
6bit为单位分割:010000 010100 001000 000000
(第3个6位二进制字符串001000,的后2个0,是属于补位0,解码时会被删除)

  上述所说的补位0所在的位置,加入我们修改为其他二进制数,而不是默认的全0,在做base64解码的时候,是不会影响解码结果的,因为这些补位0所在的位置,解码时都会被删除,所以不影响解码结果。
  所以我们想要隐藏信息的话,就可以利用这些补位0所在的位置,base64编码后的字符串,如果有1个等号,就有两个bit的补位0可隐写,如果有2个等号,就有四个bit的补位0可隐写;如果没有等号,就没有补位0可隐写。

三、Base64隐写解码案例
  了解了base64隐写原理,就可以对做了隐写的base64字符串做隐写位的提取。如以下案例,每个base64编码有一个等号,说明每行有两个bit的隐写位,将每行的两个bit隐写隐写位提取出来,即可破解隐写。

含有隐写的base64编码
YTUwZDllYTBhNTk5OWI0NmVlZmIzN2MzMDMzODlkZmR=
OTk4ODO0OmE4NWU0OTg1OTcyNjk1OzZlOWQ2ZDk5OWO=
NmZjOGJ3ZGUyODBmYmJ4ODYwZjMzZGU5NWUyZjdlNmJ=
ZDBhNDaxMzQ4NWRkZDM3a2a4ZjQwZTE0OWazM2IxMTa=
NzNlOTAzMGUwZDJwMjM3NzM0NjRmM2RhYzYxNDMxYjJ=
OTIwNzJkN2YwN2Y1Y2O0Y2Y2OjAxOTE5OGQ2NDE3NDO=
ZmIyOWIxY2Y0YTI2ZmU0Y2I2MGZiNTIzOTcxM2ZhNjT=
OWQ3NDRkOWEzNWI4NTYwYzIwYjI1ODA3Y2I5Njg4M2Q=
MjI4Z2Z3OTM0MjllMjM4NTM0NjZlNjNiZmUxZDJiZGZ=
YmQ2YjFlNjM1ZWY4YmQ4N2W0MWQ1NGIxODdkY2QwMjW=
ZmFiMTE4OTUyOTdkNjc0NmIwODAwMDdmYWE4MTFkZGU=
NDYzNGQ3NTMwNDZlMGJlNzhmNTMwM2MyMjk3ZjgwNzd=
MTUyZWNjYTViN2M5YWI1NjYzY2VlYTY1MzRxZmE0MjR=
ZGM3Yjk5YWQxNmYwMGU5MWVhYWQ4MDI1MGVlNjNjODC=
ZTc3NDg2MWZzODAwZjM1NTM3MGFlNDRjNDk0NjUxZmZ=
YTRlNjE3Y2E4ZWEwYWNkZTQ1M2QxYjM2YWFmN2U1MjD=
import re
import base64

b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

# ccc.txt为待解密的base64隐写字符串所在的文件
f = open('ccc.txt','r')
base64str = f.readline()

# pattern2用于匹配两个等号情况时,等号前的一个字符
# pattern2用于匹配一个等号情况时,等号前的一个字符
pattern2 = r'(\S)==$'
pattern1 = r'(\S)=$'

# 提取后的隐写二进制字符加入binstring中
binstring = ''

# 逐行读取待解密的base64隐写字符串,逐行处理
while(base64str):
    # 先匹配两个等号的情况,如果匹配不上,再配置一个等号的情况
    # 如果无等号,则没有隐藏,无需处理
    if re.compile(pattern2).findall(base64str):
        # mstr为等号前的一个字符,该字符为隐写二进制信息所在的字符
        mstr = re.compile(pattern2).findall(base64str)[0]
        # 确认mstr字符对应的base64二进制数,赋值给mbin
        mbin = bin(b64chars.find(mstr))
        # mbin格式如0b100,mbin[0:2]为0b
        # mbin[2:].zfill(6)为将0b后面的二进制数前面补0,使0b后面的长度为6
        mbin2 = mbin[0:2] + mbin[2:].zfill(6)
        # 两个等号情况隐写了4位二进制数,所以提取mbin2的后4bit
        # 赋值给stegobin,这就是隐藏的二进制信息
        stegobin = mbin2[-4:]
        binstring += stegobin
    elif re.compile(pattern1).findall(base64str):
        mstr = re.compile(pattern1).findall(base64str)[0]
        mbin = bin(b64chars.find(mstr))
        mbin2 = mbin[0:2] + mbin[2:].zfill(6)
        # 一个等号情况隐写了2位二进制数,所以提取mbin2的后2bit
        stegobin = mbin2[-2:]
        binstring += stegobin
    base64str = f.readline()

# stegobin将各行隐藏的二进制字符拼接在一起
# 从第0位开始,8bit、8bit处理,所以range的步进为8
for i in range(0,len(binstring),8):
    # int(xxx,2),将二进制字符串转换为10进制的整数,再用chr()转为字符
    print(chr(int(binstring[i:i+8],2)),end='')

相关文章

网友评论

      本文标题:Base64隐写原理和提取脚本

      本文链接:https://www.haomeiwen.com/subject/hdpxbctx.html