base64隐写

部分节选自https://www.tuicool.com/articles/RRr2miE
                  https://www.cnblogs.com/Pinging/p/7622871.html

1.原理

  • 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. 删除等于号的个数*8的bit
  4. 按照6个bit一组转成字符

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


1207957-20171002220446021-12904647.jpg

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

2.试试效果

下面的代码是对 UX==(X取A到Z)进行base64解码(python2.7)

import base64
b = ''
for i in range(26):
    b = 'U' + chr(65 + i) + '=='
    print b
    print base64.b64decode(b)
E:\App\py_workspace\venv\Scripts\python.exe E:/App/py_workspace/asdf.py
UA==
P
UB==
P
UC==
P
UD==
P
UE==
P
UF==
P
UG==
P
UH==
P
UI==
P
UJ==
P
UK==
P
UL==
P
UM==
P
UN==
P
UO==
P
UP==
P
UQ==
Q
UR==
Q
US==
Q
UT==
Q
UU==
Q
UV==
Q
UW==
Q
UX==
Q
UY==
Q
UZ==
Q

看出来啥了没
如果我要发给你一个Q那么我发UZ==可以,但是发UY==也可以,
看代码↓

# coding:UTF8
# import base64
import string


def decode(flag1):  # 把需要隐藏的密文变成二进制字符串
    list_flag1 = list(flag1)  # 把密文转为list例如:['I', ' ', 'a', 'm', ' ', 'a', ' ', 'C', 'T', 'F', 'e', 'r']
    list_dec_flag1 = []  # 十进制密文例如:[73, 32, 97, 109, 32, 97, 32, 67, 84, 70, 101, 114]
    for j in range(len(list_flag1)):  # 把ascii码密文转换为十进制密文list
        list_dec_flag1.append(ord(list_flag1[j]))
    list_bin_flag1 = []
    # 二进制密文例如:['1001001', '100000', '1100001', '1101101', '100000', '1100001', '100000', '1000011','1010100'...]
    for j in range(len(list_dec_flag1)):  # 把十进制密文转化为二进制密文
        list_bin_flag1.append((bin(list_dec_flag1[j])[2:]).zfill(8))
    str_bin_flag1 = ''.join(list_bin_flag1)  # 把二进制密文list拼接成str
    # 例如:010010010010000001100001011011010010000001100001001000000100001101010100010001100110010101110010
    list_bin_every_flag1 = list(str_bin_flag1)  # 把str二进制密文转换成list
    # 例如:['1', '0', '0', '1', '0', '0', '1', '1', '0', '0', '0', '0', '0', '1', '1', '0', '0', '0', '0', '1'...]
    return list_bin_every_flag1


if __name__ == '__main__':
    dic = string.uppercase+string.lowercase+string.digits+'+/'
    # a = raw_input()
    flag = 'I am a CTFer'
    list_bin_every_flag = decode(flag)  # list二进制密文
    # print len(list_bin_every_flag)
    # 例如:['1', '0', '0', '1', '0', '0', '1', '1', '0', '0', '0', '0', '0', '1', '1', '0', '0', '0', '0', '1'...]
    tip = 0  # 定义一个指针指向要写入base64的list二进制密文
    # tt = 0
    with open('hello.txt', 'rb') as h:  # 打开明文
        file_lines = h.readlines()  # 把明文读取成一行
        # 例如:['#include \r\n', '#include \r\n', 'main(){int i,n[]={(((1 <<1)<< (1<<1)...]
        for line in file_lines:  # 接下来是正文了
            normal_line = line.replace('\r\n', '')  # 每一行的明文
            # print normal_line
            # 例如:#include \r
            equal_sign_num = 3 - (len(normal_line) % 3)  # 每行base64加密后的等号数量
            if equal_sign_num == 3:  # 如果是3的倍数说明这一句没法进行隐写
                equal_sign_num = 0  # 设其等号数量为0
            # print 'equal_sign_num', equal_sign_num
            # tt += equal_sign_num * 2
            # print tt, 'tt'
            list_normal_line = decode(normal_line)  # 把明文也装换为list_bin_every_明文
            # print list_normal_line
            if equal_sign_num == 1:  # 一个等号
                for i in range(2):
                    # print 'tip', tip, 'list_bin_every_flag[tip]',list_bin_every_flag[tip]
                    list_normal_line.append(list_bin_every_flag[tip])
                    tip += 1
                # print list_normal_line
            elif equal_sign_num == 2:  # 两个等号
                for i in range(4):
                    # print 'tip', tip, 'list_bin_every_flag[tip]', list_bin_every_flag[tip]
                    list_normal_line.append(list_bin_every_flag[tip])
                    tip += 1
                # print list_normal_line
            # print tt
            str_bin_normal_line = ''.join(list_normal_line)
            # print str_bin_normal_line
            b64 = ''
            for i in range(0, len(str_bin_normal_line), 6):
                b64 += dic[int(str_bin_normal_line[i: i+6], 2)]  # 以6位为单位对照base64编码表
            if equal_sign_num == 1:
                b64 += '='
            elif equal_sign_num == 2:
                b64 += '=='
            print b64

