IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 陇原战疫2021网络安全大赛_Crypto_复现 -> 正文阅读

[网络协议]陇原战疫2021网络安全大赛_Crypto_复现

mostlycommon

k e y w o r d s : keywords: keywords: 共模攻击

D e c r y p t i o n ? c o d e Decryption~code Decryption?code

from Crypto.Util.number import *
import gmpy2

e1 = 65536
e2 = 270270
n = 122031686138696619599914690767764286094562842112088225311503826014006886039069083192974599712685027825111684852235230039182216245029714786480541087105081895339251403738703369399551593882931896392500832061070414483233029067117410952499655482160104027730462740497347212752269589526267504100262707367020244613503
c1 = 39449016403735405892343507200740098477581039605979603484774347714381635211925585924812727991400278031892391996192354880233130336052873275920425836986816735715003772614138146640312241166362203750473990403841789871473337067450727600486330723461100602952736232306602481565348834811292749547240619400084712149673
c2 = 43941404835820273964142098782061043522125350280729366116311943171108689108114444447295511969090107129530187119024651382804933594308335681000311125969011096172605146903018110328309963467134604392943061014968838406604211996322468276744714063735786505249416708394394169324315945145477883438003569372460172268277

_,s,t = gmpy2.gcdext(e1,e2)
print(s,t)
m = pow(c1,s,n) * pow(c2,t,n) % n
print(gmpy2.gcd(e1,e2))
print(bytes.decode(long_to_bytes(gmpy2.iroot(m,2)[0])))

easytask

k e y w o r d s : keywords: keywords: GGHembedded technique

解题细节思路请见paper,(20条消息) GGH非对称密码体制破解方法_M3ng@L的博客-CSDN博客

简单来说,使用embedded technique方法将 C V P CVP CVP问题转换为 S V P SVP SVP问题,进而求得干扰向量 e e e的大小,减去 e e e再乘以公钥向量 B ′ B' B的逆即可

D e c r y p t i o n ? c o d e Decryption~code Decryption?code

from sage.modules.free_module_integer import IntegerLattice
c = e = [151991736758354,115130361237591,58905390613532,130965235357066,74614897867998,48099459442369,45894485782943,7933340009592,25794185638]
B = W = [[-10150241248,-11679953514,-8802490385,-12260198788,-10290571893,-334269043,-11669932300,-2158827458,-7021995],
[52255960212,48054224859,28230779201,43264260760,20836572799,8191198018,14000400181,4370731005,14251110],
[2274129180,-1678741826,-1009050115,1858488045,978763435,4717368685,-561197285,-1999440633,-6540190],
[45454841384,34351838833,19058600591,39744104894,21481706222,14785555279,13193105539,2306952916,7501297],
[-16804706629,-13041485360,-8292982763,-16801260566,-9211427035,-4808377155,-6530124040,-2572433293,-8393737],
[28223439540,19293284310,5217202426,27179839904,23182044384,10788207024,18495479452,4007452688,13046387],
[968256091,-1507028552,1677187853,8685590653,9696793863,2942265602,10534454095,2668834317,8694828],
[33556338459,26577210571,16558795385,28327066095,10684900266,9113388576,2446282316,-173705548,-577070],
[35404775180,32321129676,15071970630,24947264815,14402999486,5857384379,10620159241,2408185012,7841686]]

c = matrix(c)
B = matrix(B)
temp = B.stack(c).augment(vector([0]*B.ncols()+[1]))
e = IntegerLattice(temp).shortest_vector()[:-1]
m = B.solve_left(c - matrix(e))
print(m)
m = [ 877  619  919  977  541  941  947 1031  821]

from Crypto.Util.number import *
from Crypto.Cipher import AES
import hashlib
c = 0x1070260d8986d5e3c4b7e672a6f1ef2c185c7fff682f99cc4a8e49cfce168aa0
m = [877,619,919,977,541,941,947,1031,821]
key = hashlib.sha256(str(m).encode()).digest()
aes = AES.new(key,AES.MODE_ECB)
flag = aes.decrypt(long_to_bytes(c))
print(flag)

