2024强网拟态MISC&Crypto
1770980518794052 发表于 浙江 CTF 403浏览 · 2024-10-22 12:25

强网拟态MISC&Crypto

MISC

Find way to read video

题目

amily0721 has put her email template on a public platform.

有些东西在public平台上被公开了!

分析

amily0721 has put her email template on a public platform.

去公开的平台上寻找amily0721,最终在gitcode上找到邮件模板,

分析邮件,有好多邮件组成,里面还有有详细的法条This mail is being sent in compliance with Senate bill 2716 , Title 4 ; Section 306 . ,尝试搜索Dear后面的名字,无果;在尝试搜法案,发现是垃圾邮件,有专门加减密的网站,去在线网站解密

得到

BV1FD2EYyEWo eyJ2IjozLCJuIjoiZmxhZyIsInMiOiIiLCJoIjoiMDI1NTVlZiIsIm0iOjkwLCJrIjo4MSwibWciOjIwMCwia2ciOjEzMCwibCI6NDMsInNsIjoxLCJmaGwiOlsiMjUyZjEwYyIsImFjYWM4NmMiLCJjYTk3ODExIiwiY2QwYWE5OCIsIjAyMWZiNTkiLCI0ZTA3NDA4IiwiNWZlY2ViNiIsIjNlMjNlODEiLCIzZTIzZTgxIiwiMTk1ODFlMiIsIjE4YWMzZTciLCI2Yjg2YjI3IiwiMThhYzNlNyIsIjM5NzNlMDIiLCIxOGFjM2U3IiwiMThhYzNlNyIsImU3ZjZjMDEiLCI0ZTA3NDA4IiwiMzk3M2UwMiIsIjRiMjI3NzciLCJkNDczNWUzIiwiNmI4NmIyNyIsIjRlMDc0MDgiLCIzOTczZTAyIiwiY2E5NzgxMSIsIjRlMDc0MDgiLCI2Yjg2YjI3IiwiZTdmNmMwMSIsIjM5NzNlMDIiLCJjYTk3ODExIiwiMThhYzNlNyIsIjE4YWMzZTciLCI0YjIyNzc3IiwiNGIyMjc3NyIsIjRiMjI3NzciLCJlZjJkMTI3IiwiMTk1ODFlMiIsIjZiODZiMjciLCI0YjIyNzc3IiwiNzkwMjY5OSIsIjJjNjI0MjMiLCJkMTBiMzZhIiwiMDFiYTQ3MSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNzliZWM3ZiIsImU3N2I5YTkiLCJhYjg5N2ZiIiwiNGFlODE1NyIsImNiZTVjZmQiLCI4OGFhM2UzIiwiMTQ4ZGU5YyIsIjVkNWM3ZDIiLCI5NDlmOTRkIl19

base64解码

]EaÈE¨{"v":3,"n":"flag","s":"","h":"02555ef","m":90,"k":81,"mg":200,"kg":130,"l":43,"sl":1,"fhl":["252f10c","acac86c","ca97811","cd0aa98","021fb59","4e07408","5feceb6","3e23e81","3e23e81","19581e2","18ac3e7","6b86b27","18ac3e7","3973e02","18ac3e7","18ac3e7","e7f6c01","4e07408","3973e02","4b22777","d4735e3","6b86b27","4e07408","3973e02","ca97811","4e07408","6b86b27","e7f6c01","3973e02","ca97811","18ac3e7","18ac3e7","4b22777","4b22777","4b22777","ef2d127","19581e2","6b86b27","4b22777","7902699","2c62423","d10b36a","01ba471","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","6e340b9","79bec7f","e77b9a9","ab897fb","4ae8157","cbe5cfd","88aa3e3","148de9c","5d5c7d2","949f94d"]}

发现开头BV1FD2EYyEWo没解码出来,题目提示信息是要找video,去b站上搜BV1FD2EYyEWo,发现有90个flag视频,

仔细分析视频,里面每秒出现一个由.-组成的电码,手搓一点,发现类里面的-长短不一样,不像是莫斯,,先把视频下载出来,然后提取出图片,

让chat帮忙写一下提取图片的脚本,分离出图片

import cv2
import os
from PIL import Image

