安询杯-Crypto题目复现Writeup

加油!        -----2024-01-05  16:35:57

0x00  题目复现

下载地址:github题目复现

下载完事之后复制源代码,打开pycharm直接运行

之后访问本地的127.0.0.1:10001,可以直接看见赛题。

0x01  Cry1

打开附件

# -*- coding:utf-8 -*-
import os
import random
import string
import hashlib
import socketserver
from Crypto.Util.number import isPrime, long_to_bytes, getStrongPrime, bytes_to_long

flag = b"D0g3{******************************************}"

class MyServer(socketserver.BaseRequestHandler):
    def proof(self):
        random.seed(os.urandom(8))
        random_str = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(20)])
        str_sha256 = hashlib.sha256(random_str.encode()).hexdigest()
        self.request.sendall(('SHA256(XXXX + %s):%s\n' % (random_str[4:], str_sha256)).encode())
        self.request.sendall('Give Me XXXX:\n'.encode())
        XXXX = self.request.recv(2048).strip()

        if hashlib.sha256((XXXX + random_str[4:].encode())).hexdigest() != str_sha256:
            return False

        return True

    def getPQN(self):
        while True:
            p = getStrongPrime(2048)
            q = getStrongPrime(2048)
            n = p * q
            if p.bit_length() == 2048 and q.bit_length() == 2048 and n.bit_length() == 4096:
                return p, q, n

    def encrypt(self):
        p, q, n = self.getPQN()
        m = bytes_to_long(flag)
        e = 0x10001
        c = pow(m, e, n)
        p = bin(p)[2:]
        p1 = list(p[:1024])
        p2 = list(p[1024:])
        p1[random.choice([i for i, c in enumerate(p1) if c == '1'])] = '0'
        p2[random.choice([i for i, c in enumerate(p1) if c == '0'])] = '1'
        return n, ''.join(p1) + ''.join(p2), c

    def handle(self):
        if not self.proof():
            self.request.sendall(b'Error Hash!')
            return
        n, p, c = self.encrypt()
        self.request.sendall('Press 1 to get ciphertext\n'.encode())
        number = self.request.recv(512).strip().decode()
        if number == '1':
            self.request.sendall((str(n) + '\n').encode())
            self.request.sendall((str(p) + '\n').encode())
            self.request.sendall((str(c) + '\n').encode())
        else:
            self.request.sendall('Incorrect input!\n'.encode())
        return


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

if __name__ == '__main__':
    sever = socketserver.ThreadingTCPServer(('0.0.0.0', 10001), MyServer)
    ThreadedTCPServer.allow_reuse_address = True
    ThreadedTCPServer.allow_reuse_port = True
    sever.serve_forever()

我们来一点一点解析,首先看一下MyServer


random.seed(os.urandom(8)):

os.urandom(8): 这个函数调用使用操作系统的加密随机数生成器生成了8个随机字节。这些字节适合用作加密目的的安全种子。random.seed(): random.seed() 函数用于使用特定的种子值初始化Python中的随机数生成器。在您的代码中,您将由 os.urandom(8) 生成的字节作为种子传递


random_str = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(20)])

这段代码的意思是从随机的在数字小写字母大写字母中取出20个字符,组成一个字符串。



str_sha256 = hashlib.sha256(random_str.encode()).hexdigest()

这段代码将随机字符串16进制后再进行sha256加密


self.request.sendall(('SHA256(XXXX + %s):%s\n' % (random_str[4:], str_sha256)).encode())

这段代码将一定内容发送出去


self.request.sendall('Give Me XXXX:\n'.encode())
        XXXX = self.request.recv(2048).strip()

        if hashlib.sha256((XXXX + random_str[4:].encode())).hexdigest() != str_sha256:
            return False

这段很好理解,如果接受的数据满足前4位就返回True,要不然返回False。

posted @ 2024-01-05 17:36  AllFalls  阅读(24)  评论(0编辑  收藏  举报