[CISCN 2018]sm

news2024/10/7 2:22:02

目录

1.题目

3.解题

4.参考


1.题目

题目链接

from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from Crypto.Cipher import AES
import hashlib
from random import randint
def gen512num():
    order=[]
    while len(order)!=512:
        tmp=randint(1,512)
        if tmp not in order:
            order.append(tmp)
    ps=[]
    for i in range(512):
        p=getPrime(512-order[i]+10)
        pre=bin(p)[2:][0:(512-order[i])]+"1"
        ps.append(int(pre+"0"*(512-len(pre)),2))
    return ps

def run():
    choose=getPrime(512)
    ps=gen512num()
    print "gen over"
    bchoose=bin(choose)[2:]
    r=0
    bchoose = "0"*(512-len(bchoose))+bchoose
    for i in range(512):
        if bchoose[i]=='1':
            r=r^ps[i]
    flag=open("flag","r").read()

    key=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
    aes_obj = AES.new(key, AES.MODE_ECB)
    ef=aes_obj.encrypt(flag).encode("base64")

    open("r", "w").write(str(r))
    open("ef","w").write(ef)
    gg=""
    for p in ps:
        gg+=str(p)+"\n"
    open("ps","w").write(gg)

run()

附件:ef、ps、r

2.分析

from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from Crypto.Cipher import AES
import hashlib
from random import randint
def gen512num():
    order=[]
    while len(order)!=512:
        tmp=randint(1,512)
        if tmp not in order:
            order.append(tmp)
    #产生1~512的序列
    ps=[]
    for i in range(512):
        p=getPrime(512-order[i]+10)
        #根据order获得一个对应的素数
        pre=bin(p)[2:][0:(512-order[i])]+"1"
        #取素数的前512-order[i]位,加1之后就能够明确保证每一位的最后一个1的位置
        ps.append(int(pre+"0"*(512-len(pre)),2))
        #剩余位置(512-)补0
        #加到集合中去
    return ps

def run():
    choose=getPrime(512)
    #获取一个512位的随机素数来作为choose
    ps=gen512num()
    #得到对应的序列了
    print "gen over"
    #完成准备
    bchoose=bin(choose)[2:]
    #获取2进制版本数
    r=0
    bchoose = "0"*(512-len(bchoose))+bchoose
    #bchoose前面完全补充0,共512位
    for i in range(512):
        if bchoose[i]=='1':
            r=r^ps[i]
        #根据choose来确定r是否与ps[i]异或
    flag=open("flag","r").read()
    #读取flag信息

    key=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
    #choose,哪个随机素数被转化为bytes后又被转化为MD5,又被按照16进制转化为了整数,然后又转化为了bytes
    aes_obj = AES.new(key, AES.MODE_ECB)
    #获取aes加密对象
    ef=aes_obj.encrypt(flag).encode("base64")
    #ef里储存flag

    open("r", "w").write(str(r))
    open("ef","w").write(ef)
    #输出ef
    gg=""
    for p in ps:
        gg+=str(p)+"\n"
    open("ps","w").write(gg)
    #ps是被完全输出
run()

题目把ps全部给了,r是最终异或的结果,那么我们的问题就是根据r和ps把choose求出,然后利用内置的AES加密方式进行解密即可,解密方法有两种,一种是根据代码寻找突破口进行解密,一种是使用sage进行矩阵解密

3.解题

第一种:

我们注意gen512num函数:

order=[]
    while len(order)!=512:
        tmp=randint(1,512)
        if tmp not in order:
            order.append(tmp)
    #产生1~512的序列
    ps=[]
    for i in range(512):
        p=getPrime(512-order[i]+10)
        #根据order获得一个对应的素数
        pre=bin(p)[2:][0:(512-order[i])]+"1"
        #取素数的前512-order[i]位,加1之后就能够明确保证每一位的最后一个1的位置
        ps.append(int(pre+"0"*(512-len(pre)),2))
        #剩余位置(512-)补0
        #加到集合中去
    return ps

所以得到的ps必然是一个末尾0的个数分别是0~511的数组,说明ps中每一个数的最后一个1的位置都不一样

还原choose:

上面这个特性可以帮助顺利我们反推choose,举例来说,假如最后一个值1为1,则它必定是来自最后一个1的位置相同的那个数,我们将目前的数异或上对应的ps数,就能够消除这个数对前面的数的影响了,然后就能够让对choose的求解推进一位

求解代码如下:

f = open("...", 'r')
ps = f.readlines()
psn = []
pos = []
for i in ps:
    psn.append(int(i))
    t1 = int(i)
    t2 = 0
    while(t1 % 2 == 0):
        t1 >>= 1
        t2 += 1
    pos.append(512 - t2)
r = 6753785483255906709117615805253027649453460653974415214642466102672301763943358839905575042938258141827000621474498066533397472809407687579125519939754658
m = list('0' * 512)
for i in range(511, -1, -1):
    if ((r >> (511 - i)) % 2 == 1):
        r ^= psn[pos.index(i + 1)]
        #找到对应的那个进行异或的位置
        m[pos.index(i + 1)] = '1'
        #置为1
