CBC字节翻转攻击介绍 例题

news2025/1/11 14:12:18

知识导入(AES-CBC模式)

在这里插入图片描述
在这里插入图片描述

加密过程

1、首先将明文分组(常见的以16字节为一组),位数不足的使用特殊字符填充。
2、生成一个随机的初始化向量(IV)和一个密钥。
3、将IV和第一组明文异或。
4、用key对3中xor后产生的密文加密。
5、用4中产生的密文对第二组明文进行xor操作。
6、用key对5中产生的密文加密。
7、重复4-7,到最后一组明文。
8、将IV和加密后的密文拼接在一起,得到最终的密文。

解密过程

(加密的逆过程)

设明文为X,密文为Y,解密函数为k。

X[i] = k(Y[i]) Xor Y[i-1]

CBC字节翻转攻击原理

对于CBC模式的解密算法,每一组明文进行分组算法解密之后,需要和前一组的密文异或才能得到明文。第一组则是和初始向量IV进行异或。

CBC字节翻转攻击的核心原理是通过破坏一个比特的密文来篡改一个比特的明文。攻击流程可参考下图:
在这里插入图片描述
可知: A ⊕ B = C 若想要改变输出的明文 C ,那么只需改变密钥 A 即可 那么要如何改变 A 呢? 我们从明文 C 入手,假设改变后的 C 为 C ′ , A 为 A ′ ,那么: 可知:A\oplus B = C\\若想要改变输出的明文C,那么只需改变密钥A即可\\那么要如何改变A呢?\\我们从明文C入手,假设改变后的C为C^{\prime},A为A^{\prime},那么: 可知:AB=C若想要改变输出的明文C,那么只需改变密钥A即可那么要如何改变A呢?我们从明文C入手,假设改变后的CCAA,那么:
C ′ = C ⊕ C ⊕ C ′ = A ⊕ B ⊕ C ⊕ C ′ = B ⊕ A ⊕ C ⊕ C ′ 令 A ′ = A ⊕ C ⊕ C ′ ⟹ A ′ ⊕ B = C ′ ( 翻转成功 ) ( 注意 : B 不管怎么样都是不变的 ) \begin{aligned}C^{\prime}&=C\oplus C\oplus C^{\prime}\\&=A\oplus B\oplus C\oplus C^{\prime}\\&=B\oplus A\oplus C\oplus C^{\prime}\\&令A^{\prime}=A\oplus C\oplus C^{\prime}\\&\Longrightarrow A^{\prime}\oplus B=C^{\prime}(\text{翻转成功})\end{aligned}\\(注意:B不管怎么样都是不变的) C=CCC=ABCC=BACCA=ACCAB=C(翻转成功)(注意:B不管怎么样都是不变的)
总结: 只要把 A 改变成 A ′ = A ⊕ C ⊕ C ′ 便能将输出的明文从 C 变为 C ′ 总结:\\只要把A改变成A^{\prime} = A\oplus C\oplus C^{\prime}\\便能将输出的明文从C变为C^{\prime} 总结:只要把A改变成A=ACC便能将输出的明文从C变为C

题一(NewStarCTF flip-flop)

题目描述:

import os
from Crypto.Cipher import AES
auth_major_key = os.urandom(16)
from flag import secret
BANNER = """
Login as admin to get the flag ! 
"""

MENU = """
Enter your choice
[1] Create NewStarCTF Account
[2] Create Admin Account
[3] Login
[4] Exit
"""

print(BANNER)
def bxor(b1, b2): # use xor for bytes
    result = b""
    for b1, b2 in zip(b1, b2):
        result += bytes([b1 ^ b2])
    return result
while True:
    print(MENU)

    option = int(input('> '))
    if option == 1:
        auth_pt = b'NewStarCTFer____'
        user_key = os.urandom(16)
        cipher = AES.new(auth_major_key, AES.MODE_CBC, user_key)
        code = cipher.encrypt(auth_pt)
        print(f'here is your authcode: {user_key.hex() + code.hex()}')
    elif option == 2:
        print('GET OUT !!!!!!')
    elif option == 3:
        authcode = input('Enter your authcode > ')
        user_key = bytes.fromhex(authcode)[:16]
        code = bytes.fromhex(authcode)[16:]
        cipher = AES.new(auth_major_key, AES.MODE_CBC, user_key)
        auth_pt = cipher.decrypt(code)
        if auth_pt == b'AdminAdmin______':
            a = user_key.hex() + code.hex()
            print(a)
        elif auth_pt == b'NewStarCTFer____':
            print('Have fun!!')
        else:
            print('Who are you?')
    elif option == 4:
        print('ByeBye')
        exit(0)
    else:
        print("WTF")

