• 2020湖湘杯-CRYPTO-简单的密码3 WriteUp (CBC字节翻转)


    前言

    第六届湖湘杯的密码学 简单的密码3

    这道题考察CBC字节翻转。

    CBC模式

    CBC是一种分组加密模式,CBC模式中,每一组的密文由上一组的密文参与异或运算得到。

    CBC字节翻转攻击就是根据CBC解密过程中的异或关系,改变上一组密文,从而使下一组解密得到的明文达到特定的值。

    加密过程

    第一组明文经过初始化向量IV异或,然后经过块加密算法使用密钥Key加密,得到第一组密文。然后这一组密文又和下一组明文异或,再经过块加密算法加密,得到下一组密文,以此类推。

    CBC模式中分组的长度,根据所用块加密算法的不同而有区别,比如AES-128的分组长度就是16字节。

    块加密算法一般是AES、Blowfish、DES、Triple DES等对称加密算法。

    初始化向量IV的长度等于分组长度,用于对加密进行随机化。加密时,IV可以影响到所有数据的加密结果。

    CBC加密的数学公式为:((E_k)表示块加密)

    [egin{aligned} &C_i = E_k(P_i oplus C_{i-1})\ &C_0 = IV end{aligned} ]

    解密过程

    第一组密文经过块加密算法使用密钥Key解密后,再经过初始化向量IV异或,得到第一组明文。第二组密文经过解密后,与第一组密文异或,得到第二组明文。以此类推,每一组明文都是由前一组密文参与异或运算得到的。

    解密时,IV只能影响第一组数据的解密结果。

    CBC解密的数学公式为:((D_k)表示块解密)

    [egin{aligned} &P_i = D_k(C_i) oplus C_{i-1}\ &C_0 = IV end{aligned} ]

    CBC字节翻转攻击

    通过改变前一组密文,使得其在与后一组密文的块解密结果异或后,得到特定的明文。

    具体为:

    假设某一组明文原来是(P_1),现在要将它变成(P_2),该组密文的块解密结果为(D_c),前一组密文原来是(C_1),需要将前一组密文构造为(C_2)

    根据异或运算的性质:


    (a oplus b = c)

    (a oplus c = b)

    由于

    [egin{aligned} &P_1 = C_1 oplus D_c\ &P_2 = C_2 oplus D_c end{aligned} ]

    可得

    [C_2 = C_1 oplus P_1 oplus P_2 ]

    因此只要将前一组密文替换为(C_2),就可以让后一组明文变成(P_2)

    由于改变了一组密文后,该组明文也会发生改变,要想使该组明文不变,执行相同的操作即可(修改前一组密文)。

    题目

    本题用nc连上后,给你三个选项,先输入用户名登陆,然后可修改iv,然后可获取flag。

    直接选flag,会提示只有admin才能获取flag。输入用户名为admin,又提示error。

    其实看到iv就可以猜测这个题是考CBC了。

    这里用CBC反序列化,先输入一个用户名,然后输入iv使得用户名解密后成为admin。

    输入iv时可以看到,iv的长度是16字节,因此明文第一组的长度也是16字节。

    输入用户名时,可知加密内容是"name:"+用户名,总长度不超过16字节,因此用户名在第一组明文中。我们只要修改iv就可以使用户名的解密结果成为admin。

    假设原来的iv是(IV_1),要构造的iv是(IV_2),第一组的块解密结果是(D_c),原明文是(P_1)(输入的用户名),要修改为(P_2)(admin)。

    由于

    [egin{aligned} &P_1 = IV_1 oplus D_c\ &P_2 = IV_2 oplus D_c end{aligned} ]

    可得

    [IV_2 = IV_1 oplus P_1 oplus P_2 ]

    注意这里第一组明文的前五个字节是"name:",我们输入的用户名从第六个字节开始,因此对iv的修改也应该从第六个字节开始。比如输入用户名为"world"的话,就应该修改iv中的第6到10个字节。

    python脚本为:

    iv1 = 'b1652f353cc1eac21e1e812fc0d51d7e'
    p1 = 'world'
    p2 = 'admin'
    iv2 = ''
    n = 0
    for i in range(10,20,2):
       iv2 += hex(int(iv1[i:i+2],16)^ord(p1[n])^ord(p2[n]))[2:]
       n += 1
    print(iv1[:10]+iv2+iv1[20:])
    

    得到iv:

    输入用户名和iv就可以获取flag。


    (由于比赛结束后,平台关闭,无法复现,这里用的是船山院士师傅们的wp中的图)

  • 相关阅读:
    线程中常见的方法
    停止线程方式
    线程间的通信_多生产者多消费者问题_JDK1.5新特性_Lock
    1-为什么java的main方法必须是静态的
    45-机器设计问题(深搜)
    44-最大差值三角形
    23-吝啬的国度(vector+深搜)
    43-八数码
    41-安排车辆
    41-邮差送信(dfs)
  • 原文地址:https://www.cnblogs.com/lnjoy/p/cbc_byte_flipping.html
Copyright © 2020-2023  润新知