P e r f e r e n c e Perference Perference

hxp |伏尔加CTF 2016资格:crypto300"XXY"写

Mathematics of Public Key Cryptography (auckland.ac.nz)

GGH | 4XWi11的博客

Nguyen’s Attack:Intended Solution to GGH in GYCTF 2020 | Soreat_u’s Blog (soreatu.com)

Civet cat for Prince

k e y w o r d s : keywords: keywords: AES_CBCxor狸猫换太子

D e s c r i p t i o n Description Description

from Crypto.Cipher import AES
import os
from hashlib import sha256
import socketserver
import signal
import string
import random

table = string.ascii_letters + string.digits
BANNER = br'''
 .d8888b.  d8b                   888                            888             
d88P  Y88b Y8P                   888                            888             
888    888                       888                            888             
888        888 888  888  .d88b.  888888        .d8888b  8888b.  888888          
888        888 888  888 d8P  Y8b 888          d88P"        "88b 888             
888    888 888 Y88  88P 88888888 888          888      .d888888 888             
Y88b  d88P 888  Y8bd8P  Y8b.     Y88b.        Y88b.    888  888 Y88b.           
 "Y8888P"  888   Y88P    "Y8888   "Y888        "Y8888P "Y888888  "Y888          
                                                                                
                                                                                
                                                                                
 .d888                        8888888b.          d8b                            
d88P"                         888   Y88b         Y8P                            
888                           888    888                                        
888888  .d88b.  888d888       888   d88P 888d888 888 88888b.   .d8888b  .d88b.  
888    d88""88b 888P"         8888888P"  888P"   888 888 "88b d88P"    d8P  Y8b 
888    888  888 888           888        888     888 888  888 888      88888888 
888    Y88..88P 888           888        888     888 888  888 Y88b.    Y8b.     
888     "Y88P"  888           888        888     888 888  888  "Y8888P  "Y8888
'''

guard_menu = br'''
1.Tell the guard my name
2.Go away
'''

cat_menu = br'''1.getpermission
2.getmessage
3.say Goodbye
'''