题目分析:

可以看出只要明文输出为 可以看出只要明文输出为 可以看出只要明文输出为b’AdminAdmin______‘, 即可得到 a , a 便是我们需要的 f l a g 即可得到a,a便是我们需要的flag 即可得到a,a便是我们需要的flag
现在我们已知①变换后的明文 现在我们已知①变换后的明文 现在我们已知变换后的明文b’NewStarCTFer____‘ ②变换前的明文 ②变换前的明文 变换前的明文b’AdminAdmin______‘ ③密文④ i v ,毫无疑问 C B C 字节翻转攻击 ③密文④iv,毫无疑问CBC字节翻转攻击 密文iv,毫无疑问CBC字节翻转攻击
A ′ = A ⊕ C ⊕ C ′ ,其中: A^{\prime} = A\oplus C\oplus C^{\prime},其中: A=ACC,其中:
C = b’NewStarCTFer____’
C’ = b’AdminAdmin______’
A = iv
A,C,C’都知道了,那么A’也就知道了,这题很容易就出来了

def strxor(a1, a2): 
    return bytes([b1 ^ b2 for b1,b2 in zip(a1,a2)])
authcode =
user_key = bytes.fromhex(authcode)[:16]
code = bytes.fromhex(authcode)[16:]
user_key=strxor(user_key,b'AdminAdmin______')
user_key=strxor(user_key,b'NewStarCTFer____')
authcode=user_key.hex()+code.hex()
print(authcode)

变换后的authcode出来了提交即可得到flag

题二

题目描述:

import socketserver
import os, sys, signal
import string, random
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
from secret import flag

key = os.urandom(32)

def decrypt(ciphertext,iv):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    print(cipher.decrypt(ciphertext))
    decrypted = unpad(cipher.decrypt(ciphertext),16)
    if decrypted[23:31]==b'lingfeng' and decrypted[40:46]==b'123456':
        a=b'welcome!,you are right!\n this is your flag\n'
        return a+flag
    else:
        return decrypted
def encrypt(c):
    iv = os.urandom(16)
    payload = pad(c,16)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted = cipher.encrypt(payload)
    return iv.hex() + encrypted.hex()

class Task(socketserver.BaseRequestHandler):
    def _recvall(self):
        BUFF_SIZE = 2048
        data = b''
        while True:
            part = self.request.recv(BUFF_SIZE)
            data += part
            if len(part) < BUFF_SIZE:
                break
        return data.strip()

    def send(self, msg, newline=True):
        if type(msg) is str:
            msg = msg.encode()
        try:
            if newline:
                msg += b'\n'
            self.request.sendall(msg)
        except:
            pass

    def recv(self, prompt=b'> '):
        self.send(prompt, newline=False)
        return self._recvall()

    def close(self):
        self.send(b"Bye~")
        self.request.close()

    def handle(self):
        menu = '''1.register\n2.login\n'''
        for _ in range(3):
            self.send('\n' + menu)
            try:
                r = int(self.recv())
            except:
                continue
            if r == 1:
                self.send(b'please input your username')
                username=self.recv().strip()
                if username==b'lingfeng':
                    self.send(b'no,you is not lingfeng')
                    continue
                self.send(b'please enter your password')
                password=self.recv().strip()
                m1=b'{"permission":username:'+username+b'password:'+password+b'}'
                self.send(encrypt(m1))
            elif r == 2:
                self.send(b'please enter your encrypted: ')
                m2=self.recv().strip().decode()
                iv=bytes.fromhex(m2[:32])
                data=bytes.fromhex(m2[32:])
                self.send(decrypt(data, iv))
            else:
                self.send(b'please input again')
        self.close()
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

class ForkedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