FREQUENCY = 1  # 提取频率(每秒提取一帧)

def extract_frames(video_path, dst_folder, index=1):
    """从视频中提取帧并保存为图片。"""
    video = cv2.VideoCapture(video_path)
    if not video.isOpened():
        print(f"无法打开视频:{video_path}")
        return

    count = 0
    while True:
        success, frame = video.read()
        if not success:
            break  # 视频读取结束

        if count % FREQUENCY == 0:
            save_path = f"{dst_folder}/{index:03d}.jpg"
            cv2.imwrite(save_path, frame)  # 保存图片
            index += 1
        count += 1

    video.release()
    print(f"从 {video_path} 提取了 {index - 1} 张图片")

# 批量处理视频
filePath = "./flag"  # 视频文件夹路径
dst_folder = "./pic"  # 图片保存的总目录
for i, file in enumerate(os.listdir(filePath)):
    if file.endswith(".mp4"):  # 只处理 .mp4 文件
        video_path = os.path.join(filePath, file)
        pic_path = os.path.join(dst_folder, f"pic{i}")  # 创建对应的图片目录
        os.makedirs(pic_path, exist_ok=True)
        extract_frames(video_path, pic_path)

{"v":3,"n":"flag","s":"","h":"02555ef","m":90,"k":81,"mg":200,"kg":130,"l":43,"sl":1,"fhl":很好奇这段信息是否有帮助,是否代表位置信息。先分析每个视频中第一个白点出现的地方,看他们的位置是否相同,仔细对比,发现每个视频的起始位置并不是一样的,第一个视频切出的第五张图,出现的是-- -- ,前面分析了不是莫斯,那就就可能是0,1二进制表示,后面的图片像极了01数据自增,尝试提取图片像素

from PIL import Image
pic_path = "./pic/pic0"
pic_img_path = os.path.join(pic_path, "005.jpg")
image = Image.open(pic_img_path)
flag = ['0'] * 8
for x in range(32, 32 + 8):
    pixel_value = image.getpixel((x, 0))
    if pixel_value >= (10, 10, 10):
        flag[x - 32] = '1'
m = int.to_bytes(int(''.join(flag), 2), 1, 'big')
print(m)

刚好得到了f,猜测flag在后面图片中,尝试后发现后面基本上确实是二进制自增

分析取后面视频的第5张图片,发现每张都不一样像极了flag,尝试提得后到flag

from PIL import Image
m = b""
for i in range(90):
    pic_path = "./pic/pic"+str(i)
    pic_img_path = os.path.join(pic_path, "005.jpg")
    image = Image.open(pic_img_path)
    flag = ['0'] * 8
    for x in range(32, 32 + 8):
        pixel_value = image.getpixel((x, 0))
        if pixel_value >= (10, 10, 10):
            flag[x - 32] = '1'
    m += int.to_bytes(int(''.join(flag), 2), 1, 'big')
print(m)

Crypto

xor

题目

mimic is a keyword.
0b050c0e180e585f5c52555c5544545c0a0f44535f0f5e445658595844050f5d0f0f55590c555e5a0914

分析

简单循环异或

CFBchall

题目

遭遇过几次拖库之后,我们直接删除了数据库!请你保存好生成的token,不要篡改哦~

from flask import Flask, render_template, request, jsonify
from Crypto.Cipher import AES
import os
from string import printable
app = Flask(__name__)

# 初始化全局变量
def initialize_globals():
    global key, iv,register_open, login_attempts
    key = os.urandom(16)
    iv  = os.urandom(16)
    register_open = True
    login_attempts = 500

initialize_globals()

def encrypt(data, key):
    #iv = os.urandom(16)
    cipher = AES.new(key, AES.MODE_CFB, iv=iv)
    ct_bytes = cipher.encrypt(data.encode('utf-8'))
    return ct_bytes.hex()

def decrypt(ct, key):
    ct_bytes = bytes.fromhex(ct)
    #iv = ct_bytes[:16]
    cipher = AES.new(key, AES.MODE_CFB, iv=iv)
    data = cipher.decrypt(ct_bytes[:])
    #print("data:",data)
    return data

@app.route('/', methods=['GET', 'POST'])
def index():
    global register_open, login_attempts
    message = ""

    if request.method in  ['POST']:
        if request.is_json:
            data = request.get_json()
            action = data.get('action')

            if action == 'register':
                if not register_open:
                    message = "Registration function is closed"
                else:
                    username = data.get('username')
                    password = data.get('password')
                    if len(password)<8:
                        message = "Registration failed, password too short"
                    elif not set(password+username)<=set(printable):
                        message = "Registration failed, illegal character"
                    elif 'admin' in username:
                        message = "Registration failed, you are not an admin"
                    else:
                        token = encrypt(f"{username}\x00{password}\x01\x02\x03", key)
                        register_open = False
                        message = f"Please save your token: {token}"

            elif action == 'login':
                if login_attempts <= 0:
                    message = "Too many attempts"
                else:
                    username = data.get('username').encode()
                    password = data.get('password').encode()
                    token = data.get('token')

                    try:
                        decrypted = decrypt(token, key)
                        #print(decrypted)
                        token_username, *_, token_password = decrypted.split(b'\x00')
                        #print(token_username,",",token_password)
                        assert(token_password[-3:]==b"\x01\x02\x03")
                        token_password=token_password[:-3]
                        if username == token_username and password == token_password:
                            if username == b'admin':
                                #print(token_password)
                                if password == b'123456':
                                    f=open("./flag","r")
                                    flag=f.read()
                                    #print(flag)
                                    f.close()
                                    message = "You have logged in with admin privileges, here is your flag: "+flag
                                else:
                                    message = "Admin login failed, please try again"
                            else:
                                message = "You have logged in as a regular user"
                        else:
                            message = "Login failed, please try again"
                    except:
                        message = "Login wrong, please try again"
                    finally:
                        login_attempts -= 1

            elif action == 'restart':
                initialize_globals()
                message = "System has been restarted. AES key and function counts have been reset."
        else:
            message = "Unsupported Media Type: Content-Type must be application/json"

        return jsonify({'message': message})
    return render_template('index.html', message=message)    

if __name__ == '__main__':
    app.run(host="0.0.0.0")

分析

考察CFB模式特性

CFB模式是一种将AES的块加密算法转化为流加密算法的方式,适用于连续数据流的加密,不需要对数据进行填充。

在CFB模式中,如果某一块密文发生错误,错误只会影响当前块和后续一块,限制了错误的扩散。

比特翻转:CFB模式中,明文和密文的关系如下

可以对密文中的某一比特位进行翻转,进而改变解密后的明文内容,如将admim伪造成admin

hex(int(token[8:10], 16) ^ ord('m') ^ ord('n'))[2:].zfill(2)

本题使用了\x00进行截断,因翻转了m的密文,所以确定后面一块密文受到影响,可以爆破出\x00与原有\x00进行组合截断,从而只保留翻转出来的admin

注册时password要大于等于8,但登录时admin所对应的密码为123456,又需要\x00进行截断伪造。可以构造17个字节加123456,改变第一个字节对应的密文,后面16个字节的密文块受到影响,且最后一个字节有概率出现\x00与原有的\x00组合截断从而丢弃中间的17个字节只保留123456

import  requests

def login(token, password):
    data = {"action": "login", "username": "admin", "password": password, "token": token}
    return requests.post(url, json=data).json()["message"]

def initialize_globals():
    requests.post(url, json={"action": "restart"})

def register():
    data = {"action": "register", "username": username, "password": password}
    token = requests.post(url, json=data).json()["message"]
    return token.split(': ')[1]

def get_admin(token, token0):
    for i in range(256):
        ct = token0 + hex(i)[2:].zfill(2) + token[12:]
        decrypted = login(ct, password)
        print(decrypted)
        if "Admin login failed" in decrypted:
            return i
        return None
url = "http://web-549638574d.challenge.xctf.org.cn:80/"
username = "admim" + "2" * 17
password = "1" * 17 + "123456"
data = f"{username}\x00{password}\x01\x02\x03"
while True:
    initialize_globals()
    token = register()

    signal = 0
    token0 = token[:8] + hex(int(token[8:10], 16) ^ ord('m') ^ ord('n'))[2:].zfill(2)
    k = get_admin(token, token0)
    if k is None: continue
    ct0 = token0 + hex(k)[2:].zfill(2)
    for i in range(256):
        ct = ct0 + token[12:12 + 44] + hex(i)[2:].zfill(2) + token[-50:]
        # decrypted = decrypt(ct, key)
        decrypted = login(ct, "123456")
        print(decrypted)
        if "flag" in decrypted:
            print(decrypted)
            signal = 1
            break
    if signal == 1:
        break

watermarking

计算太贵了!想跟我讲话,首先得买我的水印!

题目

from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
import socketserver
import signal
import os
import string
import random
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Util.number import getPrime,getStrongPrime
from Crypto.Random import get_random_bytes
from sympy import nextprime





class Task(socketserver.BaseRequestHandler):
    def _recvall(self):
        BUFF_SIZE = 4096
        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):
        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 handle(self):
        e=3
        maxlens=4096
        RSAparameter=None
        signal.alarm(60)
        watermark=os.urandom(512)

        self.send(b"welcome to my proxy encryption program with watermarking")
        messages=[]
        while 1:
            self.send(b"1 for free encrypt with time limit")
            self.send(b"2 for check your watermarking ")
            self.send(b"plz input function code")
            try:
                mode=int(self.recv())
            except:
                self.send(b"plz input right function code")
                continue
            if mode==1:
                if maxlens<=0:
                    self.send(b"sorry, no free chance, try last time~")
                    continue
                self.send(b"now choose your n bitlens")
                self.send(b"1. 1024 2. 2048 3. 4096")
                try:
                    mode=int(self.recv())
                except:
                    self.send(b"plz input right function code")
                    continue
                if mode==1:
                    newparameter=1024
                if mode==2:
                    newparameter=2048
                if mode==3:
                    newparameter=4096
                if newparameter!= RSAparameter:
                        RSAparameter=newparameter
                        p=getStrongPrime(RSAparameter//2)
                        q=getStrongPrime(RSAparameter//2)
                        n=p*q
                        phi=(p-1)*(q-1)
                        self.send(b"your n is changed to")
                        self.send(hex(n).encode())
                try:
                        rsa_key = RSA.construct((n, e))
                        public_key = rsa_key.publickey().export_key()
                        cipher = PKCS1_v1_5.new(RSA.import_key(public_key))
                        self.send(b"plz input your message with hex")
                        message=self.recv().decode()
                        #print(message,len(message))
                        messages.append(message)
                        message=watermark[:RSAparameter//16]+bytes.fromhex(message)
                        #print(message)

                        c = (cipher.encrypt(message)).hex().encode()
                        #print(c)
                        self.send(c)
                        e=nextprime(e)
                        maxlens-=RSAparameter
                except:
                        self.send(b"wrong~ try again")
                        continue
            elif mode==2:
                if maxlens>0:
                    self.send(b"sorry, not even yet~")
                    continue
                self.send(b"now give me your message without free chance")
                e=65537
                d=pow(e,-1,phi)
                rsa_key = RSA.construct((n, e,d))
                public_key = rsa_key.publickey().export_key()
                cipher = PKCS1_v1_5.new(rsa_key)

                cts=self.recv().decode()
                cts=bytes.fromhex(cts)
                try:
                    p = (cipher.decrypt(cts,b"bad cipertext"))
                    print(p)    
                except Exception as e:
                    print(e)
                    self.send(b"wrong~ try again")
                    continue    
                if p[:RSAparameter//16]!=watermark[:RSAparameter//16]:
                    self.send(b"not used the watermark!")
                    continue    
                if p[RSAparameter//16:].hex() in messages:
                    self.send(b"not cost!")
                    continue 
                f=open("./flag","rb")
                flag=f.read()
                f.close()       
                self.send(b"cong! your flag is "+flag)        











        self.request.close()


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


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


if __name__ == "__main__":
    HOST, PORT = '0.0.0.0', 9999
    print("HOST:POST " + HOST+":" + str(PORT))
    server = ForkedServer((HOST, PORT), Task)
    server.allow_reuse_address = True
    server.serve_forever()

分析

加密:

watermark=os.urandom(512)

maxlens=4096

n的bit 可以选择 1024,2048,4096,生成p,q,n

如果n的bit 等于上一轮nbit,那么不再重新生成p,q,n不变

e=3,给出message,m=watermark[:nbit//16]+mmessage

对m进行pkcs#1 v1.5填充加密,输出c

每经过一轮,e=nextprime,maxlens-nbit

直到maxlens=0结束

1024 1024 1024 1024     e--11
1024 1024 2048          e--7
1024  2048 1024         e--7
2028 1024  1024         e--7
2048  2048              e--5
4096                    e--3

解密:

n就是最后一轮加密的n

e=65537

p=decrypt(m,e,n)

如果pkcs#1 v1.5解填充成功,并且p中含有watermark[:nbit//16],但不含你给出的message

查看PKCS#1 v1.5 encryption padding源码

def encrypt(self, message):
        """Produce the PKCS#1 v1.5 encryption of a message.This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and it is specified in
    `section 7.2.1 of RFC8017
    <https://tools.ietf.org/html/rfc8017#page-28>`_.

    :param message:
        The message to encrypt, also known as plaintext. It can be of
        variable length, but not longer than the RSA modulus (in bytes) minus 11.
    :type message: bytes/bytearray/memoryview

    :Returns: A byte string, the ciphertext in which the message is encrypted.
        It is as long as the RSA modulus (in bytes).

    :Raises ValueError:
        If the RSA key length is not sufficiently long to deal with the given
        message.
    """

    # See 7.2.1 in RFC8017
    k = self._key.size_in_bytes()
    mLen = len(message)
    # Step 1
    if mLen > k - 11:
        raise ValueError("Plaintext is too long.")
    # Step 2a
    ps = []
    while len(ps) != k - mLen - 3:
        new_byte = self._randfunc(1)
        if bord(new_byte[0]) == 0x00:
            continue
        ps.append(new_byte)
    ps = b"".join(ps)
    # Step 2b
    em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message)
    # Step 3a (OS2IP)
    em_int = bytes_to_long(em)
    # Step 3b (RSAEP)
    m_int = self._key._encrypt(em_int)
    # Step 3c (I2OSP)
    c = long_to_bytes(m_int, k)
    return c
EM = 0x00 || 0x02 || PS || 0x00 || M

EM是最终要被加密的明文,PS是随机生成的不小于8字节的内容不含0x00的数据,更准确的说PS的长度应该为k - mLen - 3

题目中

em=0x00 || 0x02 || PS || 0x00 || watermark[:nbit//16]+m

求出watermark[:nbit//16],

构造

"\x00\x02" + urandom(8) + b"\x00" + watermark + urandom(117),即可获得flag

求watermark,Coppersmith’s short-pad attack

在Sage中有通用的方法来进行消元从而化归到单变量的形式

结式(resultant): f.resultant(g, q)

EG.g = f1.resultant(f2, q)消去了变量q

f = N - p*q
g = p+q - p_plus_q
h = f.resultant(g, q)
print([f, g])
# [-p*q + 91, p + q - 20]
print([h, factor(h)])
# [-p^2 + 20*p - 91, (-1) * (p - 13) * (p - 7)]

Sage内置的resultant实现不能满足计例如在Zmod(n)下,或很大的有限域下。这时可以先转化为

Sylvester矩阵,再计算矩阵的行列式

from sage.matrix.matrix2 import Matrix 
Matrix.determinant(f1.sylvester_matrix(f2, var))

消去m1变成只有a存在的单变量的形式

a=(ps1-ps2) 八字节 8*8 64bit copper攻击得到a,

gcd(f1,f2)==M1

from http.client import responses
from os import urandom
from Crypto.Util.number import long_to_bytes, bytes_to_long
from pwn import *
from sage.all import *

# context.log_level='debug'
re=remote("124.223.10.170",12000)
c=[]
re.recvuntil(b'>')
re.sendline(b'1')
re.recvuntil(b'>')
re.sendline(b'2')
re.recvline()
n=int(re.recvline().decode().strip(),16)
print(f'{n=}')
message=urandom(245-2048 // 16)
print(f'{message=}')
re.recvuntil(b'>')
re.sendline(message.hex().encode())
c1=re.recvline().decode().strip()
print(f'{c1=}')
c1=int(c1,16)

re.recvuntil(b'>')
re.sendline(b'1')
re.recvuntil(b'>')
re.sendline(b'2')
re.recvuntil(b'>')
re.sendline(message.hex().encode())
c2=re.recvline().decode().strip()
print(f'{c2=}')
c2=int(c2,16)

PR.<a,x>= PolynomialRing(Zmod(n))
f1=x^3-c1
f2=(2^(8*246)*a+x)^5-c2
t=f1.sylvester_matrix(f2, x)
res=t.det()
PR1.<a> = PolynomialRing(Zmod(n))
res=eval(str(res).replace("^","**"))
res=res.monic()
a=res.small_roots(X=2**64,beta=0.5)[0]
PR.<x> = PolynomialRing(Zmod(n))
f1 = (x)^3 - c1
f2=(2^(8*246)*a+x)^5-c2

def gcd(g1, g2):
    while g2:
        g1, g2 = g2, g1 % g2
    return g1.monic()
m = -gcd(f1, f2)[0]

watermark = long_to_bytes(int(m), 256)
print(f'{watermark=}')
re.recvuntil(b'>')
re.sendline(b'2')
re.recvline()

msg = b"\x00\x02" + urandom(8) + b"\x00" + watermark[11:11+128] + urandom(117)
ct = int(pow(bytes_to_long(msg), 65537, n))
print(f'{ct=}')
wei_message=long_to_bytes(ct).hex()
re.sendline(wei_message.encode())
re.recvuntil(b"cong! your flag is ")
flag=re.recvline()
print(flag)
re.interactive()

# b'welcome to my proxy encryption program with watermarking\n1 for free encrypt with time limit\n2 for check your watermarking \nplz input function code\n>'
# b' now choose your n bitlens\n1. 1024 2. 2048 3. 4096\n>'
# b' your n is changed to\n'
# n=22871499096953256526645322468035980618391980741781388630105510538793939947971570404996508522120309579475680627998610224649437434209180471832337705699590355261709013176067318230976515679362020967103987323487802455521315803979431734938044979900759431421068276974811022252784244587782605744072334661693985297627667054459757071053197161966966183983814888410381801898238412103796536046427828878821813388194184321987289585405673030004645604375989176226593489792938377601445540913328958268822094842351261659871799818449471352500906779537457881423439640521337291721708013586197731869596357254279708231125543898273798218499183
# message=b'\r\xd7\x8c\xf7\xfd\x98\xe2\xf8\x88 \xba\xef\xf3\x86\x1f4}5\x94\x97\xd3RC\x00z\xce\xd4\xb8\x9b\xbf\xb2a\xd7\x0b?\x1c\xc8\x88\x0e\xbau\x94T\xbb\x8es\xb2\xbd\xcd\x93\xe7\x90\xd1\x11\xf3{\xeb\x1f2\xeb9\xd6HLp`\xb6\xf0\x03\x1f8\xd4u\xca\xc7\x04\x1b0\xee\xc9\xc2L\xb2\x9e(ou)L\x1cd\x8d\xd7\x82\x9e\x84(\xa4y\xda\x01\xa3\xae\x90l\xe6>#\x00:\xba\x1a\t\xfbI\xcd\x9b'
# b'plz input your message with hex\n>'
# c1='1fc500ee133a462ada0c4b4867ab6a4c3948eb40877a00c51de6ababe2f8b030540acb4ec7b17a430b064cb43c8719d26e229b9737e0e846fb70de751575c72dd54a6236781d1299f22f799c9e749a3646b2218a42cca6938b7dc7ecaacabde345d40dbc5a437e3e6d7250b9082ec1d6232360c5d6d52510c51524fa1a93a3c002767dc861c799cf902497887ac530f08452b4692981b4d98a077c6f6fdc9a680563160ab4a362d147e2ff4bb027092bf4ade93d9c369d821f5df06ae24bf7acf4dfd1250058ec93bcd39497b0d5a5da42d3d4ce055951669525dc39f4871a924d14ccfd3bfc704de53ea9a058b3ee8b44a6cf5f0651b0a898d01cd4b3bd1e6a'
# b'1 for free encrypt with time limit\n2 for check your watermarking \nplz input function code\n>'
# b' now choose your n bitlens\n1. 1024 2. 2048 3. 4096\n>'
# b' plz input your message with hex\n>'
# c2='049110ccc39fdf7e5aa93f81aef4bf396f19d02e256a34e2175acdc9e0f4dfdf2a0c4e3c939ed09c7a8efc6a2b39f424a4dcec0dcf42b78ac9f3bad5e8a96b33b80782e2103c48a5e282228dc3accedc477b52c2d4d81dd287159a2a226e10c0f9f70f72cabc7ba1c568bad685d46e87373400409b32bfc46185db0bd664d6fa4fb50419f62ec0d864a5de033c938b0652c0c6ded001422f9ffd9b2da2b87074c62677c5da5d4abc4a931c809a2acaecb189903dfd1a2e83425ae4474e65bc06c7732446bda2cb992f29e3b9913ff3b7eeaf739606e0f60d474b8b558655a88d352d68cfb5988d38761a430812a7fbe054fa37a0005f7d51219223e35bb8a381'
# watermark=b'\x00\x02\xa1\x85\xc2\xc3\xa7Wo\xf1\x00}\xcd;4\x1c\x00\x0fS\x80Y\xd6\xae!>\xda\x0c\x156@\xb8\x9a\x98\x1av\xe1&\xa7\xa3\xe2\xce\x8a\xfb\x12<\x97i\xbe\xd5\xffp\xf9_\x0c\xad\x1f-P~:\xad\xbeN\xcd\x12L\x9c\xf2\xf6\xea\x9e\xb1\xd2%\xf0\xf2\xda\xe6D\x17nrY\x13\xb6V\x99\x0e\xc2\x1a\xfa\x97\x11\x9f\xf9j\xba$\xa6\r\x81^Y\x87\xa6\xc5R\xac9\xd7\xf8\xcb\xf3R\xcf\xc3\x96\x12\xf1\xb4B\xb9\x98\x06\xc6@\xac\x04\xc7\x8f#3\x0f=$\x7f\xa8\xf9\xca\r\xd7\x8c\xf7\xfd\x98\xe2\xf8\x88 \xba\xef\xf3\x86\x1f4}5\x94\x97\xd3RC\x00z\xce\xd4\xb8\x9b\xbf\xb2a\xd7\x0b?\x1c\xc8\x88\x0e\xbau\x94T\xbb\x8es\xb2\xbd\xcd\x93\xe7\x90\xd1\x11\xf3{\xeb\x1f2\xeb9\xd6HLp`\xb6\xf0\x03\x1f8\xd4u\xca\xc7\x04\x1b0\xee\xc9\xc2L\xb2\x9e(ou)L\x1cd\x8d\xd7\x82\x9e\x84(\xa4y\xda\x01\xa3\xae\x90l\xe6>#\x00:\xba\x1a\t\xfbI\xcd\x9b'
# b'1 for free encrypt with time limit\n2 for check your watermarking \nplz input function code\n>'
# b' now give me your message without free chance\n'
# ct=18171392056130170632697136167604589419783459492941622078742468727438054056511102954874107953620159726318555962194750406962982292144393445739154357451154199065754554227294501940966941096717019896290021398107395456084444256105059891122866745412055763116060302808295733386539517171737166287647962228852764769174454759581866828730527326411011394836523660721315720673175771770948102506963262060772853992314886180435992251579581358314191345719324465523727827783355931417983246074156222835742308842076172637675327038261140455782213034848993172703115605638695738698462742273403842605153516440401127947916904669810050953813381
# b'> cong! your flag is '
# b'flag{bda0dae2-1e60-4e04-a6ed-50857b102743}\n'

总结:

1.CFB模式特性:在CFB模式中,如果某一块密文发生错误,错误只会影响当前块和后续一块,限制了错误的扩散。

2.利用结式将多变量的多项式方程转化成单变量方程

3.Coppersmith’s Short-pad Attack和Related Message Attack(Franklin-Reiter攻击)

当padding 过短也有可能被很容易地攻击, padding 过短,其实就是对应的多项式的根会过小,是可以考虑copper attack 出padding内容

0 条评论
某人
表情
可输入 255