choose = int(''.join(m), 2)

然后进行AES求解:

from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from Crypto.Cipher import AES
import hashlib
from random import randint
import base64


key=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))

f2 = open("...", 'r')
c = f2.read()
c = base64.b64decode(c)
aes = AES.new(key, AES.MODE_ECB)
flag = aes.decrypt(c)
print(flag)

#b'flag{shemir_alotof_in_wctf_fun!}'

第二种,使用sage进行求解:

原问题可以看作:

A\cdot B = C

A代表choose,B代表ps中的512个数,C是代表最终给出的r,即异或结果

sage中模2意义的加能够满足异或运算的要求,自己动动笔应该能发现

故我们可以使用以下的方程来求解:

A=C\cdot B^{-1}

这个问题在sage中是十分易求的

代码如下:

#please run in sagemath

from Crypto.Util.number import *
from Crypto.Cipher import AES
import hashlib
import base64

ps = open("...",'r').readlines()
c = []
for i in ps:
    c.append(int(i.strip()))
A=[]
for i in c:
    A.append([int(x) for x in bin(i)[2:].zfill(512)])
r = 6753785483255906709117615805253027649453460653974415214642466102672301763943358839905575042938258141827000621474498066533397472809407687579125519939754658
B = [int(x) for x in bin(r)[2:].zfill(512)]
A = matrix(GF(2),A)
B = matrix(GF(2),B)
key = B*A.inverse()
li = []
for i in key[0]:
    li.append(bin(i)[2:])
choose = int(''.join(li), 2)
k=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
aes=AES.new(k,AES.MODE_ECB)
flag_enc='5eFo3ANg2fu9LRrFktWCJmVvx6RgBFzd0R8GXQ8JD78='

flag_enc=base64.b64decode(flag_enc)
flag=aes.decrypt(flag_enc)
print(flag)

4.参考

文章1

文章2

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

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

相关文章

探索小猪APP分发平台:构建高效的应用推广之路

在当今快速发展的移动互联网时代探索小猪APP分发平台:构建高效的应用推广之路,应用分发成为连接开发者与用户的关键桥梁。一个高效的分发平台可以显著提升应用的可达性和用户增长速度。 小猪app分发zixun.ppzhu.net 引言:小猪APP分发平台简介…

Spring AI 抢先体验,5 分钟玩转 Java AI 应用开发

作者:刘军 Spring AI 是 Spring 官方社区项目,旨在简化 Java AI 应用程序开发,让 Java 开发者像使用 Spring 开发普通应用一样开发 AI 应用。 Spring Cloud Alibaba AI 以 Spring AI 为基础,并在此基础上提供阿里云通义系列大模…

远程桌面报错:【出现验证错误。要求的函数不受支持】

WinR 输入【gpedit.msc】回车 依次打开 计算机配置----管理模板-----系统-----凭据分配---加密数据库修正 选择【已启用】,下拉菜单选择【易受攻击】

phpMyAdmin增加自定义IP登录教程