效果如下

E:\App\py_workspace\venv\Scripts\python.exe E:/App/py_workspace/mybase64隐写.py
I2luY2x1ZGU8c3RkaW8uaD5=
I2luY2x1ZGUgPHN0ZGxpYi5oPi==
bWFpbigpe2ludCBpLG5bXT17KCgoMSA8PDEpPDwoMTw8MSk8PCgxPDx=
ICAgICAgIDEpPDwoMTw8KDE+PjEpKSkrKCgxPDwxKTw8KDE8PDEpKSksICgoKDE=
ICAgICAgIDw8MSk8PCgxPDwxKTw8KDE8PDEpPDwoMTw8MSkpLSgoMTw8MSk8PCi=
ICAgIAkxPDwxKTw8KDE8PDEpKSsoKDE8PDEpPDwoMTw8KDE+PjEpKSkrKDE8PCgxPj4xKSkpLA==
ICAgICAgICgoKDE8PDEpPDwoMTw8MSk8PCgxPDwxKTw8KDE8PDEpKS0oKDEgPDwxKW==
ICAgICAgIDw8KDE8PDEpIDw8KDE8PCgxPj4xKSkpLSgoMTw8MSk8PCgxPDwoMT4+MSkpKSkgLB==
ICAgICAgICgoKDE8PDEpPDwoMTw8MSk8PCgxPDwxKTw8KCAxPDwxKSktKCgxIDw8MSk8PG==
ICAgICAgICAoMTw8MSk8PCgxIDw8KDE+PjEpKSktKCgxPDwxKTw8KDE8PCgxPj4xKSkpKSAgLN==
ICAgICAgICAoKCgxPDwxKTw8KDE8PDEpPDwoMTw8MSk8PCgxPDwxKSktKCgxPDwxKSA8PC==
ICAgICAgICAoMTw8MSk8PCgxPDwoMT4+MSkpKS0oMTw8KDE+PjEpKSksKCgoMTw8MSk8PA==
ICAgICAgICAoMTw8MSk8PCgxPDwxKSkrKCgxPDwxKTw8KDE8PDEpPDwoMTw8KDE+PjEpKSkgLW==
ICAgICAgICAoKDE8PDEpPDwoMTw8KDE+PjEpKSkpLCgoMTw8MSk8PCgxPDwxKTw8KDE8PDEpKR==
ICAgICAgICwoKCgxPDwxKTw8KDE8PDEpPDwoMTw8MSk8PCgxPDwxKSktKCgxPDwxKTw8KDE8PDEpKS==
ICAgICAgIC0oMTw8KDE+PjEpKSksKCgoMTw8MSk8PCgxPDwxKTw8KDE8PDEpPDwoMTw8MSkpLSgoMQ==
ICAgICAgIDw8MSk8PCgxPDwxKTw8KDE8PCgxPj4xKSkpLSgxPDwoMT4+MSkpKSwgICgoKDE8PDF=
ICAgICAgICk8PCgxPDwxKTw8KDE8PDEpPDwoMTw8MSkpLSgoMTw8MSk8PCAoMQ==
ICAgICAgIDw8MSk8PCgxPDwoMT4+MSkpKSsoMTw8MSkpLCgoKDE8PDEpPDwoMTw8MSAgKd==
ICAgICAgIDw8KDE8PDEpPDwoMTw8MSkpLSgoMTw8MSk8PCgxPDwxKTw8KDE8PCgxPj4xKSkpLV==
ICAgICAgICgoMTw8MSk8PCgxPDwoMT4+MSkpKSksKCgoMTw8MSk8PCgxPDwxKSA8PCgxPDwxKR==
ICAgICAgIDw8KDE8PDEpKS0oKDE8PDEpPDwoMTw8MSk8PCgxPDwxKSkrICgoMR==
ICAgICAgIDw8MSk8PCgxPDwoMT4+MSkpKSksKCgoMTw8MSk8PCgxPDwxKSAgPDwoMZ==
ICAgICAgIDw8MSkpKygxPDwoMT4+MSkpKSwoKCgxPDwxKTw8KDE8PDEpKSAgKygoMZ==
ICAgICAgIDw8MSk8PCAoMTw8KDE+PjEpKSkgKygxPDwgKDE+PjEpKSl9O2Zvcl==
ICAgICAgIChpPSgxPj4xKTtpPCgoKDE8PDEpPDwoMTw8MSkpKygoMSAgPDwxKTw8KM==
ICAgICAgIDE8PCgxPj4xKSkpKygxPDwxKSk7aSsrKSAgIHByaW50ZigiJWMiLG5baV0pO32=

