base64隐写

由NJCTF2017一道misc题引出的问题


先来看一下base64的概念

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(38 = 46 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
规则
关于这个编码的规则:
1.把3个字符变成4个字符
2.每76个字符加一个换行符
3.最后的结束符也要处理
4.10个数字,26个大写字母,26个小写字母,1个+,一个/刚好64个字符


例子
为方便理解,举下例子
转换前 11111011, 11101111, 10111110 (二进制)
首先按每6位分开 111110, 111110, 111110, 111110
再到最高位添加两个0
转换后 00111110, 00111110, 00111110, 00111110 (二进制)
上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。
转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
索引 对应字符
0 A
1 B
2 C
3 D
4 E
5 F
6 G
7 H
8 I
9 J
10 K
11 L
12 M
13 N
14 O
15 P
16 Q
17 R
18 S
19 T
20 U
21 V
22 W
23 X
24 Y
25 Z
26 a
27 b
28 c
29 d
30 e
31 f
32 g
33 h
34 i
35 j
36 k
37 l
38 m
39 n
40 o
41 p
42 q
43 r
44 s
45 t
46 u
47 v
48 w
49 x
50 y
51 z
52 0
53 1
54 2
55 3
56 4
57 5
58 6
59 7
60 8
61 9
62 +
63 /

 

虽然python解base64很方便
最好还是先写个脚本加深对base64的理解
文末我会贴出我的调试脚本

那么base64隐写到底是什么东西呢?

关键是base64解码的时候
1.检查base64编码后面有几个等于号
2.把字符串按照base64表转换成46的倍数位数二进制
3.__删除等于号的个数
8的bit__(等于号不在base64规定的范围内,只是为了补足长度,所以解码时要删除)
4.按照6个bit一组转成字符

此处的关键就是,解码的时候,会删除等于号的个数8的bit
且我们只用6个bit表示一个等于号(xxxxxx)
那么,意思就是我们可以控制__等于号个数
2bit__的字符

NJCTF2017有一道misc是base64隐写
从里面抽出一条来

1
2
3
4
5
import base64
s = "QnkgcmVhc29uIG9mIGhpcyBmYWxsZW4gZGl2aW5pdHm="
print base64.b64decode(s)
print s
print base64.b64encode(base64.b64decode(s))

 

会发现返回

1
2
3
By reason of his fallen divinity
QnkgcmVhc29uIG9mIGhpcyBmYWxsZW4gZGl2aW5pdHm=
QnkgcmVhc29uIG9mIGhpcyBmYWxsZW4gZGl2aW5pdHk=

 

会发现有区别,但是并不影响正常显示
来分析一下为啥,就拿我的昵称举例
首先是把每位字符转化成ascii的二进制形式

1
2
c | 0 | 1 | 4
01100011 | 00110000 | 00110001 | 00110100

 

进行base64编码时,按每6位分开,如果不能被6整除要用0补齐

1
2
011000 11|0011 0000|00 110001 | 001101 00
011000 | 110011 | 000000 | 110001 | 001101 | 000000

 

并且所有高位补两个0至8位

1
2
011000 | 110011 | 000000 | 110001 | 001101 | 000000
00011000 | 00110011 | 00000000 | 00110001 | 00001101 | 00000000

 

这样才能刚好用64个不同形式表示

1
2
00011000 | 00110011 | 00000000 | 00110001 | 00001101 | 00000000
Y | z | A | x | N | A

 

但是会发现字符只有6位数不够被4整除
所以到字符后面添加2个等号

1
2
YzAxNA
YzAxNA==

 

解密
先找出YzAxNA==每位字符在base64码表中的位置
由于等号没有我就不表示了

1
2
Y | z | A | x | N | A
011000 | 110011 | 000000 | 110001 | 001101 | 000000

 

将二进制连接起来并按每八位划分

1
2
011000110011000000110001001101000000
01100011 | 00110000 | 00110001 | 00110100 | 0000

 

会发现末尾多了等号数*2bit的0
这些0在解密时是要被删除的
所以base64隐写的精髓就是这几bit可控

1
2
3
4
5
YzAxNA==
YzAxNB==
YzAxNC==
......
YzAxNO==

 

解密的到的都是一样的结果

调试脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# -*- coding:utf-8 -*-
 
 
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
 
def encode(str):
s = str
s_bin = ""
for i in range(0,len(s)):
s_bin = s_bin + bin(ord(s[i])).replace( "0b","").rjust(8,"0") #把每个字符二进制化
print s_bin
 
if len(s_bin) % 6 != 0: #判断二进制长度能否被6整除
for j in range(1,6):
if (len(s_bin) + j) % 6 == 0:
bin_length = len(s_bin) + j #获取二进制长度
break
s_bin = s_bin.ljust(bin_length, "0") #把二进制长度补到能被6整除
print s_bin
 
encode = ""
for k in range(0,len(s_bin)/6):
index = k * 6
each_bin = s_bin[index:index+ 6].zfill(8) #把6Bit再添两位高位0
print each_bin
each_enc = int(each_bin, 2) #转化为10进制
print each_enc
encode = encode + base[each_enc]
 
# print encode
if len(encode) % 4 != 0: #判断解密后字符串是否能被4整除,如果不能,要在末尾加=
for l in range(1,4):
if (len(encode) + l) % 4 == 0:
encode_length = len(encode) + l
print encode.ljust(encode_length,"=")
 
def raw(str): #获取每位字符的二进制形式
s = str
for i in range(0,len(s)):
print s[i],bin(ord(s[i])).replace("0b","").rjust(8,"0")

转载于:https://www.cnblogs.com/Elope/p/6725824.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值