CBC 字节翻转攻击
CBC 字节翻转攻击的记录
原理
CBC 模式就不多说了,只放解密过程
可以看到,当修改前一个 Block1 时,会影响下一个 Block2 的解密,因为前一个 Block1 是作为后一块 Block2 的 IV 的
这就是字节翻转攻击开始发挥作用的地方
如果我们改变 Block1 的一个字节,然后与下一个解密后的组块 Block2 异或,我们就可以得到一个不同的明文了
栗子
M = a:2:{s:4:"name";s:6:"sdsdsd";s:8:"greeting";s:20:"echo 'Hello sdsdsd!'";}
我们的目标是将 s:6
当中的数字 6 转换成数字 0。我们需要做的第一件事就是把明文分成 16 个字节的块:
Block 1:a:2:{s:4:"name";
Block 2:s:6:"sdsdsd";s:8
Block 3::"greeting";s:20
Block 4::"echo 'Hello sd
Block 5:sdsd!'";}
我们的目标字符位于块 2,这意味着我们需要改变块 1 的密文来改变第二块的明文。
知道改哪了,那么要改成啥呢?
设图中第一个红块为 C1,它对应的明文块为 M1
第二个红块为 M2,它经过加密函数后的值记为 I(还没经过异或的值),它对应的密文块为 C2
根据这个流程,可知:
C1 ^ I = M2
对应上面的那个例子,就是
C1 为'2'对应的密文
I 为'6'经过加密函数后的值
M2 即为'6'
我们要求 C1'的值,根据异或特性,有
C1' = M2' ^ I = M2' ^ C1 ^ M2
要想使'6'成为我们想要得到的值,C1' 就要满足上述条件
代码
Attack
Attack.py 是攻击脚本
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# -*- coding: cp936 -*-
from Server import *
from re import findall
from Crypto.Util import strxor
# 将位于第 Block 个块中第 loc 个字符修改为 char
Block = 1
loc = 7
char = '0'
rawM = '''a:2:{s:4:"name";s:6:"sdsdsd";s:8:"greeting";s:20:"echo 'Hello sdsdsd!'";}'''
#-------------------------------------------------------------------------
print '[!]将 rawM 中的 s:4:"name"; 改为 s:0:"name";'
Blockn, b = divmod(len(rawM), 16)
if b: Blockn = Blockn + 1
rawM = rawM[::-1].zfill(Blockn * 16)[::-1]
C = CreateC(rawM)
print '[+]The rawM is:'
splitM = findall('.{16}', rawM)
for m in splitM: print ' [-]' + m
print '[+]The rawC is:'
splitC = findall('.{32}', C)
for c in splitC: print ' [-]' + c
changeBlock = findall('.{2}', splitC[Block - 1])
print '[!]Block', Block - 1, 'loc', loc, 'char had changed from', changeBlock[loc], 'to',
changeBlock[loc] = hex(int(changeBlock[loc], 16) ^ ord(rawM[(Block-1) * 16 + loc]) ^ ord(char))[2:].zfill(2)
print changeBlock[loc]
splitC[Block-1] = ''.join(changeBlock)
modifyC = ''.join(splitC)
print '[+]The attackedC is:'
for c in findall('.{32}', modifyC): print ' [-]' + c
CheckM = Check(modifyC.decode('hex'))
print '[+]The attacked M is:'
for c in findall('.{16}', CheckM[16:]): print ' [-]' + c
print '[!]All Done!'
模拟服务端
Server.py 对传入的 M 进行加密,使用随机的 Key 以及 IV,并返回解密的密文
1 |
|
结果
1 |
|
来呀快活呀