if __name__ == "__main__":
    
    HOST, PORT = '0.0.0.0', 80
    server = ForkedServer((HOST, PORT), Task)
    server.allow_reuse_address = True
    server.serve_forever()

题目分析:

(PS:非预期解,username = lingfeng111111111123456 即可得到,不是本文重点,下面以预期解来讲述)
本题流程和上题一样, u s e r n a m e 自己随便输,但不能是 l i n g f e n g 假设 u s e r n a m e = 0 i n g f e n g 我们要通过 C B C 字节翻转将最终明文 0 i n g f e n g 变为 l i n g f e n g 本题流程和上题一样,username自己随便输,但不能是lingfeng\\假设username = 0ingfeng\\我们要通过CBC字节翻转将最终明文0ingfeng变为lingfeng 本题流程和上题一样,username自己随便输,但不能是lingfeng假设username=0ingfeng我们要通过CBC字节翻转将最终明文0ingfeng变为lingfeng
现在我们已知①变换后的明文 现在我们已知①变换后的明文 现在我们已知变换后的明文b’lingfeng’ ②变换前的明文 ②变换前的明文 变换前的明文b’0ingfeng’ ③密文④ i v ,毫无疑问 C B C 字节翻转攻击 ③密文④iv,毫无疑问CBC字节翻转攻击 密文iv,毫无疑问CBC字节翻转攻击
A ′ = A ⊕ C ⊕ C ′ ,其中: A^{\prime} = A\oplus C\oplus C^{\prime},其中: A=ACC,其中:
C = b’0’
C’ = b’l‘
A = iv
(因为0ingfeng和lingfeng后面一部分一样,不需要翻转,翻转首字母即可)
注意!!!此处的iv是前一块密文,并不是初始向量
分块为1-16,17-32,此时0的位置为24,那么前一个密文相对应的位置是8,bytes转16进制长度变为2倍,在输出的encrypt中前32位是初始向量,encrypt[46,48]是0的前一个密文相对应的位置(好吧,确实有些拗口),总之iv不一定是初始向量,看流程图也能知道iv总是变化的

我的(哈哈哈,太low了):

encrypt = '598a4ebb9cd737b35e64b64522a2a0eb9d324530fda1dd2a1f712dc1b2b80291912eb35dc912ae1359b5affc6aebc989b66a55437c0ecf76246f37ccbf99ccf0'
password = 123456
iv_bytes = bytes.fromhex(encrypt[:32])
encrypt = 'b14bcfb810c6df7c2241ab1f9d37daace87ab04a67fe9dfd89835d0212078c0ade230b479e7eaf409c39d167062941f0ef17a798c440a1df616d15761a2833cb'
new_encrypt = encrypt[:46] + hex(int(encrypt[46:48],16) ^ ord('0') ^ ord('l'))[2:] + encrypt[48:]
print(new_encrypt)

官方的:

from pwn import *
sh = remote('39.105.144.62', 718)
sh.sendlineafter(b'>', b'1')
sh.sendlineafter(b'>', b'1ingfeng')
sh.sendlineafter(b'>', b'123456')
a = sh.recvline().decode().strip()

a = a[:32]+a[32:46]+hex(int(a[46:48],16)^ord('1')^ord('l'))[2:]+a[48:]
sh.sendlineafter(b'>', b'2')
sh.sendlineafter(b'>', a.encode())
sh.interactive()  # flag{31be9656-81bb-4e8b-9d5e-db84f21184b2}

浅记一下:

做题过程中发现一个好玩的

for i in b'kdlsjf':
    print(i) # 107 100 108 115 106 102
    
for b1, b2 in zip(b'dsk', b'kdj'):
    print(b1, b2)

输出结果是每个字节对应的整数值,我说怎么有时字节异或报错,有时又不报错,原来是这个原因

还发现一个好玩的

long_to_bytes(8)bytes(8)bytes([8])# 输出结果:
b'\x08'
b'\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x08'

①③输出结果相同,②比较特立独行,我说怎么用bytes()还给我报错,原来是这个原因,哈哈

  • long_to_bytes():用于将长整数转换为对应的字节对象。在这个例子中,将整数 8 转换为字节对象。

  • bytes():可以创建一个指定长度的字节对象,其中每个字节初始化为零。在这个例子中,创建了一个长度为 8 的字节对象。

  • bytes([ ]):不同的是,它接受一个整数列表作为参数,列表中的整数会被转换为相应的字节值。在这个例子中,创建了一个只包含一个字节值为8 的字节对象

