陇原战疫crypto

一个月前的比赛,当时只会简单的RSA,现在回过来复现一下

1.mostlycommon

from Crypto.Util.number import bytes_to_long, getPrime

f = open('flag.txt', 'rb')
flag = f.read()
f.close()
m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
n = p * q
e1 = 65536
e2 = 270270
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
f = open('message.txt', 'w')
f.write('n=' + str(n) + '\n')
f.write('c1=' + str(c1) + '\n')
f.write('c2=' + str(c2) + '\n')
f.close()

简单的共模攻击注意此处的e1,e2不互素,得到的m不能直接转字节(需要开根)

代码如下:

import gmpy2
n=122031686138696619599914690767764286094562842112088225311503826014006886039069083192974599712685027825111684852235230039182216245029714786480541087105081895339251403738703369399551593882931896392500832061070414483233029067117410952499655482160104027730462740497347212752269589526267504100262707367020244613503
c1=39449016403735405892343507200740098477581039605979603484774347714381635211925585924812727991400278031892391996192354880233130336052873275920425836986816735715003772614138146640312241166362203750473990403841789871473337067450727600486330723461100602952736232306602481565348834811292749547240619400084712149673
c2=43941404835820273964142098782061043522125350280729366116311943171108689108114444447295511969090107129530187119024651382804933594308335681000311125969011096172605146903018110328309963467134604392943061014968838406604211996322468276744714063735786505249416708394394169324315945145477883438003569372460172268277
e1 = 65536
e2 = 270270
def exgcd(a,b):
    if b==0:return 1,0
    else:
        x,y=exgcd(b,a%b)
        return y,x-(a//b)*y
def attack(e1,e2,c1,c2,n):
    x,y=exgcd(e1,e2)
    i=gmpy2.gcd(e1,e2)
    print(i)
    m=pow(c1,x,n)*pow(c2,y,n)%n
    print(m)
if __name__ == '__main__':
    attack(e1,e2,c1,c2,n)

2.easytask

import random
import hashlib
from Crypto.Util.number import *
from Crypto.Cipher import AES
from secret import flag,V
def get_random_U(n):
    def get_U1():
        A = Matrix(ZZ, n, n)
        for i in range(0,n):
            for j in range(0,n):
                if i<j:
                    A[i,j] = random.randint(1,1000)
                if i==j:
                    A[i,j] = 1
        return A
    def get_U2():
        A = Matrix(ZZ, n, n)
        for i in range(0,n):
            for j in range(0,n):
                if i>j:
                    A[i,j] = random.randint(1,1000)
                if i==j:
                    A[i,j] = 1
        return A
    return get_U1()*get_U2()
def get_public_key():
    U = get_random_U(9)  #U为上三角与下三角的乘积
    V = matrix(V)       #V是给定矩阵(出题者导入)
    W = V*U
    return W        #返回UV乘积
def get_random_r():  #随机的9维向量(|坐标|不超过3)
    n = 9
    delta = 4
    r = random_vector(ZZ, n, x=-delta+1, y=delta)
    r = matrix(r)
    return r
def encrypt():
    M = [getPrime(10)for i in range(9)]
    m = matrix(M)  #九维向量坐标为2^9~2^10的素数
    W = get_public_key()  #矩阵W
    r = get_random_r()  #9维向量
    e = m*W+r
    print("e =",e)
    print("W =",W)
    return M
def new_encrypt():
    M = encrypt()
    key = hashlib.sha256(str(M).encode()).digest()
    cipher = AES.new(key, AES.MODE_ECB)
    c = cipher.encrypt(flag).hex()
    print("c =",c)
new_encrypt()
#e = [151991736758354 115130361237591  58905390613532 130965235357066  74614897867998  48099459442369  45894485782943   7933340009592     25794185638]
#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=1070260d8986d5e3c4b7e672a6f1ef2c185c7fff682f99cc4a8e49cfce168aa0

还是太菜了,刚开始做的时候以为是个可以把才学的线代运用到实践,可以直接爆破的题目,写完跑了半小时没出,放弃了(果断学习wp)

考的是格的一种加密体制GGH,1999年被Nguyen证明是不安全的

而这题本质上是求CVP问题,在查阅资料后了解到babai算法和embedding technique(嵌入式技术,属于是十分形象了)可以解决此类问题

babai算法考虑的是在优质的基(哈达玛比率接近1)下CVP可以利用四舍五入求解

但是实际可能还需调整,我直接对W格基规约后进行这个操作还是不能出结果,一个可能的原因是哈达玛比率还不够高(然后wp的算法写的我有点看不太懂)

于是我们采用嵌入式技术来解决,嵌入式技术的原理是通过对格的一个升维将CVP转换为SVP(可行的原因是加密算法所选取的扰动向量相对于基太小了,所以我们可以认为通过升维求得的最短向量就是扰动向量)

把相关的资料贴这:hxp | VolgaCTF 2016 Quals: crypto300 "XXY" writeup

代码如下:

1.求解扰动向量

from sage.modules.free_module_integer import IntegerLattice
e=Matrix([[151991736758354,115130361237591,58905390613532,130965235357066,74614897867998,48099459442369,45894485782943,7933340009592,25794185638]])
W=Matrix([[-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]])
B = W.stack(e).augment(vector([0] * W.ncols() + [1]))
r=IntegerLattice(B).shortest_vector()
r=matrix(r[:-1])
V=W.solve_left(e-r)
print(V)

2.aes解密

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

3.Civet cat for Prince

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()

题目不难,但是代码有点长,熟悉一下流程接着逐个理清函数的作用即可

此题采用的是ECB模式的AES加密(考的还是通过修改数据来达到绕过检测的目的)与CBC翻转类似,但是多了一步对前面的iv的修改

代码如下:

import hashlib
from pwn import *
from itertools import product
import string
from Crypto.Util.number import *
p=remote('node4.buuoj.cn',26813)
#context.log_level = 'debug'
table = string.ascii_letters + string.digits

def proof_of_work():
        proof = p.recvline()
        tail = proof[16:24].decode()
        HASH = proof[29:93].decode()
        for i in product(table, repeat=4):
            head = ''.join(i)
            t = hashlib.sha256((head + tail).encode()).hexdigest()
            if t == HASH:
                p.recvuntil(b'[+] Give Me XXXX :')
                p.sendline(head.encode())
                break

proof_of_work()
p.recvuntil('[-]')
p.sendline('1')
p.recvuntil('[-]')
p.sendline('hashhashhashhash')
p.recvuntil('Miao~ ')
iv=p.recvuntil('\n')[:-1]
iv1=hex(bytes_to_long(iv))[2:]
p.recvuntil('[-]')
p.sendline('1')
p.recvuntil('Permission:')
c=p.recvuntil('\n')[:-1]
c1=hex(bytes_to_long(c))[2:]
SUB1=str(c1)
sub1=hex(int(SUB1[:12],16)^bytes_to_long(b'a_cat_')^bytes_to_long(b'Prince'))[2:]
c1=int(str(sub1)+SUB1[12:],16)
print(hex(c1))
c=long_to_bytes(c1)
p.recvuntil('[-]')
p.sendline('2')
p.recvuntil('[-]')
p.sendline(c)
p.recvuntil('[-]')
p.sendline(iv)
p.recvuntil('The message is ')
temp=hex(bytes_to_long(p.recvuntil('\n')[:-1]))[2:]
print(temp)
SUB2=str(iv1)
sub2=hex(int(SUB2,16)^int(str(temp)[:32],16)^bytes_to_long(b'hashhashhashhash'))[2:]
iv1=int(str(sub2),16)
print(hex(iv1))
iv=long_to_bytes(iv1)
p.recvuntil('[-]')
p.sendline('3')
p.recvuntil('[-]')
p.sendline(c)
p.recvuntil('[-]')
p.sendline(iv)
p.interactive()
posted @ 2021-12-19 10:12  hash_hash  阅读(303)  评论(0)    收藏  举报