Process finished with exit code 0

附送大家一个输出hello,world的c语言程序

#include
#include 
main(){int i,n[]={(((1 <<1)<<(1<<1)<<(1<<
       1)<<(1<<(1>>1)))+((1<<1)<<(1<<1))), (((1
       <<1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<<(
        1<<1)<<(1<<1))+((1<<1)<<(1<<(1>>1)))+(1<<(1>>1))),
       (((1<<1)<<(1<<1)<<(1<<1)<<(1<<1))-((1 <<1)
       <<(1<<1) <<(1<<(1>>1)))-((1<<1)<<(1<<(1>>1)))) ,
       (((1<<1)<<(1<<1)<<(1<<1)<<( 1<<1))-((1 <<1)<<
        (1<<1)<<(1 <<(1>>1)))-((1<<1)<<(1<<(1>>1))))  ,
        (((1<<1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1) <<
        (1<<1)<<(1<<(1>>1)))-(1<<(1>>1))),(((1<<1)<<
        (1<<1)<<(1<<1))+((1<<1)<<(1<<1)<<(1<<(1>>1))) -
        ((1<<1)<<(1<<(1>>1)))),((1<<1)<<(1<<1)<<(1<<1))
       ,(((1<<1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<<(1<<1))
       -(1<<(1>>1))),(((1<<1)<<(1<<1)<<(1<<1)<<(1<<1))-((1
       <<1)<<(1<<1)<<(1<<(1>>1)))-(1<<(1>>1))),  (((1<<1
       )<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<< (1
       <<1)<<(1<<(1>>1)))+(1<<1)),(((1<<1)<<(1<<1  )
       <<(1<<1)<<(1<<1))-((1<<1)<<(1<<1)<<(1<<(1>>1)))-
       ((1<<1)<<(1<<(1>>1)))),(((1<<1)<<(1<<1) <<(1<<1)
       <<(1<<1))-((1<<1)<<(1<<1)<<(1<<1))+ ((1
       <<1)<<(1<<(1>>1)))),(((1<<1)<<(1<<1)  <<(1
       <<1))+(1<<(1>>1))),(((1<<1)<<(1<<1))  +((1
       <<1)<< (1<<(1>>1))) +(1<< (1>>1)))};for
       (i=(1>>1);i<(((1<<1)<<(1<<1))+((1  <<1)<<(
       1<<(1>>1)))+(1<<1));i++)   printf("%c",n[i]);}

3.解密的脚本如下:

def get_base64_diff_value(s1, s2):
    base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    res = 0
    for i in xrange(len(s2)):
        if s1[i] != s2[i]:
            return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))
    return res


def solve_stego():
    with open('3.txt', 'rb') as f:
        file_lines = f.readlines()
        bin_str = ''
        for line in file_lines:
            steg_line = line.replace('\n', '')
            norm_line = line.replace('\n', '').decode('base64').encode('base64').replace('\n', '')
            diff = get_base64_diff_value(steg_line, norm_line)
            print diff
            pads_num = steg_line.count('=')
            if diff:
                bin_str += bin(diff)[2:].zfill(pads_num * 2)
            else:
                bin_str += '0' * pads_num * 2
            print goflag(bin_str)


def goflag(bin_str):
    res_str = ''
    for i in xrange(0, len(bin_str), 8):
        res_str += chr(int(bin_str[i:i + 8], 2))
    return res_str


if __name__ == '__main__':
    solve_stego()

效果↓

E:\App\py_workspace\venv\Scripts\python.exe E:/App/py_workspace/Tools/base64隐写解密.py
1
�
2
�
1
I
0
I 
2
I�
0
I 
6
I �
1
I a
6
I a�
13
I am
2
I am�
0
I am 
6
I am �
1
I am a
2
I am a�
0
I am a 
1
I am a �
0
I am a �
13
I am a C�
5
I am a C�
1
I am a CT�
1
I am a CT�
9
I am a CTF�
9
I am a CTF�
5
I am a CTFe�
12
I am a CTFe�
2
I am a CTFer

Process finished with exit code 0

你可能感兴趣的:(base64隐写)