phpMyAdmin增加自定义IP登录教程 1、打开phpMyAdmin目录, 在此目录下是否有config.sample.inc.php文件,如果存在,那么将其改名为config.inc.php(为避免修改失误所造成的损失,强烈建议先备份config.sample.inc.php文件…

笔记85:如何计算递归算法的“时间复杂度”和空间复杂度?

先上公式: 递归算法的时间复杂度 递归次数 x 每次递归消耗的时间颗粒数递归算法的空间复杂度 递归深度 x 每次递归消耗的内存空间大小 注意: 时间复杂度指的是在执行这一段程序的时候,所花费的全部的时间,即时间的总和而空间复…

可视化大屏C位图:智慧场馆/场所图

Hello,我是大千UI工场,本期可视化大屏的焦点图(C位)分享将场馆作为焦点图的情形,欢迎友友们关注、评论,如果有订单可私信。 智慧场馆是指通过物联网、大数据、人工智能等技术手段,将传统场馆与…

Epinio:Kubernetes 的应用程序开发引擎-加CLI Demo演示

一、解决了什么问题? 开发人员如何专注于代码编写,怎么让他们可以完全忽略k8s基础设施并且和以前在本地Run一个应用一样的体验。 从源码构建一个容器程序 二、解决方案 Introduction | Epinio docs 三、Epinio 的 Kubernetes 的应用程序开发引擎 by Ra…

FFmpeg学习记录(二)—— ffmpeg多媒体文件处理

1.日志系统 常用的日志级别&#xff1a; AV_LOG_ERRORAV_LOG_WARNINGAV_LOG_INFOAV_LOG_DEBUG #include <stdio.h> #include <libavutil/log.h>int main(int argc, char *argv[]) {av_log_set_level(AV_LOG_DEBUG);av_log(NULL, AV_LOG_DEBUG, "hello worl…

怎样建设网站

建设一个网站需要经过一系列的步骤和技术&#xff0c;以下是一个简单的指导&#xff1a; 1. 确定网站目的&#xff1a;首先要确定网站的目的和目标。是为了促销产品&#xff1f;提供信息&#xff1f;还是为了社交交流&#xff1f;确定网站目的可以帮助你更好地规划网站的结构和…

【强训笔记】day8

NO.3 思路&#xff1a;相乘除以最大公约数等于最小公倍数。最小公倍数等于gcd&#xff08;a&#xff0c;a%b&#xff09;递归直到b等于0。 代码实现&#xff1a; #include <iostream> using namespace std;int gcd(int a,int b) {if(b0) return a;return gcd(b,a%b); }…

MySQL CRUD操作

前言&#x1f440;~ 上一章我们介绍了数据库的一些基础操作&#xff0c;关于如何去创建一个数据库&#xff0c;还有使用数据库&#xff0c;删 除数据库以及对表进行的一些基础操作&#xff0c;今天我们学习CRUD操作 俗称&#xff08;增删改查&#xff09; 如果各位对文章的内…

无U盘基于本地硬盘无损制作虚拟U盘(Windows、Linux系统安装启动盘)

知识点 实验环境 名称版本使用平台Win11本地硬盘格式GPT待安装镜像deepin-desktop-community-20.9-amd64.iso 文中工具下载链接&#xff1a; https://download.csdn.net/download/xzzteach/89263714 deepin-desktop-community-20.9-amd64.iso 文件结构如下&#xff1a; 在Li…

如何保证每次画出的都同一张人脸?AI绘画Stable Diffusion的Reference only教程

Ai绘画有一个很现实的问题&#xff0c;要保证每次画出的都是同一个人物的话&#xff0c;很费劲。 Midjourney就不必说了&#xff0c;人物的高度一致性一直得不到很好的解决。而在Stable Diffusion&#xff08;SD&#xff09;中&#xff0c;常用办法是通过同一个Seed值&#xf…

10G MAC层设计系列-(4)MAC TX模块

一、前言 MAC TX模块就是要将IP层传输过来的数据封装前导码、MAC地址、帧类型以及进行CRC校验&#xff0c;并与CRC值一块组成以太网帧。 二、模块设计 首先对输入的数据进行缓存&#xff0c;原因是在之后要进行封装MAC帧头&#xff0c;所以需要控制数据流的流动 FIFO_DATA_6…

Ubuntu编译安装MariaDB并进行初始化配置

Ubuntu编译安装MariaDB并进行初始化配置 1. 编译安装MariaDB2. 配置MariaDB3. Docker安装MariaDB 1. 编译安装MariaDB MariaDB官方安装文档&#xff1a;https://mariadb.com/kb/en/Build_Environment_Setup_for_Linux/    下载MariaDB源码&#xff1a;https://mariadb.org/ma…

Enum,你学会了吗?

大家后&#xff0c;我是小七。 今天给大家分享下java.lang包下面Enum类的面试点&#xff0c;本文阅读需3分钟。 Java轮子 分享程序员日常、职场、互联网项目、开发经验&#xff0c;专注技术提升 12篇原创内容 公众号 在 Java 编程中&#xff0c;枚举类型&#xff08;Enum&…

go是如何运行的?

前言 go程序的入口是main函数吗&#xff1f;诚然很多程序的入口都是main,比如java,C,C等&#xff0c;但是go由于他的运行时环境是代码&#xff0c;而不是像Java那样有自己的虚拟机&#xff0c;所以程序在运行main函数之前&#xff0c;需要做很多的准备工作&#xff0c; 该文章…

这书不错,古琴乐理实用教程(尹溧新编),有课学得通透。

通篇阅读后&#xff0c;发现这本书以古琴初习者、未系统接触过现代乐理的读者为对象&#xff0c;将复杂的古琴音乐理论简单化、通俗化。书中采用参照比较的方法、通俗易懂的语言、言简意赅的文字&#xff0c;并结合具体音乐作品将古琴研习中最主要的、最核心的理论知识进行简明…

【算法系列】哈希表

目录 哈希表总结 leetcode题目 一、两数之和 二、判定是否互为字符重排 三、存在重复元素 四、存在重复元素 II 五、字母异位词分组 六、在长度2N的数组中找出重复N次的元素 七、两个数组的交集 八、两个数组的交集 II 九、两句话中的不常见单词 哈希表总结 1.存储数…

登封授牌,花落郑州

近日&#xff0c;“大禹故里故都”授牌仪式在河南省登封市隆重举行&#xff0c;河南省社科院有关单位将匾牌授予登封市。报道称&#xff1a;至此&#xff0c;千百年来备受争议的大禹故里、故都问题&#xff0c;终于尘埃落定&#xff0c;华夏立国始祖大禹终于魂归故里。 略有微词…