CBC Padding Oracle 攻击

0x01 题目来源

https://github.com/pbiernat/BlackBox/tree/master/Padz

0x02 解题过程

1、首先还是需要了解CBC加解密模式的基本流程

CBC加密:
CBC Padding Oracle 攻击_第1张图片

CBC解密:
CBC Padding Oracle 攻击_第2张图片

整个做题的目标四计算出中间结果,这需要从最后一个字节开始向前逐个字节计算。整个的理论原理参考了下文中的链接,这里不再赘述。

2、查看源码

CBC Padding Oracle 攻击_第3张图片

  • 输出唯一的密文,发现当输入有效的时候只会返回“VALID PADDING”而不会返回明文,这就涉及到CBC中的Padding Oracle攻击。

  • 依次改变最后一个字节,初始化IV为全零,然后利用填充从“0x01~0x10”进行异或,然后得到每一个中间值的字节值,共进行十六次,每次注意IV随着填充的改变。

  • 得到了中间值的时候,可以看一下加密的过程,将中间值与前一个的密文进行异或,得到的就是这一个分组的明文,由于我们已知flag在中间的一个分组,因此,下面的代码就知识对中间的一个密文分组进行了解密,如果不知道,需要对其他的分组做同样的操作。

  • 其实掌握了Padding Oracle的原理,编写代码也还是可以完成的,需要注意字节前面是零或者字节就是零的时候的,计算机识别的问题。

0x03 编写代码

在写代码的时候经过了很多次的调试,首先用的是笨办法,需要修改16次代码,后来完善了此版本,很多注释是调试的时候用的。

import socket

def str2num(s):
    return int(s.encode('hex'),16)
def num2str(n):
    d = ('%x' % n)
    if len(d) % 2 == 1:
        d = '0' + d
    return d

def func(j,z):
    x = "00"
    for i in range(255):
        y = "parse:"+"00"*j + x + z+"ef2c6db9d0bc134f752a119899160b72"
        client.send(y)
        data = client.recv(1024)
        if data == "VALID PADDING":
           # print i, hex(i)
            return i
        x = int(x, 16) + 1
        x = num2str(x)

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 9004))

client.send("get:AAAAAAA")
data = client.recv(1024)
print data

client.send("parse:f9b6e7556dd0fa9038ac346e849cc5c1ef2c6db9d0bc134f752a119899160b7217a36290f3ed054ca48f1b052578b644")
data = client.recv(1024)
print data

sum = 16
j = 15
k = 1
tmp = "01" # from 1 to \x10
string_s = ""
string_mid = ""
z = ""
while(sum):
    confir = num2str(func(j,z))
   # print confir
    string_s = str(confir) 
    #print "string_s:"+string_s
    #print "string_mid:"+string_mid
    #print tmp*k
    string_mid = str(hex(int(string_s,16)^int(tmp,16)))+string_mid

    print "string_mid:" + string_mid
    tmp = int(tmp, 16) + 1
    tmp = num2str(tmp)
    string_mid = string_mid[2:].replace('L','')
    if len(string_mid)%2 !=0:
    string_mid = "0"+string_mid
    #print string_mid
    #print tmp
    temp = len(z)+3

    z = str(hex(int(string_mid,16)^int(tmp*k,16)))
    z = z[2:].replace('L','')
    if temp == len(str(hex(int(string_mid,16)^int(tmp*k,16)))):
    z = "00" + z
    if len(z)%2 !=0:
    z = "0"+z
    #print "z:"+z
    j = j-1
    k = k+1
    sum = sum-1
#func(j,z)

client.close()

0x06 得到flag

运行脚本以后得到中间值,这里显示了16轮的中间值:
CBC Padding Oracle 攻击_第4张图片

将上图的最后一轮的中间值与密文的前16个字节进行以后,得到的就是我们要的flag。

0x05 参考资料

http://www.freebuf.com/articles/web/15504.html
http://blog.zhaojie.me/2010/10/padding-oracle-attack-in-detail.html

你可能感兴趣的:(CTF中的密码学)