又给我学到了,继续加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/787188.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大厂案例 - 腾讯万亿级 Elasticsearch 架构实践

文章目录 概述提纲益处正文一、Elasticsearch 简介0. 应用领域搜索引擎可观测性安全检测发展现状 1.系统架构集群架构物理数据模型查询 2.腾讯应用现状搜索领日志实时分析时序数据 二、技术挑战1.可用性2.成本3.性能 三、架构设计实践1.可用性优化1.1 解决方案2.2 集群扩展性2.…

RK3588平台开发系列讲解(LCD篇)LCD的分辨率和像素格式

文章目录 一、分辨率二、像素格式三、LCD成像步骤四、LCD屏幕时序4.1、行显示时序4.2、帧显示时序沉淀、分享、成长,让自己和他人都能有所收获!😄 📢液晶 LCD 显示器是由两片平行的玻璃基板组成,两片平行的玻璃基板之间放置了一个液晶盒。在下基板玻璃上,有一组被称为薄…

【Postman】- 基本用法

一、用例集 1.1 用例集 Collections&#xff1a;用例集。目录下可以创建子目录。 1.2 导出用例集 1.3 导入用例集 二、Postman断言 断言&#xff1a;让程序判断预期结果和实际结果是否一致 2.1 特点 Postman的断言是使用JavaScript语言编写的&#xff0c;写在"Tests&…

Jvm参数优化

Jvm参数优化 背景1. 系统上线规划容量- 分析 2. 垃圾回收器选择吞吐量和响应时间垃圾回收器选择 3. 规划各个分区的比例大小4. 对象年龄对少移动到老年代合适5. 对象多大放到老年代6. 垃圾回收器CMS老年代参数优化7. 配置OOM时的内存dump文件和GC日志8. 通用JVM参数模板 背景 …

任务的调度 和 任务的状态

任务的调度 Q: 什么是任务调度&#xff1f; A: 调度器就是使用相关的调度算法来决定当前需要执行的哪个任务。 FreeRTOS中开启任务调度的函数是 vTaskStartScheduler() &#xff0c;但在 CubeMX 中被封装为 osKernelStart() 。 这个“osKernelStart()”就是在main.c中main函…

MyBatis源码分析_ResultSetHandler(7)

1. 传统JDBC Mybatis其实就是封装传统JDBC的&#xff0c;它和传统JDBC访问数据库基本一模一样。因此&#xff0c;不要觉得Mybatis有多高级。而 ResultSetHandler 就是处理我们JDBC访问数据库获取到的ResultSet结果集的。在此之前&#xff0c;我们还是先看一下传统JDBC&#xf…

5.2.10.应用程序如何调用驱动 mknod /dev/test c 250 0 创建设备文件,应用app 程序 调用 我们 驱动 壳子

5.2.10.应用程序如何调用驱动 5.2.10.1、驱动设备文件的创建 (1)何为设备文件 索引驱动 (2)设备文件的关键信息是&#xff1a;设备号 主设备号 次设备号&#xff0c;使用ls -l去查看设备文件&#xff0c;就可以得到这个设备文件对应的主次设备号。 4颗LED不可能 都占用 主设备…

【深度学习】日常笔记14

对神经网络模型参数的初始化方案对保持数值稳定性有很重要的作用。初始化⽅案的选择可以与⾮线性激活函数的选择有趣的结合在⼀起。 突然有感触&#xff1a;做习题和模拟考研就分别是训练集和验证集&#xff0c;考研不就是最后的测试集&#xff08;&#xff09; p168的↓的解释…

【计算机编程语言】JAVA-MyBatis(Eclipse)

文章目录 MyBatis1.简介1.1什么是Mybatis1.2持久化1.3持久层1.4为什么需要Mybatis 2.第一个Mybatis程序2.1搭建环境2.1.1.搭建数据库&#xff1a;2.1.2.新建项目&#xff08;工程&#xff09;2.1.3导入依赖 2.2创建一个模块2.2.1.编写Mybatis的核心配置文件2.2.2.编写Mybatis的…