def Pad(msg):
    return msg + os.urandom((16 - len(msg) % 16) % 16)


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):
        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 proof_of_work(self):
        proof = (''.join([random.choice(table) for _ in range(12)])).encode()
        sha = sha256(proof).hexdigest().encode()
        self.send(b"[+] sha256(XXXX+" + proof[4:] + b") == " + sha)
        XXXX = self.recv(prompt=b'[+] Give Me XXXX :')
        if len(XXXX) != 4 or sha256(XXXX + proof[4:]).hexdigest().encode() != sha:
            return False
        return True

    def register(self):
        self.send(b'')
        username = self.recv()
        return username

    def getpermission(self, name, iv, key):
        aes = AES.new(key, AES.MODE_CBC, iv)
        plain = Pad(name)+b"a_cat_permission"
        return aes.encrypt(plain)

    def getmessage(self, iv, key, permission):
        aes = AES.new(key, AES.MODE_CBC, iv)
        return aes.decrypt(permission)

    def handle(self):
        signal.alarm(50)
        if not self.proof_of_work():
            return
        self.send(BANNER, newline=False)
        self.key = os.urandom(16)
        self.iv = os.urandom(16)
        self.send(b"I'm the guard, responsible for protecting the prince's safety.")
        self.send(b"You shall not pass, unless you have the permission of the prince.")
        self.send(b"You have two choices now. Tell me who you are or leave now!")
        self.send(guard_menu, newline=False)
        option = self.recv()
        if option == b'1':
            try:
                self.name = self.register()
                self.send(b"Hello " + self.name)
                self.send(b"Nice to meet you. But I can't let you pass. I can give you a cat. She will play with you")
                self.send(b'Miao~ ' + self.iv)
                for i in range(3):
                    self.send(b"I'm a magic cat. What can I help you")
                    self.send(cat_menu, newline=False)
                    op = self.recv()
                    if op == b'1':
                        self.send(b"Looks like you want permission. Here you are~")
                        permission = self.getpermission(self.name, self.iv, self.key)
                        self.send(b"Permission:" + permission)
                    elif op == b'2':
                        self.send(b"Looks like you want to know something. Give me your permission:")
                        permission = self.recv()
                        self.send(b"Miao~ ")
                        iv = self.recv()
                        plain = self.getmessage(iv, self.key, permission)
                        self.send(b"The message is " + plain)
                    elif op == b'3':
                        self.send(b"I'm leaving. Bye~")
                        break
                self.send(b"Oh, you're here again. Let me check your permission.")
                self.send(b"Give me your permission:")
                cipher = self.recv()
                self.send(b"What's the cat tell you?")
                iv = self.recv()
                plain = self.getmessage(iv, self.key, cipher)
                prs, uid = plain[16:],plain[:16]
                if prs != b'Princepermission' or uid != self.name:
                    self.send(b"You don't have the Prince Permission. Go away!")
                    return
                else:
                    self.send(b"Unbelievable! How did you get it!")
                    self.send(b"The prince asked me to tell you this:")
                    f = open('flag.txt', 'rb')
                    flag = f.read()
                    f.close()
                    self.send(flag)
            except:
                self.request.close()
        if option == b'2':
            self.send(b"Stay away from here!")
        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', 10005
    print("HOST:POST " + HOST + ":" + str(PORT))
    server = ForkedServer((HOST, PORT), Task)
    server.allow_reuse_address = True
    server.serve_forever()

A n a l y s i s Analysis Analysis

首先是执行proof of work函数,简单的爆破四个字符使得其连接上剩余已知字符的sha256等于函数给出的sha256

然后进入正题,第一段守卫处没有有用信息,需要输入你的name(之后称为m1),然后在magic cat处可以获得

  • getpermission()

得到对m1+b'a_cat_permission'的AES_CBC加密之后得到的密文,其中iv是系统生成的已知量,key未知

    def getpermission(self, name, iv, key):
        aes = AES.new(key, AES.MODE_CBC, iv)
        plain = Pad(name)+b"a_cat_permission"
        return aes.encrypt(plain)
  • getmessage()

输入一段密文进行AES_CBC解密,其中iv由我们给出,key是之前使用的,得到解密之后给出的明文

    def getmessage(self, iv, key, permission):
        aes = AES.new(key, AES.MODE_CBC, iv)
        return aes.decrypt(permission)

总共有三次询问的机会(循环次数为3),循环完成之后由守卫进行验证

提交给守卫某个密文和自己给出的偏移量iv,使得进行相同的key的AES_CBC解密之后得到的明文是m1+b'Princeperimission'

self.send(b"Give me your permission:")
cipher = self.recv()
self.send(b"What's the cat tell you?")
iv = self.recv()
plain = self.getmessage(iv, self.key, cipher)
prs, uid = plain[16:],plain[:16]
if prs != b'Princepermission' or uid != self.name:
    ...

以上就是对题目代码的分析

简单来说,我们需要想办法把从magic cat处得到的perimission = m1 + b'a_cat_perimission'的密文换成m1 + b'Princepermission'的密文