linux学成之路(基础篇(二十三)MySQL服务(下)

目录 MySQL服务之SQL语句 一、SQL语句类型 一、 DDL语句 二、DML语句 三、DCL语句 四、DQL 语句 二、 数据库操作 一、查看 二、创建 三、进入 四、删除数据库 五、更改数据库名称 六、更改字符集 三、数据表管理 一、数据类型 一、数值类型 TINYINT SMALLINT…

JUC并发编程之CompletableFuture详解

目录 1.Future接口 1.1 Future介绍 1.1.1 FutureTask 1.1.2 代码示例 2. CompletableFuture 2.1 基本概念 2.2 代码示例 2.2.1 创建CompletableFuture 2.2.2 函数式接口&#xff08;补充&#xff09; 2.2.3 异步任务组合 1.Future接口 1.1 Future介绍 JUC并发编程中的…

(三)InfluxDB入门(借助Web UI)

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 3 章 InfluxDB入门&#xff08;借助Web UI&#xff09; 借助Web UI&#xff0c;我们可以更好地理解InfluxD…

SiddonGpu编译过程记录

1. 还是想要能够快速生成DRR&#xff0c;用了这个up的代码GitHub - fabio86d/CUDA_DigitallyReconstructedRadiographs: GPU accelerated python library for generation of Digitally Reconstructed Radiographs (March 2018) 在看步骤的时候不是很清晰。尤其是procedure to…

生产环境Session解决方案、Session服务器之Redis

目录 一、服务器配置 二、安装nginx 三、安装配置Tomcat&#xff1a; 四、配置session Session服务器之Redis Redis与Memcached的区别 安装部署redis 一、服务器配置 IP地址 主机名 软件包列表 192.168.100.131 huyang1 nginx 192.168.100.133 huyang3 JDK Tomca…

隧道安全监测解决方案

隧道安全监测 解决方案 一、监测目的 通过监控量测&#xff0c;实现信息化施工&#xff0c;不仅能及时掌握隧道实际的地质情况&#xff0c;掌握隧道围岩、支护衬砌结构的受力特征和变形情况&#xff0c;据此可以尽早发现塌方、大变形等灾害征兆&#xff0c;及时采取措施&…

Qgis二次开发-加载高德在线地图失败报错Raster layer Cannot instantiate the ‘wms‘ data provider

1.加载在线的高德地图 以下是在线高德地图地址。 http://webrd01.is.autonavi.com/appmaptile?x{x}&y{y}&z{z}&langzh_cn&size1&scale1&style8 以下是代码示例&#xff1a; #include <QApplication> #include <QMainWindow> #include …

Django学习笔记-表单(forms)的使用

在Django中提供了了form表单&#xff0c;可以更为简单的创建表单模板信息&#xff0c;简化html的表单。 一、网页应用程序中表单的应用 表单通常用来作为提交数据时候使用。 1.1 创建表单模板文件夹 在项目文件夹下创建一个template文件夹&#xff0c;用于存储所有的html模…

Integer 和 int

一、区别 1.Integer是int的包装类&#xff0c;int则是java的一种基本的数据类型&#xff1b; 2.Integer变量必须实例化之后才能使用&#xff0c;而int变量不需要实例化&#xff1b; 3.Integer实际是对象的引用&#xff0c;当new一个Integer时&#xff0c;实际上生成一个指针指向…

Linux vsftp三种模式的简单配置部署

环境&#xff1a;Debian 6.1.27-1kali1 (2023-05-12) vsftpd 安装 --查看是否当前系统是否已安装 apt list --installed | grep vsftpd 没有安装的话&#xff0c;就正常安装 apt-get update apt-get install vsftpd 一、匿名用户模式 分享一些不重要文件&#xff0c;任…

AI学习笔记二:YOLOV5环境搭建及测试全过程

若该文为原创文章&#xff0c;转载请注明原文出处。 记录yolov5从环境搭建到测试全过程。 一、运行环境 1、系统&#xff1a;windows10 &#xff08;无cpu) 2、yolov5版本&#xff1a;yolov5-5.0 3、python版本&#xff1a;py3.8 在创建虚拟环境前需要先把miniconda3和py…