其中可以用到的是magic cat会提供一次或两次解密的机会(用自己给出的iv

显然没有办法知道key进而直接求解,但是我们不需要老老实实地直接找 n e e d _ m 1 + n e e d _ m 2 need\_m_1+need\_m_2 need_m1?+need_m2?的密文,因为我们可以构造合适的iv代入最后的AES_CBC解密

先令

m 1 = i n p u t _ n a m e m_1 = input\_name m1?=input_name

m 2 = a _ c a t _ p e r m i s s i o n m_2 = a\_cat\_permission m2?=a_cat_permission

n e e d _ m 1 = m 1 need\_m_1=m_1 need_m1?=m1?

n e e d _ m 2 = P r i n c e p e r m i s s i o n need\_m_2=Princepermission need_m2?=Princepermission

由于AES_CBC加密是分块加密,而每一块的大小是128bits也就是16字节,而由于题目要求, m 1 m_1 m1? m 2 m_2 m2?以及 n e e d _ m 2 need\_m_2 need_m2?都是16字节大小的

这就意味着加密得到的密文块会有特殊的性质

c 1 = p e r m i s s i o n [ : 16 ] c_1=permission[:16] c1?=permission[:16] c 2 = p e r m i s s i o n [ 16 : ] c_2=permission[16:] c2?=permission[16:];其中 p e r m i s s i o n permission permissionmagic cat通过getpermission()给出的密文

通过图片明确一下AES_CBC加解密过程

加密过程是,先将明文按16字节一分组拆开,然后进行如图加密(先进行异或,非明文分组1的异或对象是前一个密文分组或者是明文分组1的异或对象初始化向量iv),再分别投入加密器,得到各个密文分组后拼接起来成为最后的密文

解密过程是,将密文按16字节一分组拆开,然后分别投入解密器,得到的结果与前一个密文分组或者初始化向量进行异或,最后得到各个明文分组再直接拼接在一起组成最后的明文

其中加密器和解密器在本题算是黑盒,只需要知道进去的数据和原来是不一样的即可

我们构造的密文要先经过一次解密器,这就意味着非经过AES_CBC加密产生的密文(比如 c 1 , c 2 c_1,c_2 c1?,c2?)都会产生一个未知的数据;那么这时就需要用到magic cat提供的解密的机会

经过解密器之后会进行异或,那么这就是本题的关键之一了,异或的性质就是两个一样的数异或均为0,也就是说对其他一起的数不会有影响,利用这个性质我们构造

f a k e _ c 1 = c 1 ⊕ m 2 ⊕ n e e d _ m 2 fake\_c_1=c_1\oplus m_2\oplus need\_m_2 fake_c1?=c1?m2?need_m2?

使用系统给出的iv代入magic cat提供的一次解密的机会

先经过解密器得到 m 1 ⊕ i v ⊕ d e c r y p t e d _ m 2 ⊕ d e c r y p t e d _ n e e d _ m 2 m_1\oplus iv\oplus decrypted\_m_2\oplus decrypted\_need\_m_2 m1?ivdecrypted_m2?decrypted_need_m2?

在与初始化向量iv异或得到 m = m 1 ⊕ d e c r y p t e d _ m 2 ⊕ d e c r y p t e d _ n e e d _ m 2 m=m_1\oplus decrypted\_m_2\oplus decrypted\_need\_m_2 m=m1?decrypted_m2?decrypted_need_m2?

接着构造

f a k e _ i v = m ⊕ m 1 ⊕ i v = d e c r y p t e d _ m 2 ⊕ d e c r y p t e d _ n e e d _ m 2 ⊕ i v fake\_iv=m\oplus m_1\oplus iv=decrypted\_m_2\oplus decrypted\_need\_m_2\oplus iv fake_iv=mm1?iv=decrypted_m2?decrypted_need_m2?iv

那么最后传入的密文是 f a k e _ c 1 + c 2 fake\_c_1+c_2 fake_c1?+c2?,传入的iv也就是 f a k e _ i v fake\_iv fake_iv

推导一下最后的解密过程,(AES_CBC是分块解密的)

f a k e _ c 1 fake\_c_1 fake_c1?单独进行解密得到 m 1 ⊕ i v ⊕ d e c r y p t e d _ m 2 ⊕ d e c r y p t e d _ n e e d _ m 2 m_1\oplus iv\oplus decrypted\_m_2\oplus decrypted\_need\_m_2 m1?ivdecrypted_m2?decrypted_need_m2?

然后再与 f a k e _ i v fake\_iv fake_iv异或得到

m 1 ⊕ i v ⊕ d e c r y p t e d _ m 2 ⊕ d e c r y p t e d _ n e e d _ m 2 ⊕ d e c r y p t e d _ m 2 ⊕ d e c r y p t e d _ n e e d _ m 2 ⊕ i v m_1\oplus iv\oplus decrypted\_m_2\oplus decrypted\_need\_m_2\oplus decrypted\_m_2\oplus decrypted\_need\_m_2\oplus iv m1?ivdecrypted_m2?decrypted_need_m2?decrypted_m2?decrypted_need_m2?iv

= m 1 =m_1 =m1?

得到明文分组1,符合最后的判断条件

然后 c 2 c_2 c2?单独进行解密,得到 c 1 ⊕ m 2 c_1\oplus m_2 c1?m2?

再与 f a k e _ c 1 fake\_c_1 fake_c1?进行异或得到 c 1 ⊕ m 2 ⊕ n e e d _ m 2 ⊕ c 1 ⊕ m 2 = n e e d _ m 2 c_1\oplus m_2\oplus need\_m_2 \oplus c_1\oplus m_2=need\_m_2 c1?m2?need_m2?c1?m2?=need_m2?

这就是明文分组2,符合最后的判断条件

D e c r y p t i o n ? c o d e Decryption~code Decryption?code

from re import L
from pwn import *
import hashlib,string,random
from Crypto.Cipher import AES

io = remote("node4.buuoj.cn","27370")
temp = io.recvline()
# print(temp)
temp1 = temp.split(b"==")
# print(temp1)
part_proof = bytes.decode(temp1[0].split(b"XXXX")[1])[1:-2]
sha = bytes.decode(temp1[1]).strip()
table = string.ascii_letters + string.digits
while True:
    XXXX = "".join([random.choice(table)for _ in range(4)])
    temp_proof = XXXX + part_proof
    temp_sha = hashlib.sha256(temp_proof.encode()).hexdigest()
    if sha == temp_sha:
        io.recvuntil(b"[+] Give Me XXXX :")
        io.sendline(XXXX.encode())
        break
io.recvuntil(b"[-] ")
io.sendline(b"1")
io.sendline(b"1" * 16)
io.recvuntil(b'Miao~ ')
iv = io.recvuntil(b"\n")[:-1]
# print(iv)
io.recvuntil(b'[-]')
io.sendline(b'1')
io.recvuntil(b'Permission:')
cat_permission = io.recvline()[:-1]
# print(cat_permission)
io.recvuntil(b"[-]")
io.sendline(b'2')
io.recvuntil(b"Looks like you want to know something. Give me your permission:")

m2 = b"a_cat_permission"
m1 = b'1' * 16 # your name,直接16字节,不会进行pad()函数,如果那样的话,m1也会成为一个未知量
need_m2 = b"Princepermission"
need_m1 = m1
c1 = cat_permission[:16]
c2 = cat_permission[16:]
fake_c1 = xor(xor(c1,m2),need_m2)

io.sendline(fake_c1)
io.recvuntil(b"Miao~ ")
io.sendline(iv)
io.recvuntil(b"The message is ")
m = io.recvuntil(b"\n")[:-1]
# print(plain)
io.recvuntil(b"[-]")
io.sendline(b'3')
io.recvuntil(b"Give me your permission:")

fake_permission = fake_c1 + c2
fake_iv = xor(xor(m,m1),iv)

io.sendline(fake_permission)
io.recvuntil(b"What's the cat tell you?")
io.sendline(fake_iv)
io.interactive()

P e r f e r e n c e Perference Perference

完美起航-20211107陇原战疫Crypto方向WP (okgoes.cn)

(11条消息) CBC模式解读_实践求真知-CSDN博客_cbc模式

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:49:22  更:2022-03-03 16:51:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:46:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码